Overhauled modifiers to run clientside only. BuilderChain applies rotation and mirror to blockstates.

Removed ModifierSettingsManager, ModifierSettingsMessage and capabilities.
This commit is contained in:
Christian Knaapen
2023-01-26 02:09:50 +01:00
parent a760565b66
commit ed2609f97e
31 changed files with 659 additions and 1199 deletions

View File

@@ -66,13 +66,13 @@ public class ClientEvents {
} }
} }
@SubscribeEvent // @SubscribeEvent
public static void registerShaders(RegisterShadersEvent event) throws IOException { // public static void registerShaders(RegisterShadersEvent event) throws IOException {
event.registerShader(new ShaderInstance(event.getResourceManager(), // event.registerShader(new ShaderInstance(event.getResourceManager(),
new ResourceLocation(EffortlessBuilding.MODID, "dissolve"), // new ResourceLocation(EffortlessBuilding.MODID, "dissolve"),
DefaultVertexFormat.BLOCK), // DefaultVertexFormat.BLOCK),
shaderInstance -> BuildRenderTypes.dissolveShaderInstance = shaderInstance); // shaderInstance -> BuildRenderTypes.dissolveShaderInstance = shaderInstance);
} // }
} }
@SubscribeEvent @SubscribeEvent
@@ -223,19 +223,6 @@ public class ClientEvents {
keyBindings[keybindIndex].getKey().getValue()); keyBindings[keybindIndex].getKey().getValue());
} }
public static BlockHitResult getLookingAtFar(Player player) {
Level world = player.level;
//base distance off of player ability (config)
float raytraceRange = ReachHelper.getPlacementReach(player);
Vec3 look = player.getLookAngle();
Vec3 start = new Vec3(player.getX(), player.getY() + player.getEyeHeight(), player.getZ());
Vec3 end = new Vec3(player.getX() + look.x * raytraceRange, player.getY() + player.getEyeHeight() + look.y * raytraceRange, player.getZ() + look.z * raytraceRange);
return world.clip(new ClipContext(start, end, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, player));
}
public static boolean isGameActive() { public static boolean isGameActive() {
return !(Minecraft.getInstance().level == null || Minecraft.getInstance().player == null); return !(Minecraft.getInstance().level == null || Minecraft.getInstance().player == null);
} }

View File

@@ -3,10 +3,8 @@ package nl.requios.effortlessbuilding;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.FakePlayer;
@@ -16,14 +14,10 @@ import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.level.BlockEvent; import net.minecraftforge.event.level.BlockEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.network.PacketDistributor;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.systems.UndoRedo; import nl.requios.effortlessbuilding.systems.UndoRedo;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.systems.ServerBuildState; import nl.requios.effortlessbuilding.systems.ServerBuildState;
import nl.requios.effortlessbuilding.utilities.ReachHelper; import nl.requios.effortlessbuilding.utilities.ReachHelper;
import nl.requios.effortlessbuilding.network.PacketHandler;
@EventBusSubscriber @EventBusSubscriber
public class CommonEvents { public class CommonEvents {
@@ -32,18 +26,7 @@ public class CommonEvents {
@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD) @EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD)
public static class ModBusEvents { public static class ModBusEvents {
@SubscribeEvent
public void registerCapabilities(RegisterCapabilitiesEvent event){
event.register(ModifierCapabilityManager.IModifierCapability.class);
}
}
@SubscribeEvent
public static void attachCapabilities(AttachCapabilitiesEvent<Entity> event) {
if (event.getObject() instanceof FakePlayer) return;
if (event.getObject() instanceof Player) {
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "build_modifier"), new ModifierCapabilityManager.Provider());
}
} }
@SubscribeEvent @SubscribeEvent
@@ -98,15 +81,22 @@ public class CommonEvents {
public static void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) { public static void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) {
if (event.getEntity() instanceof FakePlayer) return; if (event.getEntity() instanceof FakePlayer) return;
Player player = event.getEntity(); Player player = event.getEntity();
if (player.getCommandSenderWorld().isClientSide) {
EffortlessBuilding.log("PlayerLoggedInEvent triggers on client side");
return;
}
ServerBuildState.handleNewPlayer(player); ServerBuildState.handleNewPlayer(player);
ModifierSettingsManager.handleNewPlayer(player);
} }
@SubscribeEvent @SubscribeEvent
public static void onPlayerLoggedOut(PlayerEvent.PlayerLoggedOutEvent event) { public static void onPlayerLoggedOut(PlayerEvent.PlayerLoggedOutEvent event) {
if (event.getEntity() instanceof FakePlayer) return; if (event.getEntity() instanceof FakePlayer) return;
Player player = event.getEntity(); Player player = event.getEntity();
if (player.getCommandSenderWorld().isClientSide) return; if (player.getCommandSenderWorld().isClientSide) {
EffortlessBuilding.log("PlayerLoggedOutEvent triggers on client side");
return;
}
UndoRedo.clear(player); UndoRedo.clear(player);
} }
@@ -115,37 +105,27 @@ public class CommonEvents {
public static void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) { public static void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) {
if (event.getEntity() instanceof FakePlayer) return; if (event.getEntity() instanceof FakePlayer) return;
Player player = event.getEntity(); Player player = event.getEntity();
if (player.getCommandSenderWorld().isClientSide) {
EffortlessBuilding.log("PlayerRespawnEvent triggers on client side");
return;
}
//TODO check if this is needed
ServerBuildState.handleNewPlayer(player); ServerBuildState.handleNewPlayer(player);
ModifierSettingsManager.handleNewPlayer(player);
} }
@SubscribeEvent @SubscribeEvent
public static void onPlayerChangedDimension(PlayerEvent.PlayerChangedDimensionEvent event) { public static void onPlayerChangedDimension(PlayerEvent.PlayerChangedDimensionEvent event) {
if (event.getEntity() instanceof FakePlayer) return; if (event.getEntity() instanceof FakePlayer) return;
Player player = event.getEntity(); Player player = event.getEntity();
if (player.getCommandSenderWorld().isClientSide) return; if (player.getCommandSenderWorld().isClientSide) {
EffortlessBuilding.log("PlayerChangedDimensionEvent triggers on client side");
//Disable modifiers return;
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); }
modifierSettings.getMirrorSettings().enabled = false;
modifierSettings.getRadialMirrorSettings().enabled = false;
modifierSettings.getArraySettings().enabled = false;
ModifierSettingsManager.setModifierSettings(player, modifierSettings);
ServerBuildState.handleNewPlayer(player);
ModifierSettingsManager.handleNewPlayer(player);
//Undo redo has no dimension data, so clear it
UndoRedo.clear(player); UndoRedo.clear(player);
}
@SubscribeEvent //TODO disable build mode and modifiers?
public static void onPlayerClone(PlayerEvent.Clone event) {
if (event.getEntity() instanceof FakePlayer) return;
//Attach capabilities on death, otherwise crash
Player oldPlayer = event.getOriginal();
oldPlayer.revive();
Player newPlayer = event.getEntity();
ModifierSettingsManager.setModifierSettings(newPlayer, ModifierSettingsManager.getModifierSettings(oldPlayer));
} }
} }

View File

@@ -18,7 +18,7 @@ import java.util.*;
public class BuildModes { public class BuildModes {
private BuildModeEnum buildMode = BuildModeEnum.DISABLED; private BuildModeEnum buildMode = BuildModeEnum.DISABLED;
public void findCoordinates(BlockSet blocks, Player player, BuildModeEnum buildMode) { public void findCoordinates(BlockSet blocks, Player player) {
buildMode.instance.findCoordinates(blocks); buildMode.instance.findCoordinates(blocks);
} }

View File

@@ -1,5 +1,8 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@@ -10,95 +13,56 @@ import net.minecraft.world.phys.Vec3;
import net.minecraft.core.Vec3i; import net.minecraft.core.Vec3i;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem; import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import nl.requios.effortlessbuilding.utilities.BlockEntry;
import nl.requios.effortlessbuilding.utilities.BlockSet;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class Array { public class Array extends BaseModifier {
public static List<BlockPos> findCoordinates(Player player, BlockPos startPos) { public BlockPos offset = BlockPos.ZERO;
List<BlockPos> coordinates = new ArrayList<>(); public int count = 5;
//find arraysettings for the player @Override
ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings(); public void findCoordinates(BlockSet blocks, Player player) {
if (!isEnabled(a)) return coordinates; if (!enabled || offset.getX() == 0 && offset.getY() == 0 && offset.getZ() == 0) return;
BlockPos pos = startPos; var originalBlocks = new BlockSet(blocks);
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ()); for (BlockEntry blockEntry : originalBlocks) {
var pos = blockEntry.blockPos;
for (int i = 0; i < count; i++) {
pos = pos.offset(offset);
if (blocks.containsKey(pos)) continue;
for (int i = 0; i < a.count; i++) { var newBlockEntry = new BlockEntry(pos);
pos = pos.offset(offset); newBlockEntry.copyRotationSettingsFrom(blockEntry);
coordinates.add(pos);
}
return coordinates;
}
public static List<BlockState> findBlockStates(Player player, BlockPos startPos, BlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
List<BlockState> blockStates = new ArrayList<>();
//find arraysettings for the player that placed the block
ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings();
if (!isEnabled(a)) return blockStates;
BlockPos pos = startPos;
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
//Randomizer bag synergy
AbstractRandomizerBagItem randomizerBagItem = null;
IItemHandler bagInventory = null;
if (!itemStack.isEmpty() && itemStack.getItem() instanceof AbstractRandomizerBagItem) {
randomizerBagItem = (AbstractRandomizerBagItem) itemStack.getItem() ;
bagInventory = randomizerBagItem.getBagInventory(itemStack);
}
for (int i = 0; i < a.count; i++) {
pos = pos.offset(offset);
//Randomizer bag synergy
if (randomizerBagItem != null) {
itemStack = randomizerBagItem.pickRandomStack(bagInventory);
blockState = BuildModifiers
.getBlockStateFromItem(itemStack, player, startPos, Direction.UP, new Vec3(0, 0, 0), InteractionHand.MAIN_HAND);
} }
//blockState = blockState.getBlock().getStateForPlacement(player.world, pos, )
blockStates.add(blockState);
itemStacks.add(itemStack);
}
return blockStates;
}
public static boolean isEnabled(ArraySettings a) {
if (a == null || !a.enabled) return false;
return a.offset.getX() != 0 || a.offset.getY() != 0 || a.offset.getZ() != 0;
}
public static class ArraySettings {
public boolean enabled = false;
public BlockPos offset = BlockPos.ZERO;
public int count = 5;
public ArraySettings() {
}
public ArraySettings(boolean enabled, BlockPos offset, int count) {
this.enabled = enabled;
this.offset = offset;
this.count = count;
}
public int getReach() {
//find largest offset
int x = Math.abs(offset.getX());
int y = Math.abs(offset.getY());
int z = Math.abs(offset.getZ());
int largestOffset = Math.max(Math.max(x, y), z);
return largestOffset * count;
} }
} }
public int getReach() {
//find largest offset
int x = Math.abs(offset.getX());
int y = Math.abs(offset.getY());
int z = Math.abs(offset.getZ());
int largestOffset = Math.max(Math.max(x, y), z);
return largestOffset * count;
}
@Override
public CompoundTag serializeNBT() {
var compound = super.serializeNBT();
compound.getCompound("offset").merge(NbtUtils.writeBlockPos(offset));
compound.putInt("count", count);
return compound;
}
@Override
public void deserializeNBT(CompoundTag compound) {
super.deserializeNBT(compound);
offset = NbtUtils.readBlockPos(compound.getCompound("offset"));
count = compound.getInt("count");
}
} }

View File

@@ -0,0 +1,23 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.entity.player.Player;
import nl.requios.effortlessbuilding.utilities.BlockSet;
public abstract class BaseModifier {
public boolean enabled = false;
public abstract void findCoordinates(BlockSet blocks, Player player);
public CompoundTag serializeNBT() {
CompoundTag compound = new CompoundTag();
compound.putString("type", this.getClass().getSimpleName());
compound.putBoolean("enabled", enabled);
return compound;
}
public void deserializeNBT(CompoundTag compound) {
enabled = compound.getBoolean("enabled");
}
}

View File

@@ -1,6 +1,8 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
@@ -18,9 +20,11 @@ import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.CommonConfig; import nl.requios.effortlessbuilding.CommonConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.create.foundation.utility.NBTHelper;
import nl.requios.effortlessbuilding.systems.DelayedBlockPlacer; import nl.requios.effortlessbuilding.systems.DelayedBlockPlacer;
import nl.requios.effortlessbuilding.systems.UndoRedo; import nl.requios.effortlessbuilding.systems.UndoRedo;
import nl.requios.effortlessbuilding.utilities.BlockSet; import nl.requios.effortlessbuilding.utilities.BlockSet;
import nl.requios.effortlessbuilding.utilities.ReachHelper;
import nl.requios.effortlessbuilding.utilities.SurvivalHelper; import nl.requios.effortlessbuilding.utilities.SurvivalHelper;
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem; import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import nl.requios.effortlessbuilding.utilities.UndoRedoBlockSet; import nl.requios.effortlessbuilding.utilities.UndoRedoBlockSet;
@@ -30,201 +34,133 @@ import java.util.Collections;
import java.util.List; import java.util.List;
public class BuildModifiers { public class BuildModifiers {
private List<BaseModifier> modifierSettingsList = new ArrayList<>();
public void findCoordinates(BlockSet blocks, LocalPlayer player, ModifierSettingsManager.ModifierSettings modifierSettings) { public List<BaseModifier> getModifierSettingsList() {
return Collections.unmodifiableList(modifierSettingsList);
} }
//Called from BuildModes public void addModifierSettings(BaseModifier modifierSettings) {
public static void onBlockPlaced(Player player, List<BlockPos> startCoordinates, Direction sideHit, Vec3 hitVec, boolean placeStartPos) { modifierSettingsList.add(modifierSettings);
Level world = player.level; }
AbstractRandomizerBagItem.renewRandomness();
//Format hitvec to 0.x public void removeModifierSettings(BaseModifier modifierSettings) {
hitVec = new Vec3(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), Math.abs(hitVec.z - ((int) hitVec.z))); modifierSettingsList.remove(modifierSettings);
}
//find coordinates and blockstates public void removeModifierSettings(int index) {
List<BlockPos> coordinates = findCoordinates(player, startCoordinates); modifierSettingsList.remove(index);
List<ItemStack> itemStacks = new ArrayList<>(); }
List<BlockState> blockStates = findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks);
//check if valid blockstates public void moveUp(BaseModifier modifierSettings) {
if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return; int index = modifierSettingsList.indexOf(modifierSettings);
if (index == 0) return;
if (world.isClientSide) { Collections.swap(modifierSettingsList, index, index - 1);
}
// BlockPreviews.onBlocksPlaced(blocks); public void moveDown(BaseModifier modifierSettings) {
int index = modifierSettingsList.indexOf(modifierSettings);
if (index == modifierSettingsList.size() - 1) return;
} else { Collections.swap(modifierSettingsList, index, index + 1);
}
int delay = CommonConfig.visuals.appearAnimationLength.get() * 3 - 3; //DelayedBlockPlacer is 3 times faster than client tick? public void setFirst(BaseModifier modifierSettings) {
int index = modifierSettingsList.indexOf(modifierSettings);
if (index == 0) return;
//place blocks after delay modifierSettingsList.remove(index);
EffortlessBuilding.DELAYED_BLOCK_PLACER.placeBlocksDelayed(new DelayedBlockPlacer.Entry(world, player, coordinates, modifierSettingsList.add(0, modifierSettings);
blockStates, itemStacks, placeStartPos, delay)); }
public void setLast(BaseModifier modifierSettings) {
int index = modifierSettingsList.indexOf(modifierSettings);
if (index == modifierSettingsList.size() - 1) return;
modifierSettingsList.remove(index);
modifierSettingsList.add(modifierSettings);
}
public void clearAllModifierSettings() {
modifierSettingsList.clear();
}
public void findCoordinates(BlockSet blocks, Player player) {
for (BaseModifier modifierSettings : modifierSettingsList) {
modifierSettings.findCoordinates(blocks, player);
} }
} }
public static void onBlockBroken(Player player, List<BlockPos> startCoordinates, boolean breakStartPos) { private static final String DATA_KEY = EffortlessBuilding.MODID + ":buildModifiers";
Level world = player.level;
List<BlockPos> coordinates = findCoordinates(player, startCoordinates);
if (coordinates.isEmpty()) return;
//remember previous blockstates for undo
List<BlockState> previousBlockStates = new ArrayList<>(coordinates.size());
List<BlockState> newBlockStates = new ArrayList<>(coordinates.size());
for (BlockPos coordinate : coordinates) {
previousBlockStates.add(world.getBlockState(coordinate));
}
if (world.isClientSide) {
// BlockPreviews.onBlocksBroken(blocks);
//list of air blockstates
for (int i = 0; i < coordinates.size(); i++) {
newBlockStates.add(Blocks.AIR.defaultBlockState());
}
} else {
//If the player is going to instabreak grass or a plant, only break other instabreaking things
boolean onlyInstaBreaking = !player.isCreative() &&
world.getBlockState(startCoordinates.get(0)).getDestroySpeed(world, startCoordinates.get(0)) == 0f;
//break all those blocks
for (int i = breakStartPos ? 0 : 1; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
if (world.isLoaded(coordinate) && !world.isEmptyBlock(coordinate)) {
if (!onlyInstaBreaking || world.getBlockState(coordinate).getDestroySpeed(world, coordinate) == 0f) {
SurvivalHelper.breakBlock(world, player, coordinate, false);
}
}
}
//find actual new blockstates for undo
for (BlockPos coordinate : coordinates) {
newBlockStates.add(world.getBlockState(coordinate));
}
}
//Set first newBlockState to empty if in NORMAL mode, to make undo/redo work
//(Block isn't broken yet by the time it gets here, and broken after this)
if (!breakStartPos) newBlockStates.set(0, Blocks.AIR.defaultBlockState());
//add to undo stack
BlockPos firstPos = startCoordinates.get(0);
BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1);
UndoRedo.addUndo(player, new UndoRedoBlockSet(coordinates, previousBlockStates, newBlockStates, firstPos, secondPos));
public void save(Player player) {
var listTag = NBTHelper.writeCompoundList(modifierSettingsList, BaseModifier::serializeNBT);
player.getPersistentData().put(DATA_KEY, listTag);
} }
public static List<BlockPos> findCoordinates(Player player, List<BlockPos> posList) { //TODO call load
List<BlockPos> coordinates = new ArrayList<>(); public void load(Player player) {
//Add current blocks being placed too var listTag = player.getPersistentData().getList(DATA_KEY, Tag.TAG_COMPOUND);
coordinates.addAll(posList); modifierSettingsList = NBTHelper.readCompoundList(listTag, compoundTag -> {
var modifier = createModifier(compoundTag.getString("type"));
//Find mirror/array/radial mirror coordinates for each blockpos modifier.deserializeNBT(compoundTag);
for (BlockPos blockPos : posList) { return modifier;
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos); });
coordinates.addAll(arrayCoordinates);
coordinates.addAll(Mirror.findCoordinates(player, blockPos));
coordinates.addAll(RadialMirror.findCoordinates(player, blockPos));
//get mirror for each array coordinate
for (BlockPos coordinate : arrayCoordinates) {
coordinates.addAll(Mirror.findCoordinates(player, coordinate));
coordinates.addAll(RadialMirror.findCoordinates(player, coordinate));
}
}
return coordinates;
} }
public static List<BlockPos> findCoordinates(Player player, BlockPos blockPos) { private BaseModifier createModifier(String type) {
return findCoordinates(player, new ArrayList<>(Collections.singletonList(blockPos))); switch (type) {
case "Mirror": return new Mirror();
case "Array": return new Array();
case "RadialMirror": return new RadialMirror();
default: throw new IllegalArgumentException("Unknown modifier type: " + type);
}
} }
public static List<BlockState> findBlockStates(Player player, List<BlockPos> posList, Vec3 hitVec, Direction facing, List<ItemStack> itemStacks) { // public static String sanitize(ModifierSettingsManager.ModifierSettings modifierSettings, Player player) {
List<BlockState> blockStates = new ArrayList<>(); // int maxReach = ReachHelper.getMaxReach(player);
itemStacks.clear(); // String error = "";
//
//Get itemstack // //Mirror settings
ItemStack itemStack = player.getItemInHand(InteractionHand.MAIN_HAND); // Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (itemStack.isEmpty() || !CompatHelper.isItemBlockProxy(itemStack)) { // if (m.radius < 1) {
itemStack = player.getItemInHand(InteractionHand.OFF_HAND); // m.radius = 1;
} // error += "Mirror size has to be at least 1. This has been corrected. ";
if (itemStack.isEmpty() || !CompatHelper.isItemBlockProxy(itemStack)) { // }
return blockStates; // if (m.getReach() > maxReach) {
} // m.radius = maxReach / 2;
// error += "Mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to " + (maxReach / 2) + ". ";
//Get ItemBlock stack // }
ItemStack itemBlock = ItemStack.EMPTY; //
if (itemStack.getItem() instanceof BlockItem) itemBlock = itemStack; // //Array settings
else itemBlock = CompatHelper.getItemBlockFromStack(itemStack); // Array.ArraySettings a = modifierSettings.getArraySettings();
AbstractRandomizerBagItem.resetRandomness(); // if (a.count < 0) {
// a.count = 0;
//Add blocks in posList first // error += "Array count may not be negative. It has been reset to 0.";
for (BlockPos blockPos : posList) { // }
if (!(itemStack.getItem() instanceof BlockItem)) itemBlock = CompatHelper.getItemBlockFromStack(itemStack); //
BlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, InteractionHand.MAIN_HAND); // if (a.getReach() > maxReach) {
if (blockState == null) continue; // a.count = 0;
// error += "Array exceeds your maximum reach of " + maxReach + ". Array count has been reset to 0. ";
blockStates.add(blockState); // }
itemStacks.add(itemBlock); //
} // //Radial mirror settings
// RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
for (BlockPos blockPos : posList) { // if (r.slices < 2) {
BlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, InteractionHand.MAIN_HAND); // r.slices = 2;
if (blockState == null) continue; // error += "Radial mirror needs to have at least 2 slices. Slices has been set to 2.";
// }
List<BlockState> arrayBlockStates = Array.findBlockStates(player, blockPos, blockState, itemStack, itemStacks); //
blockStates.addAll(arrayBlockStates); // if (r.radius < 1) {
blockStates.addAll(Mirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks)); // r.radius = 1;
blockStates.addAll(RadialMirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks)); // error += "Radial mirror radius has to be at least 1. This has been corrected. ";
//add mirror for each array coordinate // }
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos); // if (r.getReach() > maxReach) {
for (int i = 0; i < arrayCoordinates.size(); i++) { // r.radius = maxReach / 2;
BlockPos coordinate = arrayCoordinates.get(i); // error += "Radial mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to " + (maxReach / 2) + ". ";
BlockState blockState1 = arrayBlockStates.get(i); // }
if (blockState1 == null) continue; //
// return error;
blockStates.addAll(Mirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks)); // }
blockStates.addAll(RadialMirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
}
//Adjust blockstates for torches and ladders etc to place on a valid side
//TODO optimize findCoordinates (done twice now)
//TODO fix mirror
// List<BlockPos> coordinates = findCoordinates(player, startPos);
// for (int i = 0; i < blockStates.size(); i++) {
// blockStates.set(i, blockStates.get(i).getBlock().getStateForPlacement(player.world, coordinates.get(i), facing,
// (float) hitVec.x, (float) hitVec.y, (float) hitVec.z, itemStacks.get(i).getMetadata(), player, EnumHand.MAIN_HAND));
// }
}
return blockStates;
}
public static BlockState getBlockStateFromItem(ItemStack itemStack, Player player, BlockPos blockPos, Direction facing, Vec3 hitVec, InteractionHand hand) {
return Block.byItem(itemStack.getItem()).getStateForPlacement(new BlockPlaceContext(new UseOnContext(player, hand, new BlockHitResult(hitVec, facing, blockPos, false))));
}
//Returns true if equal (or both null)
public static boolean compareCoordinates(List<BlockPos> coordinates1, List<BlockPos> coordinates2) {
if (coordinates1 == null && coordinates2 == null) return true;
if (coordinates1 == null || coordinates2 == null) return false;
//Check count, not actual values
if (coordinates1.size() == coordinates2.size()) {
if (coordinates1.size() == 1) {
return coordinates1.get(0).equals(coordinates2.get(0));
}
return true;
} else {
return false;
}
// return coordinates1.equals(coordinates2);
}
} }

View File

@@ -1,234 +1,113 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.properties.Half;
import net.minecraft.world.level.block.state.properties.SlabType;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import java.util.ArrayList; import nl.requios.effortlessbuilding.utilities.BlockEntry;
import java.util.List; import nl.requios.effortlessbuilding.utilities.BlockSet;
import net.minecraft.world.level.block.DirectionalBlock; public class Mirror extends BaseModifier {
import net.minecraft.world.level.block.DispenserBlock; public Vec3 position = new Vec3(0.5, 64.5, 0.5);
import net.minecraft.world.level.block.SlabBlock; public boolean mirrorX = true;
import net.minecraft.world.level.block.StairBlock; public boolean mirrorY = false;
import net.minecraft.world.level.block.state.BlockState; public boolean mirrorZ = false;
public int radius = 10;
public boolean drawLines = true;
public boolean drawPlanes = true;
public class Mirror { @Override
public void findCoordinates(BlockSet blocks, Player player) {
if (!(enabled && (mirrorX || mirrorY || mirrorZ))) return;
public static List<BlockPos> findCoordinates(Player player, BlockPos startPos) { var originalBlocks = new BlockSet(blocks);
List<BlockPos> coordinates = new ArrayList<>(); for (BlockEntry blockEntry : originalBlocks) {
if (!isWithinRange(blockEntry.blockPos)) continue;
//find mirrorsettings for the player if (mirrorX) performMirrorX(blocks, blockEntry);
MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings(); if (mirrorY) performMirrorY(blocks, blockEntry);
if (!isEnabled(m, startPos)) return coordinates; if (mirrorZ) performMirrorZ(blocks, blockEntry);
}
if (m.mirrorX) coordinateMirrorX(m, startPos, coordinates);
if (m.mirrorY) coordinateMirrorY(m, startPos, coordinates);
if (m.mirrorZ) coordinateMirrorZ(m, startPos, coordinates);
return coordinates;
} }
private static void coordinateMirrorX(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) { private void performMirrorX(BlockSet blocks, BlockEntry blockEntry) {
//find mirror position //find mirror position
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5); double x = position.x + (position.x - blockEntry.blockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ()); BlockPos newBlockPos = new BlockPos(x, blockEntry.blockPos.getY(), blockEntry.blockPos.getZ());
coordinates.add(newBlockPos);
if (m.mirrorY) coordinateMirrorY(m, newBlockPos, coordinates); if (blocks.containsKey(newBlockPos)) return;
if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, coordinates);
var newBlockEntry = new BlockEntry(newBlockPos);
newBlockEntry.copyRotationSettingsFrom(blockEntry);
newBlockEntry.mirrorX = !newBlockEntry.mirrorX;
if (mirrorY) performMirrorY(blocks, newBlockEntry);
if (mirrorZ) performMirrorZ(blocks, newBlockEntry);
} }
private static void coordinateMirrorY(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) { private void performMirrorY(BlockSet blocks, BlockEntry blockEntry) {
//find mirror position //find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5); double y = position.y + (position.y - blockEntry.blockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ()); BlockPos newBlockPos = new BlockPos(blockEntry.blockPos.getX(), y, blockEntry.blockPos.getZ());
coordinates.add(newBlockPos);
if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, coordinates); if (blocks.containsKey(newBlockPos)) return;
var newBlockEntry = new BlockEntry(newBlockPos);
newBlockEntry.copyRotationSettingsFrom(blockEntry);
newBlockEntry.mirrorY = !newBlockEntry.mirrorY;
if (mirrorZ) performMirrorZ(blocks, newBlockEntry);
} }
private static void coordinateMirrorZ(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) { private void performMirrorZ(BlockSet blocks, BlockEntry blockEntry) {
//find mirror position //find mirror position
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5); double z = position.z + (position.z - blockEntry.blockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z); BlockPos newBlockPos = new BlockPos(blockEntry.blockPos.getX(), blockEntry.blockPos.getY(), z);
coordinates.add(newBlockPos);
if (blocks.containsKey(newBlockPos)) return;
var newBlockEntry = new BlockEntry(newBlockPos);
newBlockEntry.copyRotationSettingsFrom(blockEntry);
newBlockEntry.mirrorZ = !newBlockEntry.mirrorZ;
} }
public static List<BlockState> findBlockStates(Player player, BlockPos startPos, BlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) { public boolean isWithinRange(BlockPos blockPos) {
List<BlockState> blockStates = new ArrayList<>(); return !(blockPos.getX() + 0.5 < position.x - radius) && !(blockPos.getX() + 0.5 > position.x + radius) &&
!(blockPos.getY() + 0.5 < position.y - radius) && !(blockPos.getY() + 0.5 > position.y + radius) &&
//find mirrorsettings for the player !(blockPos.getZ() + 0.5 < position.z - radius) && !(blockPos.getZ() + 0.5 > position.z + radius);
MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings();
if (!isEnabled(m, startPos)) return blockStates;
//Randomizer bag synergy
AbstractRandomizerBagItem randomizerBagItem = null;
IItemHandler bagInventory = null;
if (!itemStack.isEmpty() && itemStack.getItem() instanceof AbstractRandomizerBagItem) {
randomizerBagItem = (AbstractRandomizerBagItem) itemStack.getItem() ;
bagInventory = randomizerBagItem.getBagInventory(itemStack);
}
if (m.mirrorX)
blockStateMirrorX(player, m, startPos, blockState, bagInventory, itemStack, InteractionHand.MAIN_HAND, blockStates, itemStacks);
if (m.mirrorY)
blockStateMirrorY(player, m, startPos, blockState, bagInventory, itemStack, InteractionHand.MAIN_HAND, blockStates, itemStacks);
if (m.mirrorZ)
blockStateMirrorZ(player, m, startPos, blockState, bagInventory, itemStack, InteractionHand.MAIN_HAND, blockStates, itemStacks);
return blockStates;
} }
private static void blockStateMirrorX(Player player, MirrorSettings m, BlockPos oldBlockPos, BlockState oldBlockState, public int getReach() {
IItemHandler bagInventory, ItemStack itemStack, InteractionHand hand, List<BlockState> blockStates, List<ItemStack> itemStacks) { return radius * 2; //Change ModifierSettings#setReachUpgrade too
//find mirror position
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
//Randomizer bag synergy
if (bagInventory != null) {
itemStack = ((AbstractRandomizerBagItem)itemStack.getItem()).pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, Direction.UP, new Vec3(0, 0, 0), hand);
}
//Find blockstate
BlockState newBlockState = oldBlockState == null ? null : oldBlockState.mirror(net.minecraft.world.level.block.Mirror.FRONT_BACK);
//Store blockstate and itemstack
blockStates.add(newBlockState);
itemStacks.add(itemStack);
if (m.mirrorY)
blockStateMirrorY(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
if (m.mirrorZ)
blockStateMirrorZ(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
} }
private static void blockStateMirrorY(Player player, MirrorSettings m, BlockPos oldBlockPos, BlockState oldBlockState, @Override
IItemHandler bagInventory, ItemStack itemStack, InteractionHand hand, List<BlockState> blockStates, List<ItemStack> itemStacks) { public CompoundTag serializeNBT() {
//find mirror position var compound = super.serializeNBT();
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5); compound.putDouble("positionX", position.x);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ()); compound.putDouble("positionY", position.y);
compound.putDouble("positionZ", position.z);
//Randomizer bag synergy compound.putBoolean("mirrorX", mirrorX);
if (bagInventory != null) { compound.putBoolean("mirrorY", mirrorY);
itemStack = ((AbstractRandomizerBagItem)itemStack.getItem()).pickRandomStack(bagInventory); compound.putBoolean("mirrorZ", mirrorZ);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, Direction.UP, new Vec3(0, 0, 0), hand); compound.putInt("radius", radius);
} compound.putBoolean("drawLines", drawLines);
compound.putBoolean("drawPlanes", drawPlanes);
//Find blockstate return compound;
BlockState newBlockState = oldBlockState == null ? null : getVerticalMirror(oldBlockState);
//Store blockstate and itemstack
blockStates.add(newBlockState);
itemStacks.add(itemStack);
if (m.mirrorZ)
blockStateMirrorZ(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
} }
private static void blockStateMirrorZ(Player player, MirrorSettings m, BlockPos oldBlockPos, BlockState oldBlockState, @Override
IItemHandler bagInventory, ItemStack itemStack, InteractionHand hand, List<BlockState> blockStates, List<ItemStack> itemStacks) { public void deserializeNBT(CompoundTag compound) {
//find mirror position super.deserializeNBT(compound);
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5); position = new Vec3(compound.getDouble("positionX"), compound.getDouble("positionY"), compound.getDouble("positionZ"));
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z); mirrorX = compound.getBoolean("mirrorX");
mirrorY = compound.getBoolean("mirrorY");
//Randomizer bag synergy mirrorZ = compound.getBoolean("mirrorZ");
if (bagInventory != null) { radius = compound.getInt("radius");
itemStack = ((AbstractRandomizerBagItem)itemStack.getItem()).pickRandomStack(bagInventory); drawLines = compound.getBoolean("drawLines");
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, Direction.UP, new Vec3(0, 0, 0), hand); drawPlanes = compound.getBoolean("drawPlanes");
}
//Find blockstate
BlockState newBlockState = oldBlockState == null ? null : oldBlockState.mirror(net.minecraft.world.level.block.Mirror.LEFT_RIGHT);
//Store blockstate and itemstack
blockStates.add(newBlockState);
itemStacks.add(itemStack);
}
public static boolean isEnabled(MirrorSettings m, BlockPos startPos) {
if (m == null || !m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return false;
//within mirror distance
return !(startPos.getX() + 0.5 < m.position.x - m.radius) && !(startPos.getX() + 0.5 > m.position.x + m.radius) &&
!(startPos.getY() + 0.5 < m.position.y - m.radius) && !(startPos.getY() + 0.5 > m.position.y + m.radius) &&
!(startPos.getZ() + 0.5 < m.position.z - m.radius) && !(startPos.getZ() + 0.5 > m.position.z + m.radius);
}
private static BlockState getVerticalMirror(BlockState blockState) {
//Stairs
if (blockState.getBlock() instanceof StairBlock) {
if (blockState.getValue(StairBlock.HALF) == Half.BOTTOM) {
return blockState.setValue(StairBlock.HALF, Half.TOP);
} else {
return blockState.setValue(StairBlock.HALF, Half.BOTTOM);
}
}
//Slabs
if (blockState.getBlock() instanceof SlabBlock) {
if (blockState.getValue(SlabBlock.TYPE) == SlabType.DOUBLE) {
return blockState;
} else if (blockState.getValue(SlabBlock.TYPE) == SlabType.BOTTOM) {
return blockState.setValue(SlabBlock.TYPE, SlabType.TOP);
} else {
return blockState.setValue(SlabBlock.TYPE, SlabType.BOTTOM);
}
}
//Buttons, endrod, observer, piston
if (blockState.getBlock() instanceof DirectionalBlock) {
if (blockState.getValue(DirectionalBlock.FACING) == Direction.DOWN) {
return blockState.setValue(DirectionalBlock.FACING, Direction.UP);
} else if (blockState.getValue(DirectionalBlock.FACING) == Direction.UP) {
return blockState.setValue(DirectionalBlock.FACING, Direction.DOWN);
}
}
//Dispenser, dropper
if (blockState.getBlock() instanceof DispenserBlock) {
if (blockState.getValue(DispenserBlock.FACING) == Direction.DOWN) {
return blockState.setValue(DispenserBlock.FACING, Direction.UP);
} else if (blockState.getValue(DispenserBlock.FACING) == Direction.UP) {
return blockState.setValue(DispenserBlock.FACING, Direction.DOWN);
}
}
return blockState;
}
public static class MirrorSettings {
public boolean enabled = false;
public Vec3 position = new Vec3(0.5, 64.5, 0.5);
public boolean mirrorX = true, mirrorY = false, mirrorZ = false;
public int radius = 10;
public boolean drawLines = true, drawPlanes = true;
public MirrorSettings() {
}
public MirrorSettings(boolean mirrorEnabled, Vec3 position, boolean mirrorX, boolean mirrorY, boolean mirrorZ, int radius, boolean drawLines, boolean drawPlanes) {
this.enabled = mirrorEnabled;
this.position = position;
this.mirrorX = mirrorX;
this.mirrorY = mirrorY;
this.mirrorZ = mirrorZ;
this.radius = radius;
this.drawLines = drawLines;
this.drawPlanes = drawPlanes;
}
public int getReach() {
return radius * 2; //Change ModifierSettings#setReachUpgrade too
}
} }
} }

View File

@@ -1,166 +0,0 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.world.entity.player.Player;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.network.PacketDistributor;
import nl.requios.effortlessbuilding.CommonConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.utilities.ReachHelper;
import nl.requios.effortlessbuilding.network.ModifierSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import javax.annotation.Nonnull;
@Mod.EventBusSubscriber
public class ModifierSettingsManager {
//Retrieves the buildsettings of a player through the modifierCapability capability
//Never returns null
@Nonnull
public static ModifierSettings getModifierSettings(Player player) {
LazyOptional<ModifierCapabilityManager.IModifierCapability> modifierCapability =
player.getCapability(ModifierCapabilityManager.MODIFIER_CAPABILITY, null);
if (modifierCapability.isPresent()) {
ModifierCapabilityManager.IModifierCapability capability = modifierCapability.orElse(null);
if (capability.getModifierData() == null){
capability.setModifierData(new ModifierSettings());
}
return capability.getModifierData();
}
EffortlessBuilding.logger.warn("Player does not have modifierCapability: " + player);
//Return dummy settings
return new ModifierSettings();
}
public static void setModifierSettings(Player player, ModifierSettings modifierSettings) {
if (player == null) {
EffortlessBuilding.log("Cannot set buildsettings, player is null");
return;
}
LazyOptional<ModifierCapabilityManager.IModifierCapability> modifierCapability =
player.getCapability(ModifierCapabilityManager.MODIFIER_CAPABILITY, null);
modifierCapability.ifPresent((capability) -> {
capability.setModifierData(modifierSettings);
});
if (!modifierCapability.isPresent()) {
EffortlessBuilding.log(player, "Saving buildsettings failed.");
}
}
public static String sanitize(ModifierSettings modifierSettings, Player player) {
int maxReach = ReachHelper.getMaxReach(player);
String error = "";
//Mirror settings
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m.radius < 1) {
m.radius = 1;
error += "Mirror size has to be at least 1. This has been corrected. ";
}
if (m.getReach() > maxReach) {
m.radius = maxReach / 2;
error += "Mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to " + (maxReach / 2) + ". ";
}
//Array settings
Array.ArraySettings a = modifierSettings.getArraySettings();
if (a.count < 0) {
a.count = 0;
error += "Array count may not be negative. It has been reset to 0.";
}
if (a.getReach() > maxReach) {
a.count = 0;
error += "Array exceeds your maximum reach of " + maxReach + ". Array count has been reset to 0. ";
}
//Radial mirror settings
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
if (r.slices < 2) {
r.slices = 2;
error += "Radial mirror needs to have at least 2 slices. Slices has been set to 2.";
}
if (r.radius < 1) {
r.radius = 1;
error += "Radial mirror radius has to be at least 1. This has been corrected. ";
}
if (r.getReach() > maxReach) {
r.radius = maxReach / 2;
error += "Radial mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to " + (maxReach / 2) + ". ";
}
return error;
}
public static void handleNewPlayer(Player player) {
//Makes sure player has modifier settings (if it doesnt it will create it)
getModifierSettings(player);
//Only on server
if (!player.level.isClientSide) {
//Send to client
ModifierSettingsMessage msg = new ModifierSettingsMessage(getModifierSettings(player));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), msg);
}
}
public static class ModifierSettings {
private Mirror.MirrorSettings mirrorSettings;
private Array.ArraySettings arraySettings;
private RadialMirror.RadialMirrorSettings radialMirrorSettings;
public ModifierSettings() {
mirrorSettings = new Mirror.MirrorSettings();
arraySettings = new Array.ArraySettings();
radialMirrorSettings = new RadialMirror.RadialMirrorSettings();
}
public ModifierSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings,
RadialMirror.RadialMirrorSettings radialMirrorSettings) {
this.mirrorSettings = mirrorSettings;
this.arraySettings = arraySettings;
this.radialMirrorSettings = radialMirrorSettings;
}
public Mirror.MirrorSettings getMirrorSettings() {
if (this.mirrorSettings == null) this.mirrorSettings = new Mirror.MirrorSettings();
return this.mirrorSettings;
}
public void setMirrorSettings(Mirror.MirrorSettings mirrorSettings) {
if (mirrorSettings == null) return;
this.mirrorSettings = mirrorSettings;
}
public Array.ArraySettings getArraySettings() {
if (this.arraySettings == null) this.arraySettings = new Array.ArraySettings();
return this.arraySettings;
}
public void setArraySettings(Array.ArraySettings arraySettings) {
if (arraySettings == null) return;
this.arraySettings = arraySettings;
}
public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() {
if (this.radialMirrorSettings == null) this.radialMirrorSettings = new RadialMirror.RadialMirrorSettings();
return this.radialMirrorSettings;
}
public void setRadialMirrorSettings(RadialMirror.RadialMirrorSettings radialMirrorSettings) {
if (radialMirrorSettings == null) return;
this.radialMirrorSettings = radialMirrorSettings;
}
}
}

View File

@@ -1,5 +1,6 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@@ -12,107 +13,91 @@ import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem; import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import nl.requios.effortlessbuilding.utilities.BlockEntry;
import nl.requios.effortlessbuilding.utilities.BlockSet;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class RadialMirror { public class RadialMirror extends BaseModifier {
public static List<BlockPos> findCoordinates(Player player, BlockPos startPos) { public Vec3 position = new Vec3(0.5, 64.5, 0.5);
List<BlockPos> coordinates = new ArrayList<>(); public int slices = 4;
public boolean alternate = false;
public int radius = 20;
public boolean drawLines = true;
public boolean drawPlanes = false;
//find radial mirror settings for the player @Override
RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings(); public void findCoordinates(BlockSet blocks, Player player) {
if (!isEnabled(r, startPos)) return coordinates; if (!enabled) return;
var originalBlocks = new BlockSet(blocks);
for (BlockEntry blockEntry : originalBlocks) {
if (!isWithinRange(blockEntry.blockPos)) continue;
performRadialMirror(blocks, blockEntry);
}
}
public void performRadialMirror(BlockSet blocks, BlockEntry blockEntry) {
//get angle between slices //get angle between slices
double sliceAngle = 2 * Math.PI / r.slices; double sliceAngle = 2 * Math.PI / slices;
Vec3 startVec = new Vec3(startPos.getX() + 0.5f, startPos.getY() + 0.5f, startPos.getZ() + 0.5f); //Get start vector relative to mirror center
Vec3 relStartVec = startVec.subtract(r.position); Vec3 relStartVec = Vec3.atCenterOf(blockEntry.blockPos).subtract(position);
double startAngleToCenter = Mth.atan2(relStartVec.x, relStartVec.z); double startAngleToCenter = Mth.atan2(relStartVec.x, relStartVec.z); //between -PI and PI
//TODO change to Abs if alternative?
if (startAngleToCenter < 0) startAngleToCenter += Math.PI; if (startAngleToCenter < 0) startAngleToCenter += Math.PI;
double startAngleInSlice = startAngleToCenter % sliceAngle; double startAngleInSlice = startAngleToCenter % sliceAngle;
for (int i = 1; i < r.slices; i++) { for (int i = 1; i < slices; i++) {
double curAngle = sliceAngle * i; double curAngle = sliceAngle * i;
//alternate mirroring of slices //alternate mirroring of slices
if (r.alternate && i % 2 == 1) { boolean doAlternate = alternate && i % 2 == 1;
if (doAlternate) {
curAngle = curAngle - startAngleInSlice + (sliceAngle - startAngleInSlice); curAngle = curAngle - startAngleInSlice + (sliceAngle - startAngleInSlice);
} }
Vec3 relNewVec = relStartVec.yRot((float) curAngle); Vec3 relNewVec = relStartVec.yRot((float) curAngle);
BlockPos newBlockPos = new BlockPos(r.position.add(relNewVec)); BlockPos newBlockPos = new BlockPos(position.add(relNewVec));
if (!coordinates.contains(newBlockPos) && !newBlockPos.equals(startPos)) coordinates.add(newBlockPos);
}
return coordinates; if (blocks.containsKey(newBlockPos)) continue;
BlockEntry newBlockEntry = new BlockEntry(newBlockPos);
newBlockEntry.copyRotationSettingsFrom(blockEntry);
//rotate block
double angleToCenter = Mth.atan2(relNewVec.x, relNewVec.z); //between -PI and PI
rotateBlockEntry(newBlockEntry, angleToCenter, doAlternate);
}
} }
public static List<BlockState> findBlockStates(Player player, BlockPos startPos, BlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) { private void rotateBlockEntry(BlockEntry blockEntry, double angleToCenter, boolean alternate) {
List<BlockState> blockStates = new ArrayList<>();
List<BlockPos> coordinates = new ArrayList<>(); //to keep track of duplicates
//find radial mirror settings for the player that placed the block if (angleToCenter < -0.751 * Math.PI || angleToCenter > 0.749 * Math.PI) {
RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings(); blockEntry.rotation = blockEntry.rotation.getRotated(Rotation.CLOCKWISE_180);
if (!isEnabled(r, startPos)) return blockStates; if (alternate) {
blockEntry.mirrorZ = !blockEntry.mirrorZ;
//get angle between slices
double sliceAngle = 2 * Math.PI / r.slices;
Vec3 startVec = new Vec3(startPos.getX() + 0.5f, startPos.getY() + 0.5f, startPos.getZ() + 0.5f);
Vec3 relStartVec = startVec.subtract(r.position);
double startAngleToCenter = Mth.atan2(relStartVec.x, relStartVec.z);
double startAngleToCenterMod = startAngleToCenter < 0 ? startAngleToCenter + Math.PI : startAngleToCenter;
double startAngleInSlice = startAngleToCenterMod % sliceAngle;
//Rotate the original blockstate
blockState = rotateOriginalBlockState(player, startPos, startAngleToCenter, blockState);
//Randomizer bag synergy
AbstractRandomizerBagItem randomizerBagItem = null;
IItemHandler bagInventory = null;
if (!itemStack.isEmpty() && itemStack.getItem() instanceof AbstractRandomizerBagItem) {
randomizerBagItem = (AbstractRandomizerBagItem) itemStack.getItem() ;
bagInventory = randomizerBagItem.getBagInventory(itemStack);
}
BlockState newBlockState;
for (int i = 1; i < r.slices; i++) {
newBlockState = blockState;
double curAngle = sliceAngle * i;
//alternate mirroring of slices
if (r.alternate && i % 2 == 1) {
curAngle = curAngle - startAngleInSlice + (sliceAngle - startAngleInSlice);
} }
} else if (angleToCenter < -0.251 * Math.PI) {
Vec3 relNewVec = relStartVec.yRot((float) curAngle); blockEntry.rotation = blockEntry.rotation.getRotated(Rotation.CLOCKWISE_90);
BlockPos newBlockPos = new BlockPos(r.position.add(relNewVec)); if (alternate) {
if (coordinates.contains(newBlockPos) || newBlockPos.equals(startPos)) continue; //filter out duplicates blockEntry.mirrorX = !blockEntry.mirrorX;
coordinates.add(newBlockPos); }
} else if (angleToCenter > 0.249 * Math.PI) {
//Randomizer bag synergy blockEntry.rotation = blockEntry.rotation.getRotated(Rotation.COUNTERCLOCKWISE_90);
if (randomizerBagItem != null) { if (alternate) {
itemStack = randomizerBagItem.pickRandomStack(bagInventory); blockEntry.mirrorX = !blockEntry.mirrorX;
newBlockState = BuildModifiers }
.getBlockStateFromItem(itemStack, player, startPos, Direction.UP, new Vec3(0, 0, 0), InteractionHand.MAIN_HAND); } else {
if (alternate) {
newBlockState = rotateOriginalBlockState(player, startPos, startAngleToCenter, newBlockState); blockEntry.mirrorZ = !blockEntry.mirrorZ;
} }
//rotate
newBlockState = rotateBlockState(player, startPos, relNewVec, newBlockState, r.alternate && i % 2 == 1);
blockStates.add(newBlockState);
itemStacks.add(itemStack);
} }
return blockStates;
} }
private static BlockState rotateOriginalBlockState(Player player, BlockPos startPos, double startAngleToCenter, BlockState blockState) { private static BlockState rotateOriginalBlockState(Player player, BlockPos startPos, double startAngleToCenter, BlockState blockState) {
@@ -158,37 +143,36 @@ public class RadialMirror {
return newBlockState; return newBlockState;
} }
public static boolean isEnabled(RadialMirrorSettings r, BlockPos startPos) { public boolean isWithinRange(BlockPos startPos) {
if (r == null || !r.enabled) return false; return (new Vec3(startPos.getX() + 0.5, startPos.getY() + 0.5, startPos.getZ() + 0.5).subtract(position).lengthSqr() < radius * radius);
return !(new Vec3(startPos.getX() + 0.5, startPos.getY() + 0.5, startPos.getZ() + 0.5).subtract(r.position).lengthSqr() >
r.radius * r.radius);
} }
public static class RadialMirrorSettings { public int getReach() {
public boolean enabled = false; return radius * 2;
public Vec3 position = new Vec3(0.5, 64.5, 0.5);
public int slices = 4;
public boolean alternate = false;
public int radius = 20;
public boolean drawLines = true, drawPlanes = false;
public RadialMirrorSettings() {
}
public RadialMirrorSettings(boolean enabled, Vec3 position, int slices, boolean alternate, int radius, boolean drawLines, boolean drawPlanes) {
this.enabled = enabled;
this.position = position;
this.slices = slices;
this.alternate = alternate;
this.radius = radius;
this.drawLines = drawLines;
this.drawPlanes = drawPlanes;
}
public int getReach() {
return radius * 2;
}
} }
@Override
public CompoundTag serializeNBT() {
var compound = super.serializeNBT();
compound.putDouble("positionX", position.x);
compound.putDouble("positionY", position.y);
compound.putDouble("positionZ", position.z);
compound.putInt("slices", slices);
compound.putBoolean("alternate", alternate);
compound.putInt("radius", radius);
compound.putBoolean("drawLines", drawLines);
compound.putBoolean("drawPlanes", drawPlanes);
return compound;
}
@Override
public void deserializeNBT(CompoundTag nbt) {
super.deserializeNBT(nbt);
position = new Vec3(nbt.getDouble("positionX"), nbt.getDouble("positionY"), nbt.getDouble("positionZ"));
slices = nbt.getInt("slices");
alternate = nbt.getBoolean("alternate");
radius = nbt.getInt("radius");
drawLines = nbt.getBoolean("drawLines");
drawPlanes = nbt.getBoolean("drawPlanes");
}
} }

View File

@@ -1,180 +0,0 @@
package nl.requios.effortlessbuilding.capability;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.capabilities.*;
import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings;
@Mod.EventBusSubscriber
public class ModifierCapabilityManager {
public final static Capability<IModifierCapability> MODIFIER_CAPABILITY = CapabilityManager.get(new CapabilityToken<>(){});
// Allows for the capability to persist after death.
@SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) {
LazyOptional<IModifierCapability> original = event.getOriginal().getCapability(MODIFIER_CAPABILITY, null);
LazyOptional<IModifierCapability> clone = event.getEntity().getCapability(MODIFIER_CAPABILITY, null);
clone.ifPresent(cloneModifierCapability ->
original.ifPresent(originalModifierCapability ->
cloneModifierCapability.setModifierData(originalModifierCapability.getModifierData())));
}
public interface IModifierCapability {
ModifierSettings getModifierData();
void setModifierData(ModifierSettings modifierSettings);
}
public static class ModifierCapability implements IModifierCapability {
private ModifierSettings modifierSettings;
@Override
public ModifierSettings getModifierData() {
return modifierSettings;
}
@Override
public void setModifierData(ModifierSettings modifierSettings) {
this.modifierSettings = modifierSettings;
}
}
public static class Provider extends CapabilityProvider<Provider> implements INBTSerializable<Tag> {
private final IModifierCapability instance = new ModifierCapability();
private LazyOptional<IModifierCapability> modifierCapabilityOptional = LazyOptional.of(() -> instance);
public Provider() {
super(Provider.class);
gatherCapabilities();
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (cap == MODIFIER_CAPABILITY) return modifierCapabilityOptional.cast();
return LazyOptional.empty();
}
@Override
public void invalidateCaps() {
super.invalidateCaps();
modifierCapabilityOptional.invalidate();
}
@Override
public void reviveCaps() {
super.reviveCaps();
modifierCapabilityOptional = LazyOptional.of(() -> instance);
}
@Override
public Tag serializeNBT() {
CompoundTag compound = new CompoundTag();
ModifierSettings modifierSettings = instance.getModifierData();
if (modifierSettings == null) modifierSettings = new ModifierSettings();
//MIRROR
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m == null) m = new Mirror.MirrorSettings();
compound.putBoolean("mirrorEnabled", m.enabled);
compound.putDouble("mirrorPosX", m.position.x);
compound.putDouble("mirrorPosY", m.position.y);
compound.putDouble("mirrorPosZ", m.position.z);
compound.putBoolean("mirrorX", m.mirrorX);
compound.putBoolean("mirrorY", m.mirrorY);
compound.putBoolean("mirrorZ", m.mirrorZ);
compound.putInt("mirrorRadius", m.radius);
compound.putBoolean("mirrorDrawLines", m.drawLines);
compound.putBoolean("mirrorDrawPlanes", m.drawPlanes);
//ARRAY
Array.ArraySettings a = modifierSettings.getArraySettings();
if (a == null) a = new Array.ArraySettings();
compound.putBoolean("arrayEnabled", a.enabled);
compound.putInt("arrayOffsetX", a.offset.getX());
compound.putInt("arrayOffsetY", a.offset.getY());
compound.putInt("arrayOffsetZ", a.offset.getZ());
compound.putInt("arrayCount", a.count);
//compound.putBoolean("quickReplace", buildSettings.doQuickReplace()); dont save quickreplace
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
if (r == null) r = new RadialMirror.RadialMirrorSettings();
compound.putBoolean("radialMirrorEnabled", r.enabled);
compound.putDouble("radialMirrorPosX", r.position.x);
compound.putDouble("radialMirrorPosY", r.position.y);
compound.putDouble("radialMirrorPosZ", r.position.z);
compound.putInt("radialMirrorSlices", r.slices);
compound.putBoolean("radialMirrorAlternate", r.alternate);
compound.putInt("radialMirrorRadius", r.radius);
compound.putBoolean("radialMirrorDrawLines", r.drawLines);
compound.putBoolean("radialMirrorDrawPlanes", r.drawPlanes);
return compound;
}
@Override
public void deserializeNBT(Tag nbt) {
CompoundTag compound = (CompoundTag) nbt;
//MIRROR
boolean mirrorEnabled = compound.getBoolean("mirrorEnabled");
Vec3 mirrorPosition = new Vec3(
compound.getDouble("mirrorPosX"),
compound.getDouble("mirrorPosY"),
compound.getDouble("mirrorPosZ"));
boolean mirrorX = compound.getBoolean("mirrorX");
boolean mirrorY = compound.getBoolean("mirrorY");
boolean mirrorZ = compound.getBoolean("mirrorZ");
int mirrorRadius = compound.getInt("mirrorRadius");
boolean mirrorDrawLines = compound.getBoolean("mirrorDrawLines");
boolean mirrorDrawPlanes = compound.getBoolean("mirrorDrawPlanes");
Mirror.MirrorSettings mirrorSettings = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius, mirrorDrawLines, mirrorDrawPlanes);
//ARRAY
boolean arrayEnabled = compound.getBoolean("arrayEnabled");
BlockPos arrayOffset = new BlockPos(
compound.getInt("arrayOffsetX"),
compound.getInt("arrayOffsetY"),
compound.getInt("arrayOffsetZ"));
int arrayCount = compound.getInt("arrayCount");
Array.ArraySettings arraySettings = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
//RADIAL MIRROR
boolean radialMirrorEnabled = compound.getBoolean("radialMirrorEnabled");
Vec3 radialMirrorPosition = new Vec3(
compound.getDouble("radialMirrorPosX"),
compound.getDouble("radialMirrorPosY"),
compound.getDouble("radialMirrorPosZ"));
int radialMirrorSlices = compound.getInt("radialMirrorSlices");
boolean radialMirrorAlternate = compound.getBoolean("radialMirrorAlternate");
int radialMirrorRadius = compound.getInt("radialMirrorRadius");
boolean radialMirrorDrawLines = compound.getBoolean("radialMirrorDrawLines");
boolean radialMirrorDrawPlanes = compound.getBoolean("radialMirrorDrawPlanes");
RadialMirror.RadialMirrorSettings radialMirrorSettings = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition,
radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
ModifierSettings modifierSettings = new ModifierSettings(mirrorSettings, arraySettings, radialMirrorSettings);
instance.setModifierData(modifierSettings);
}
}
}

View File

@@ -127,10 +127,10 @@ public abstract class AbstractSimiContainerScreen<T extends AbstractContainerMen
return leftPos - windowXOffset + (imageWidth - textureWidth) / 2; return leftPos - windowXOffset + (imageWidth - textureWidth) / 2;
} }
public void renderPlayerInventory(PoseStack ms, int x, int y) { // public void renderPlayerInventory(PoseStack ms, int x, int y) {
AllGuiTextures.PLAYER_INVENTORY.render(ms, x, y, this); // AllGuiTextures.PLAYER_INVENTORY.render(ms, x, y, this);
font.draw(ms, playerInventoryTitle, x + 8, y + 6, 0x404040); // font.draw(ms, playerInventoryTitle, x + 8, y + 6, 0x404040);
} // }
@Override @Override
public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) { public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) {

View File

@@ -10,9 +10,7 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Array; import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.gui.elements.GuiCheckBoxFixed; import nl.requios.effortlessbuilding.gui.elements.GuiCheckBoxFixed;
import nl.requios.effortlessbuilding.gui.elements.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiNumberField; import nl.requios.effortlessbuilding.gui.elements.GuiNumberField;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane; import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.utilities.ReachHelper; import nl.requios.effortlessbuilding.utilities.ReachHelper;
@@ -21,14 +19,14 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class ArraySettingsGui extends GuiCollapsibleScrollEntry { public class ArrayPanel extends BaseModifierPanel {
protected List<GuiNumberField> arrayNumberFieldList = new ArrayList<>(); protected List<GuiNumberField> arrayNumberFieldList = new ArrayList<>();
private GuiCheckBoxFixed buttonArrayEnabled; private GuiCheckBoxFixed buttonArrayEnabled;
private GuiNumberField textArrayOffsetX, textArrayOffsetY, textArrayOffsetZ, textArrayCount; private GuiNumberField textArrayOffsetX, textArrayOffsetY, textArrayOffsetZ, textArrayCount;
public ArraySettingsGui(GuiScrollPane scrollPane) { public ArrayPanel(GuiScrollPane scrollPane) {
super(scrollPane); super(scrollPane);
} }

View File

@@ -0,0 +1,14 @@
package nl.requios.effortlessbuilding.gui.buildmodifier;
import nl.requios.effortlessbuilding.buildmodifier.BaseModifier;
import nl.requios.effortlessbuilding.gui.elements.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
public abstract class BaseModifierPanel extends GuiCollapsibleScrollEntry {
public BaseModifierPanel(GuiScrollPane scrollPane) {
super(scrollPane);
}
public abstract void setModifier(BaseModifier modifier);
}

View File

@@ -12,7 +12,6 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Mirror; import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.gui.elements.*; import nl.requios.effortlessbuilding.gui.elements.*;
import nl.requios.effortlessbuilding.utilities.ReachHelper; import nl.requios.effortlessbuilding.utilities.ReachHelper;
@@ -22,7 +21,7 @@ import java.util.List;
@SuppressWarnings("Duplicates") @SuppressWarnings("Duplicates")
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class MirrorSettingsGui extends GuiCollapsibleScrollEntry { public class MirrorPanel extends BaseModifierPanel {
protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png"); protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
@@ -35,7 +34,7 @@ public class MirrorSettingsGui extends GuiCollapsibleScrollEntry {
private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines; private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines;
private boolean drawPlanes, drawLines, toggleOdd; private boolean drawPlanes, drawLines, toggleOdd;
public MirrorSettingsGui(GuiScrollPane scrollPane) { public MirrorPanel(GuiScrollPane scrollPane) {
super(scrollPane); super(scrollPane);
} }

View File

@@ -9,25 +9,32 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.ClientEvents; import nl.requios.effortlessbuilding.ClientEvents;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.EffortlessBuildingClient;
import nl.requios.effortlessbuilding.buildmodifier.Array; import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.BaseModifier;
import nl.requios.effortlessbuilding.buildmodifier.Mirror; import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror; import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import nl.requios.effortlessbuilding.gui.elements.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane; import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.network.ModifierSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler; import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class ModifierSettingsGui extends Screen { public class ModifierSettingsGui extends Screen {
private final Map<Class, Class> modifierPanelMap = new HashMap<Class, Class>() {{
put(Mirror.class, MirrorPanel.class);
put(Array.class, ArrayPanel.class);
put(RadialMirror.class, RadialMirrorPanel.class);
}};
private GuiScrollPane scrollPane; private GuiScrollPane scrollPane;
private List<BaseModifierPanel> modifierPanels;
private Button buttonClose; private Button buttonClose;
private MirrorSettingsGui mirrorSettingsGui;
private ArraySettingsGui arraySettingsGui;
private RadialMirrorSettingsGui radialMirrorSettingsGui;
public ModifierSettingsGui() { public ModifierSettingsGui() {
super(Component.translatable("effortlessbuilding.screen.modifier_settings")); super(Component.translatable("effortlessbuilding.screen.modifier_settings"));
} }
@@ -38,14 +45,7 @@ public class ModifierSettingsGui extends Screen {
scrollPane = new GuiScrollPane(this, font, 8, height - 30); scrollPane = new GuiScrollPane(this, font, 8, height - 30);
mirrorSettingsGui = new MirrorSettingsGui(scrollPane); initScrollEntries();
scrollPane.AddListEntry(mirrorSettingsGui);
arraySettingsGui = new ArraySettingsGui(scrollPane);
scrollPane.AddListEntry(arraySettingsGui);
radialMirrorSettingsGui = new RadialMirrorSettingsGui(scrollPane);
scrollPane.AddListEntry(radialMirrorSettingsGui);
scrollPane.init(renderables); scrollPane.init(renderables);
@@ -57,6 +57,27 @@ public class ModifierSettingsGui extends Screen {
addRenderableOnly(buttonClose); addRenderableOnly(buttonClose);
} }
private void initScrollEntries() {
var modifierSettingsList = EffortlessBuildingClient.BUILD_MODIFIERS.getModifierSettingsList();
for (BaseModifier modifier : modifierSettingsList) {
BaseModifierPanel modifierPanel = createModifierPanel(modifier.getClass().getSimpleName());
if (modifierPanel != null) {
modifierPanel.setModifier(modifier);
scrollPane.AddListEntry(modifierPanel);
}
}
}
private BaseModifierPanel createModifierPanel(String type) {
switch (type) {
case "Mirror": return new MirrorPanel(scrollPane);
case "Array": return new ArrayPanel(scrollPane);
case "RadialMirror": return new RadialMirrorPanel(scrollPane);
default: return null;
}
}
@Override @Override
//Process general logic, i.e. hide buttons //Process general logic, i.e. hide buttons
public void tick() { public void tick() {
@@ -131,9 +152,9 @@ public class ModifierSettingsGui extends Screen {
scrollPane.onGuiClosed(); scrollPane.onGuiClosed();
//save everything //save everything
Mirror.MirrorSettings m = mirrorSettingsGui.getMirrorSettings(); Mirror.MirrorSettings m = mirrorPanel.getMirrorSettings();
Array.ArraySettings a = arraySettingsGui.getArraySettings(); Array.ArraySettings a = arrayPanel.getArraySettings();
RadialMirror.RadialMirrorSettings r = radialMirrorSettingsGui.getRadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = radialMirrorPanel.getRadialMirrorSettings();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(minecraft.player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(minecraft.player);
if (modifierSettings == null) modifierSettings = new ModifierSettingsManager.ModifierSettings(); if (modifierSettings == null) modifierSettings = new ModifierSettingsManager.ModifierSettings();

View File

@@ -11,7 +11,6 @@ import net.minecraft.ChatFormatting;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror; import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import nl.requios.effortlessbuilding.gui.elements.*; import nl.requios.effortlessbuilding.gui.elements.*;
import nl.requios.effortlessbuilding.utilities.ReachHelper; import nl.requios.effortlessbuilding.utilities.ReachHelper;
@@ -22,7 +21,7 @@ import java.util.List;
@SuppressWarnings("Duplicates") @SuppressWarnings("Duplicates")
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry { public class RadialMirrorPanel extends BaseModifierPanel {
protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png"); protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
@@ -35,7 +34,7 @@ public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry {
private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines; private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines;
private boolean drawPlanes, drawLines, toggleOdd; private boolean drawPlanes, drawLines, toggleOdd;
public RadialMirrorSettingsGui(GuiScrollPane scrollPane) { public RadialMirrorPanel(GuiScrollPane scrollPane) {
super(scrollPane); super(scrollPane);
} }

View File

@@ -24,7 +24,6 @@ import net.minecraftforge.network.NetworkHooks;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.systems.ServerBuildState; import nl.requios.effortlessbuilding.systems.ServerBuildState;
import nl.requios.effortlessbuilding.capability.ItemHandlerCapabilityProvider;
import nl.requios.effortlessbuilding.utilities.SurvivalHelper; import nl.requios.effortlessbuilding.utilities.SurvivalHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;

View File

@@ -1,4 +1,4 @@
package nl.requios.effortlessbuilding.capability; package nl.requios.effortlessbuilding.item;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;

View File

@@ -11,7 +11,6 @@ import net.minecraft.ChatFormatting;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.CommonConfig; import nl.requios.effortlessbuilding.CommonConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.utilities.ReachHelper; import nl.requios.effortlessbuilding.utilities.ReachHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;

View File

@@ -11,7 +11,6 @@ import net.minecraft.ChatFormatting;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.CommonConfig; import nl.requios.effortlessbuilding.CommonConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.utilities.ReachHelper; import nl.requios.effortlessbuilding.utilities.ReachHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;

View File

@@ -11,7 +11,6 @@ import net.minecraft.ChatFormatting;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.CommonConfig; import nl.requios.effortlessbuilding.CommonConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.utilities.ReachHelper; import nl.requios.effortlessbuilding.utilities.ReachHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;

View File

@@ -1,132 +0,0 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.world.entity.player.Player;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import java.util.function.Supplier;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings;
/**
* Shares modifier settings (see ModifierSettingsManager) between server and client
*/
public class ModifierSettingsMessage {
private ModifierSettings modifierSettings;
public ModifierSettingsMessage() {
}
public ModifierSettingsMessage(ModifierSettings modifierSettings) {
this.modifierSettings = modifierSettings;
}
public static void encode(ModifierSettingsMessage message, FriendlyByteBuf buf) {
//MIRROR
Mirror.MirrorSettings m = message.modifierSettings.getMirrorSettings();
buf.writeBoolean(m != null);
if (m != null) {
buf.writeBoolean(m.enabled);
buf.writeDouble(m.position.x);
buf.writeDouble(m.position.y);
buf.writeDouble(m.position.z);
buf.writeBoolean(m.mirrorX);
buf.writeBoolean(m.mirrorY);
buf.writeBoolean(m.mirrorZ);
buf.writeInt(m.radius);
buf.writeBoolean(m.drawLines);
buf.writeBoolean(m.drawPlanes);
}
//ARRAY
Array.ArraySettings a = message.modifierSettings.getArraySettings();
buf.writeBoolean(a != null);
if (a != null) {
buf.writeBoolean(a.enabled);
buf.writeInt(a.offset.getX());
buf.writeInt(a.offset.getY());
buf.writeInt(a.offset.getZ());
buf.writeInt(a.count);
}
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = message.modifierSettings.getRadialMirrorSettings();
buf.writeBoolean(r != null);
if (r != null) {
buf.writeBoolean(r.enabled);
buf.writeDouble(r.position.x);
buf.writeDouble(r.position.y);
buf.writeDouble(r.position.z);
buf.writeInt(r.slices);
buf.writeBoolean(r.alternate);
buf.writeInt(r.radius);
buf.writeBoolean(r.drawLines);
buf.writeBoolean(r.drawPlanes);
}
}
public static ModifierSettingsMessage decode(FriendlyByteBuf buf) {
//MIRROR
Mirror.MirrorSettings m = new Mirror.MirrorSettings();
if (buf.readBoolean()) {
boolean mirrorEnabled = buf.readBoolean();
Vec3 mirrorPosition = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble());
boolean mirrorX = buf.readBoolean();
boolean mirrorY = buf.readBoolean();
boolean mirrorZ = buf.readBoolean();
int mirrorRadius = buf.readInt();
boolean mirrorDrawLines = buf.readBoolean();
boolean mirrorDrawPlanes = buf.readBoolean();
m = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius,
mirrorDrawLines, mirrorDrawPlanes);
}
//ARRAY
Array.ArraySettings a = new Array.ArraySettings();
if (buf.readBoolean()) {
boolean arrayEnabled = buf.readBoolean();
BlockPos arrayOffset = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
int arrayCount = buf.readInt();
a = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
}
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = new RadialMirror.RadialMirrorSettings();
if (buf.readBoolean()) {
boolean radialMirrorEnabled = buf.readBoolean();
Vec3 radialMirrorPosition = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble());
int radialMirrorSlices = buf.readInt();
boolean radialMirrorAlternate = buf.readBoolean();
int radialMirrorRadius = buf.readInt();
boolean radialMirrorDrawLines = buf.readBoolean();
boolean radialMirrorDrawPlanes = buf.readBoolean();
r = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition, radialMirrorSlices,
radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
}
ModifierSettings modifierSettings = new ModifierSettings(m, a, r);
return new ModifierSettingsMessage(modifierSettings);
}
public static class Handler {
public static void handle(ModifierSettingsMessage message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
// Sanitize
ModifierSettingsManager.sanitize(message.modifierSettings, player);
ModifierSettingsManager.setModifierSettings(player, message.modifierSettings);
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -24,8 +24,6 @@ public class PacketHandler {
IsUsingBuildModePacket.Handler::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER)); IsUsingBuildModePacket.Handler::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER));
INSTANCE.registerMessage(id++, IsQuickReplacingPacket.class, IsQuickReplacingPacket::encode, IsQuickReplacingPacket::decode, INSTANCE.registerMessage(id++, IsQuickReplacingPacket.class, IsQuickReplacingPacket::encode, IsQuickReplacingPacket::decode,
IsQuickReplacingPacket.Handler::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER)); IsQuickReplacingPacket.Handler::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER));
INSTANCE.registerMessage(id++, ModifierSettingsMessage.class, ModifierSettingsMessage::encode, ModifierSettingsMessage::decode,
ModifierSettingsMessage.Handler::handle);
INSTANCE.registerMessage(id++, ServerPlaceBlocksPacket.class, ServerPlaceBlocksPacket::encode, ServerPlaceBlocksPacket::decode, INSTANCE.registerMessage(id++, ServerPlaceBlocksPacket.class, ServerPlaceBlocksPacket::encode, ServerPlaceBlocksPacket::decode,
ServerPlaceBlocksPacket.Handler::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER)); ServerPlaceBlocksPacket.Handler::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER));
INSTANCE.registerMessage(id++, ServerBreakBlocksPacket.class, ServerBreakBlocksPacket::encode, ServerBreakBlocksPacket::decode, INSTANCE.registerMessage(id++, ServerBreakBlocksPacket.class, ServerBreakBlocksPacket::encode, ServerBreakBlocksPacket::decode,

View File

@@ -8,7 +8,6 @@ import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.buildmodifier.Mirror; import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror; import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import java.awt.*; import java.awt.*;

View File

@@ -17,7 +17,6 @@ import net.minecraftforge.client.event.RenderLevelStageEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import nl.requios.effortlessbuilding.EffortlessBuildingClient; import nl.requios.effortlessbuilding.EffortlessBuildingClient;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.systems.BuilderChain; import nl.requios.effortlessbuilding.systems.BuilderChain;
/*** /***

View File

@@ -18,9 +18,9 @@ import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.ClientEvents; import nl.requios.effortlessbuilding.ClientEvents;
import nl.requios.effortlessbuilding.CommonConfig;
import nl.requios.effortlessbuilding.EffortlessBuildingClient; import nl.requios.effortlessbuilding.EffortlessBuildingClient;
import nl.requios.effortlessbuilding.buildmode.BuildModeEnum; import nl.requios.effortlessbuilding.buildmode.BuildModeEnum;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem; import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import nl.requios.effortlessbuilding.network.PacketHandler; import nl.requios.effortlessbuilding.network.PacketHandler;
@@ -42,6 +42,8 @@ public class BuilderChain {
private BlockEntry startPosForPlacing; private BlockEntry startPosForPlacing;
private BlockPos startPosForBreaking; private BlockPos startPosForBreaking;
private BlockHitResult lookingAtNear; private BlockHitResult lookingAtNear;
//Can be near or far depending on abilities
private BlockHitResult lookingAt;
public enum BuildingState { public enum BuildingState {
IDLE, IDLE,
@@ -82,6 +84,10 @@ public class BuilderChain {
EffortlessBuildingClient.BLOCK_PREVIEWS.onBlocksPlaced(blocks); EffortlessBuildingClient.BLOCK_PREVIEWS.onBlocksPlaced(blocks);
BlockUtilities.playSoundIfFurtherThanNormal(player, blocks.getLastBlockEntry(), false); BlockUtilities.playSoundIfFurtherThanNormal(player, blocks.getLastBlockEntry(), false);
player.swing(InteractionHand.MAIN_HAND); player.swing(InteractionHand.MAIN_HAND);
//TODO place blocks delayed on server, calculate what tick they should be placed on
int delay = CommonConfig.visuals.appearAnimationLength.get() * 3 - 3; //DelayedBlockPlacer is 3 times faster than client tick?
PacketHandler.INSTANCE.sendToServer(new ServerPlaceBlocksPacket(blocks)); PacketHandler.INSTANCE.sendToServer(new ServerPlaceBlocksPacket(blocks));
} }
} }
@@ -127,6 +133,7 @@ public class BuilderChain {
startPosForPlacing = null; startPosForPlacing = null;
startPosForBreaking = null; startPosForBreaking = null;
lookingAtNear = null; lookingAtNear = null;
lookingAt = null;
var mc = Minecraft.getInstance(); var mc = Minecraft.getInstance();
var player = mc.player; var player = mc.player;
@@ -136,7 +143,6 @@ public class BuilderChain {
if (abilitiesState == AbilitiesState.NONE) return; if (abilitiesState == AbilitiesState.NONE) return;
var buildMode = EffortlessBuildingClient.BUILD_MODES.getBuildMode(); var buildMode = EffortlessBuildingClient.BUILD_MODES.getBuildMode();
var modifierSettings = ModifierSettingsManager.getModifierSettings(player);
if (buildingState == BuildingState.IDLE) { if (buildingState == BuildingState.IDLE) {
//Find start position //Find start position
@@ -150,8 +156,8 @@ public class BuilderChain {
} }
} }
EffortlessBuildingClient.BUILD_MODES.findCoordinates(blocks, player, buildMode); EffortlessBuildingClient.BUILD_MODES.findCoordinates(blocks, player);
EffortlessBuildingClient.BUILD_MODIFIERS.findCoordinates(blocks, player, modifierSettings); EffortlessBuildingClient.BUILD_MODIFIERS.findCoordinates(blocks, player);
BuilderFilter.filterOnCoordinates(blocks, player); BuilderFilter.filterOnCoordinates(blocks, player);
if (buildMode == BuildModeEnum.DISABLED && blocks.size() <= 1) { if (buildMode == BuildModeEnum.DISABLED && blocks.size() <= 1) {
@@ -196,40 +202,14 @@ public class BuilderChain {
return AbilitiesState.CAN_PLACE_AND_BREAK; return AbilitiesState.CAN_PLACE_AND_BREAK;
} }
private void onBlocksChanged(Player player) {
//Renew randomness of randomizer bag
AbstractRandomizerBagItem.renewRandomness();
//Play sound (max once every tick)
if (blocks.size() > 1 && soundTime < ClientEvents.ticksInGame) {
soundTime = ClientEvents.ticksInGame;
if (blocks.getLastBlockEntry() != null && blocks.getLastBlockEntry().newBlockState != null) {
var lastBlockState = blocks.getLastBlockEntry().newBlockState;
SoundType soundType = lastBlockState.getBlock().getSoundType(lastBlockState, player.level, blocks.lastPos, player);
SoundEvent soundEvent = buildingState == BuildingState.BREAKING ? soundType.getBreakSound() : soundType.getPlaceSound();
player.level.playSound(player, player.blockPosition(), soundEvent, SoundSource.BLOCKS, 0.3f, 0.8f);
}
}
}
public void cancel() {
if (buildingState == BuildingState.IDLE) return;
buildingState = BuildingState.IDLE;
EffortlessBuildingClient.BUILD_MODES.onCancel();
Minecraft.getInstance().player.playSound(SoundEvents.UI_TOAST_OUT, 4, 1);
}
private BlockEntry findStartPosition(Player player, BuildModeEnum buildMode) { private BlockEntry findStartPosition(Player player, BuildModeEnum buildMode) {
//Determine if we should look far or nearby //Determine if we should look far or nearby
boolean shouldLookAtNear = buildMode == BuildModeEnum.DISABLED; boolean shouldLookAtNear = buildMode == BuildModeEnum.DISABLED;
BlockHitResult lookingAt;
if (shouldLookAtNear) { if (shouldLookAtNear) {
lookingAt = lookingAtNear; lookingAt = lookingAtNear;
} else { } else {
lookingAt = ClientEvents.getLookingAtFar(player); lookingAt = BlockUtilities.getLookingAtFar(player);
} }
if (lookingAt == null || lookingAt.getType() == HitResult.Type.MISS) return null; if (lookingAt == null || lookingAt.getType() == HitResult.Type.MISS) return null;
@@ -291,10 +271,14 @@ public class BuilderChain {
private void findNewBlockStates(Player player, ItemStack itemStack) { private void findNewBlockStates(Player player, ItemStack itemStack) {
if (buildingState == BuildingState.BREAKING) return; if (buildingState == BuildingState.BREAKING) return;
var originalDirection = player.getDirection();
var clickedFace = lookingAt.getDirection();
Vec3 relativeHitVec = lookingAt.getLocation().subtract(Vec3.atLowerCornerOf(lookingAt.getBlockPos()));
if (itemStack.getItem() instanceof BlockItem) { if (itemStack.getItem() instanceof BlockItem) {
for (BlockEntry blockEntry : blocks) { for (BlockEntry blockEntry : blocks) {
blockEntry.newBlockState = BlockUtilities.getBlockState(player, InteractionHand.MAIN_HAND, itemStack, blockEntry); blockEntry.setItemStackAndFindNewBlockState(itemStack, player.level, originalDirection, clickedFace, relativeHitVec);
} }
} else if (CompatHelper.isItemBlockProxy(itemStack, false)) { } else if (CompatHelper.isItemBlockProxy(itemStack, false)) {
@@ -303,11 +287,36 @@ public class BuilderChain {
for (BlockEntry blockEntry : blocks) { for (BlockEntry blockEntry : blocks) {
ItemStack itemBlockStack = CompatHelper.getItemBlockFromStack(itemStack); ItemStack itemBlockStack = CompatHelper.getItemBlockFromStack(itemStack);
if (itemBlockStack == null || itemBlockStack.isEmpty()) continue; if (itemBlockStack == null || itemBlockStack.isEmpty()) continue;
blockEntry.newBlockState = BlockUtilities.getBlockState(player, InteractionHand.MAIN_HAND, itemBlockStack, blockEntry); blockEntry.setItemStackAndFindNewBlockState(itemBlockStack, player.level, originalDirection, clickedFace, relativeHitVec);
} }
} }
} }
private void onBlocksChanged(Player player) {
//Renew randomness of randomizer bag
AbstractRandomizerBagItem.renewRandomness();
//Play sound (max once every tick)
if (blocks.size() > 1 && soundTime < ClientEvents.ticksInGame) {
soundTime = ClientEvents.ticksInGame;
if (blocks.getLastBlockEntry() != null && blocks.getLastBlockEntry().newBlockState != null) {
var lastBlockState = blocks.getLastBlockEntry().newBlockState;
SoundType soundType = lastBlockState.getBlock().getSoundType(lastBlockState, player.level, blocks.lastPos, player);
SoundEvent soundEvent = buildingState == BuildingState.BREAKING ? soundType.getBreakSound() : soundType.getPlaceSound();
player.level.playSound(player, player.blockPosition(), soundEvent, SoundSource.BLOCKS, 0.3f, 0.8f);
}
}
}
public void cancel() {
if (buildingState == BuildingState.IDLE) return;
buildingState = BuildingState.IDLE;
EffortlessBuildingClient.BUILD_MODES.onCancel();
Minecraft.getInstance().player.playSound(SoundEvents.UI_TOAST_OUT, 4, 1);
}
public BlockSet getBlocks() { public BlockSet getBlocks() {
return blocks; return blocks;
} }

View File

@@ -1,5 +1,6 @@
package nl.requios.effortlessbuilding.systems; package nl.requios.effortlessbuilding.systems;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
@@ -7,6 +8,7 @@ import nl.requios.effortlessbuilding.EffortlessBuildingClient;
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.utilities.BlockSet; import nl.requios.effortlessbuilding.utilities.BlockSet;
import nl.requios.effortlessbuilding.utilities.PlaceChecker; import nl.requios.effortlessbuilding.utilities.PlaceChecker;
import nl.requios.effortlessbuilding.utilities.SurvivalHelper;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class BuilderFilter { public class BuilderFilter {
@@ -41,6 +43,21 @@ public class BuilderFilter {
if (remove) iter.remove(); if (remove) iter.remove();
} }
//If the player is going to instabreak grass or a plant, only break other instabreaking things
// boolean onlyInstaBreaking = !player.isCreative() &&
// world.getBlockState(startCoordinates.get(0)).getDestroySpeed(world, startCoordinates.get(0)) == 0f;
//
// //break all those blocks
// for (int i = breakStartPos ? 0 : 1; i < coordinates.size(); i++) {
// BlockPos coordinate = coordinates.get(i);
// if (world.isLoaded(coordinate) && !world.isEmptyBlock(coordinate)) {
// if (!onlyInstaBreaking || world.getBlockState(coordinate).getDestroySpeed(world, coordinate) == 0f) {
// SurvivalHelper.breakBlock(world, player, coordinate, false);
// }
// }
// }
} }
public static void filterOnNewBlockStates(BlockSet blocks, Player player) { public static void filterOnNewBlockStates(BlockSet blocks, Player player) {

View File

@@ -1,19 +1,23 @@
package nl.requios.effortlessbuilding.utilities; package nl.requios.effortlessbuilding.utilities;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
import java.util.BitSet; //Common
public class BlockEntry { public class BlockEntry {
public final BlockPos blockPos; public final BlockPos blockPos;
public boolean mirrorX; public boolean mirrorX;
public boolean mirrorY; public boolean mirrorY;
public boolean mirrorZ; public boolean mirrorZ;
//Horizontal rotation
public Rotation rotation; public Rotation rotation;
//BlockState that is currently in the world //BlockState that is currently in the world
public BlockState existingBlockState; public BlockState existingBlockState;
@@ -24,22 +28,29 @@ public class BlockEntry {
this.blockPos = blockPos; this.blockPos = blockPos;
} }
public boolean meansBreakBlock() { public void copyRotationSettingsFrom(BlockEntry blockEntry) {
return newBlockState == null || newBlockState.isAir(); mirrorX = blockEntry.mirrorX;
mirrorY = blockEntry.mirrorY;
mirrorZ = blockEntry.mirrorZ;
rotation = blockEntry.rotation;
} }
public BitSet getMirrorBitSet() { public void setItemStackAndFindNewBlockState(ItemStack itemStack, Level world, Direction originalDirection, Direction clickedFace, Vec3 relativeHitVec) {
BitSet bitSet = new BitSet(3); this.itemStack = itemStack;
bitSet.set(0, mirrorX);
bitSet.set(1, mirrorY); Block block = Block.byItem(itemStack.getItem());
bitSet.set(2, mirrorZ); var direction = rotation.rotate(originalDirection);
return bitSet; direction = applyMirror(direction);
//TODO mirror and rotate relativeHitVec?
var blockPlaceContext = new MyPlaceContext(world, blockPos, direction, itemStack, clickedFace, relativeHitVec);
newBlockState = block.getStateForPlacement(blockPlaceContext);
} }
public void setMirrorBitSet(BitSet bitSet) { private Direction applyMirror(Direction direction) {
mirrorX = bitSet.get(0); if (mirrorX && direction.getAxis() == Direction.Axis.Z) direction = direction.getOpposite();
mirrorY = bitSet.get(1); if (mirrorY && direction.getAxis() == Direction.Axis.Y) direction = direction.getOpposite();
mirrorZ = bitSet.get(2); if (mirrorZ && direction.getAxis() == Direction.Axis.X) direction = direction.getOpposite();
return direction;
} }
public static void encode(FriendlyByteBuf buf, BlockEntry block) { public static void encode(FriendlyByteBuf buf, BlockEntry block) {

View File

@@ -8,10 +8,12 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.Half;
import net.minecraft.world.level.block.state.properties.SlabType;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@@ -19,10 +21,11 @@ import net.minecraft.world.phys.Vec3;
//Common //Common
public class BlockUtilities { public class BlockUtilities {
public static BlockState getBlockState(Player player, InteractionHand hand, ItemStack blockItemStack, BlockEntry blockEntry) { @Deprecated //Use BlockEntry.setItemStackAndFindNewBlockState instead
public static BlockState getBlockState(Player player, InteractionHand hand, ItemStack blockItemStack, BlockEntry blockEntry, Vec3 relativeHitVec, Direction sideHit) {
Block block = Block.byItem(blockItemStack.getItem()); Block block = Block.byItem(blockItemStack.getItem());
//TODO convert lookingAt hitvec to relative hitvec Vec3 hitVec = relativeHitVec.add(Vec3.atLowerCornerOf(blockEntry.blockPos));
var blockHitResult = new BlockHitResult(Vec3.ZERO, Direction.UP, blockEntry.blockPos, false); var blockHitResult = new BlockHitResult(hitVec, sideHit, blockEntry.blockPos, false);
return block.getStateForPlacement(new BlockPlaceContext(player, hand, blockItemStack, blockHitResult)); return block.getStateForPlacement(new BlockPlaceContext(player, hand, blockItemStack, blockHitResult));
} }
@@ -56,4 +59,59 @@ public class BlockUtilities {
SoundEvent soundEvent = breaking ? soundType.getBreakSound() : soundType.getPlaceSound(); SoundEvent soundEvent = breaking ? soundType.getBreakSound() : soundType.getPlaceSound();
player.level.playSound(player, player.blockPosition(), soundEvent, SoundSource.BLOCKS, 0.6f, soundType.getPitch()); player.level.playSound(player, player.blockPosition(), soundEvent, SoundSource.BLOCKS, 0.6f, soundType.getPitch());
} }
public static BlockState getVerticalMirror(BlockState blockState) {
//Stairs
if (blockState.getBlock() instanceof StairBlock) {
if (blockState.getValue(StairBlock.HALF) == Half.BOTTOM) {
return blockState.setValue(StairBlock.HALF, Half.TOP);
} else {
return blockState.setValue(StairBlock.HALF, Half.BOTTOM);
}
}
//Slabs
if (blockState.getBlock() instanceof SlabBlock) {
if (blockState.getValue(SlabBlock.TYPE) == SlabType.DOUBLE) {
return blockState;
} else if (blockState.getValue(SlabBlock.TYPE) == SlabType.BOTTOM) {
return blockState.setValue(SlabBlock.TYPE, SlabType.TOP);
} else {
return blockState.setValue(SlabBlock.TYPE, SlabType.BOTTOM);
}
}
//Buttons, endrod, observer, piston
if (blockState.getBlock() instanceof DirectionalBlock) {
if (blockState.getValue(DirectionalBlock.FACING) == Direction.DOWN) {
return blockState.setValue(DirectionalBlock.FACING, Direction.UP);
} else if (blockState.getValue(DirectionalBlock.FACING) == Direction.UP) {
return blockState.setValue(DirectionalBlock.FACING, Direction.DOWN);
}
}
//Dispenser, dropper
if (blockState.getBlock() instanceof DispenserBlock) {
if (blockState.getValue(DispenserBlock.FACING) == Direction.DOWN) {
return blockState.setValue(DispenserBlock.FACING, Direction.UP);
} else if (blockState.getValue(DispenserBlock.FACING) == Direction.UP) {
return blockState.setValue(DispenserBlock.FACING, Direction.DOWN);
}
}
return blockState;
}
public static BlockHitResult getLookingAtFar(Player player) {
Level world = player.level;
//base distance off of player ability (config)
float raytraceRange = ReachHelper.getPlacementReach(player);
Vec3 look = player.getLookAngle();
Vec3 start = new Vec3(player.getX(), player.getY() + player.getEyeHeight(), player.getZ());
Vec3 end = new Vec3(player.getX() + look.x * raytraceRange, player.getY() + player.getEyeHeight() + look.y * raytraceRange, player.getZ() + look.z * raytraceRange);
return world.clip(new ClipContext(start, end, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, player));
}
} }

View File

@@ -0,0 +1,68 @@
package nl.requios.effortlessbuilding.utilities;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
// Version of DirectionalPlaceContext with hitVec
public class MyPlaceContext extends BlockPlaceContext {
private final Direction direction;
public MyPlaceContext(Level level, BlockPos blockPos, Direction direction, ItemStack itemStack, Direction clickedFace, Vec3 relativeHitVec) {
super(level, null, InteractionHand.MAIN_HAND, itemStack, new BlockHitResult(
Vec3.atLowerCornerOf(blockPos).add(relativeHitVec), clickedFace, blockPos, false));
this.direction = direction;
}
public BlockPos getClickedPos() {
return this.getHitResult().getBlockPos();
}
public boolean canPlace() {
return this.getLevel().getBlockState(this.getHitResult().getBlockPos()).canBeReplaced(this);
}
public boolean replacingClickedOnBlock() {
return this.canPlace();
}
public Direction getNearestLookingDirection() {
return Direction.DOWN;
}
public Direction[] getNearestLookingDirections() {
switch (this.direction) {
case DOWN:
default:
return new Direction[]{Direction.DOWN, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP};
case UP:
return new Direction[]{Direction.DOWN, Direction.UP, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST};
case NORTH:
return new Direction[]{Direction.DOWN, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.UP, Direction.SOUTH};
case SOUTH:
return new Direction[]{Direction.DOWN, Direction.SOUTH, Direction.EAST, Direction.WEST, Direction.UP, Direction.NORTH};
case WEST:
return new Direction[]{Direction.DOWN, Direction.WEST, Direction.SOUTH, Direction.UP, Direction.NORTH, Direction.EAST};
case EAST:
return new Direction[]{Direction.DOWN, Direction.EAST, Direction.SOUTH, Direction.UP, Direction.NORTH, Direction.WEST};
}
}
public Direction getHorizontalDirection() {
return this.direction.getAxis() == Direction.Axis.Y ? Direction.NORTH : this.direction;
}
public boolean isSecondaryUseActive() {
return false;
}
public float getRotation() {
return (float)(this.direction.get2DDataValue() * 90);
}
}

View File

@@ -4,7 +4,6 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import nl.requios.effortlessbuilding.CommonConfig; import nl.requios.effortlessbuilding.CommonConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
//Common //Common
public class ReachHelper { public class ReachHelper {