From a7dd0823e10c1f969284e62b9b99ab468927c0a6 Mon Sep 17 00:00:00 2001 From: Christian Knaapen Date: Wed, 8 Feb 2023 20:34:05 +0100 Subject: [PATCH] Fixed redo and running on server. --- .../effortlessbuilding/ClientEvents.java | 20 +-------- .../item/AbstractRandomizerBagItem.java | 6 +-- .../systems/ServerBlockPlacer.java | 45 +++++++++++++------ .../effortlessbuilding/systems/UndoRedo.java | 32 ++++++++++++- .../utilities/BlockPlacerHelper.java | 6 +-- .../utilities/BlockSet.java | 9 +++- 6 files changed, 74 insertions(+), 44 deletions(-) diff --git a/src/main/java/nl/requios/effortlessbuilding/ClientEvents.java b/src/main/java/nl/requios/effortlessbuilding/ClientEvents.java index f72be3b..13fad4e 100644 --- a/src/main/java/nl/requios/effortlessbuilding/ClientEvents.java +++ b/src/main/java/nl/requios/effortlessbuilding/ClientEvents.java @@ -40,14 +40,13 @@ public class ClientEvents { EffortlessBuilding.log("Registering KeyMappings!"); // register key bindings - keyBindings = new KeyMapping[5]; + keyBindings = new KeyMapping[4]; // instantiate the key bindings keyBindings[0] = new KeyMapping("key.effortlessbuilding.mode.desc", KeyConflictContext.IN_GAME, InputConstants.getKey(GLFW.GLFW_KEY_LEFT_ALT, 0), "key.effortlessbuilding.category"); keyBindings[1] = new KeyMapping("key.effortlessbuilding.hud.desc", KeyConflictContext.IN_GAME, InputConstants.getKey(GLFW.GLFW_KEY_KP_ADD, 0), "key.effortlessbuilding.category"); keyBindings[2] = new KeyMapping("key.effortlessbuilding.undo.desc", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, InputConstants.getKey(GLFW.GLFW_KEY_Z, 0), "key.effortlessbuilding.category"); keyBindings[3] = new KeyMapping("key.effortlessbuilding.redo.desc", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, InputConstants.getKey(GLFW.GLFW_KEY_Y, 0), "key.effortlessbuilding.category"); - keyBindings[4] = new KeyMapping("key.effortlessbuilding.altplacement.desc", KeyConflictContext.IN_GAME, InputConstants.getKey(GLFW.GLFW_KEY_LEFT_CONTROL, 0), "key.effortlessbuilding.category"); for (KeyMapping keyBinding : keyBindings) { event.register(keyBinding); @@ -159,23 +158,6 @@ public class ClientEvents { if (keyBindings[3].consumeClick()) { ModeOptions.performAction(player, ModeOptions.ActionEnum.REDO); } - - //Change placement mode - if (keyBindings[4].isDown()) { - //Toggle between first two actions of the first option of the current build mode - BuildModeEnum currentBuildMode = EffortlessBuildingClient.BUILD_MODES.getBuildMode(); - if (currentBuildMode.options.length > 0) { - ModeOptions.OptionEnum option = currentBuildMode.options[0]; - if (option.actions.length >= 2) { - if (ModeOptions.getOptionSetting(option) == option.actions[0]) { - ModeOptions.performAction(player, option.actions[1]); - } else { - ModeOptions.performAction(player, option.actions[0]); - } - } - } - } - } public static void openModifierSettings() { diff --git a/src/main/java/nl/requios/effortlessbuilding/item/AbstractRandomizerBagItem.java b/src/main/java/nl/requios/effortlessbuilding/item/AbstractRandomizerBagItem.java index 5f2c6a9..a9432c3 100644 --- a/src/main/java/nl/requios/effortlessbuilding/item/AbstractRandomizerBagItem.java +++ b/src/main/java/nl/requios/effortlessbuilding/item/AbstractRandomizerBagItem.java @@ -19,7 +19,9 @@ import net.minecraft.world.phys.Vec3; import net.minecraft.network.chat.Component; import net.minecraft.ChatFormatting; import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.network.NetworkHooks; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; @@ -206,10 +208,8 @@ public abstract class AbstractRandomizerBagItem extends Item { @Override public void appendHoverText(ItemStack stack, @Nullable Level world, List tooltip, TooltipFlag flag) { + tooltip.add(Component.literal(ChatFormatting.YELLOW + "*Experimental* Only works in singleplayer")); tooltip.add(Component.literal(ChatFormatting.BLUE + "Rightclick" + ChatFormatting.GRAY + " to place a random block")); tooltip.add(Component.literal(ChatFormatting.BLUE + "Sneak + rightclick" + ChatFormatting.GRAY + " to open inventory")); - if (world != null && world.players().size() > 1) { - tooltip.add(Component.literal(ChatFormatting.YELLOW + "Experimental on servers: may lose inventory")); - } } } diff --git a/src/main/java/nl/requios/effortlessbuilding/systems/ServerBlockPlacer.java b/src/main/java/nl/requios/effortlessbuilding/systems/ServerBlockPlacer.java index 7fb8f3e..e359650 100644 --- a/src/main/java/nl/requios/effortlessbuilding/systems/ServerBlockPlacer.java +++ b/src/main/java/nl/requios/effortlessbuilding/systems/ServerBlockPlacer.java @@ -66,11 +66,12 @@ public class ServerBlockPlacer { undoSet.add(block); } } - EffortlessBuilding.UNDO_REDO.addUndo(player, undoSet); + if (isAllowedToUndo(player, false)) + EffortlessBuilding.UNDO_REDO.addUndo(player, undoSet); } public void undoBlockSet(Player player, BlockSet blocks) { - if (!isAllowedToUndo(player)) return; + if (!isAllowedToUndo(player, true)) return; var redoSet = new BlockSet(); for (BlockEntry block : blocks) { @@ -100,25 +101,27 @@ public class ServerBlockPlacer { } private boolean undoBlockEntry(Player player, BlockEntry block) { - //Update newBlockState for future redo's - block.newBlockState = player.level.getBlockState(block.blockPos); boolean breaking = BlockUtilities.isNullOrAir(block.existingBlockState); var tempBlockEntry = new BlockEntry(block.blockPos); - var newBlockState = block.existingBlockState; + var temp = block.existingBlockState; tempBlockEntry.existingBlockState = block.newBlockState; - tempBlockEntry.newBlockState = newBlockState; + tempBlockEntry.newBlockState = temp; if (!validateBlockEntry(player, tempBlockEntry, breaking)) return false; + //Update newBlockState for future redo's + block.newBlockState = player.level.getBlockState(block.blockPos); + boolean success; isPlacingOrBreakingBlocks = true; if (breaking) { - success = BlockPlacerHelper.placeBlock(player, tempBlockEntry); - } else { success = BlockPlacerHelper.breakBlock(player, tempBlockEntry); + } else { + success = BlockPlacerHelper.placeBlock(player, tempBlockEntry); } isPlacingOrBreakingBlocks = false; + return success; } @@ -151,9 +154,9 @@ public class ServerBlockPlacer { return true; } - private boolean isAllowedToUndo(Player player) { + private boolean isAllowedToUndo(Player player, boolean log) { if (!player.isCreative()) { - EffortlessBuilding.log(player, ChatFormatting.RED + "Undo is not supported in survival mode."); + if (log) EffortlessBuilding.log(player, ChatFormatting.RED + "Undo is not supported in survival mode."); return false; } @@ -161,15 +164,30 @@ public class ServerBlockPlacer { } private boolean validateBlockSet(Player player, BlockSet blocks) { + if (blocks.isEmpty()) { + EffortlessBuilding.log(player, ChatFormatting.RED + "No blocks to place."); + return false; + } + if (blocks.skipFirst && blocks.size() == 1 && blocks.iterator().next().blockPos == blocks.firstPos) { + EffortlessBuilding.log(player, ChatFormatting.RED + "No blocks to place because the first block was skipped."); + return false; + } if (blocks.size() > ServerConfig.validation.maxBlocksPlacedAtOnce.get()) { EffortlessBuilding.log(player, ChatFormatting.RED + "Too many blocks to place. Max: " + ServerConfig.validation.maxBlocksPlacedAtOnce.get()); return false; } //Dont allow mixing breaking and placing blocks - //TODO fix if skipping first block - boolean breaking = blocks.getFirstBlockEntry().newBlockState == null || blocks.getFirstBlockEntry().newBlockState.isAir(); - for (var iterator = blocks.iterator(); iterator.hasNext(); ) { + //First determine if we are breaking or placing + var iterator = blocks.iterator(); + //Get any block from the set, skip first if we have to + var anyBlock = iterator.next(); + if (blocks.skipFirst && anyBlock.blockPos == blocks.firstPos) { + anyBlock = iterator.next(); + } + boolean breaking = anyBlock.newBlockState == null || anyBlock.newBlockState.isAir(); + + while (iterator.hasNext()) { var block = iterator.next(); if (block.newBlockState == null || block.newBlockState.isAir()) { if (!breaking) { @@ -183,6 +201,7 @@ public class ServerBlockPlacer { } } } + return true; } diff --git a/src/main/java/nl/requios/effortlessbuilding/systems/UndoRedo.java b/src/main/java/nl/requios/effortlessbuilding/systems/UndoRedo.java index 26abe73..1bba987 100644 --- a/src/main/java/nl/requios/effortlessbuilding/systems/UndoRedo.java +++ b/src/main/java/nl/requios/effortlessbuilding/systems/UndoRedo.java @@ -1,5 +1,6 @@ package nl.requios.effortlessbuilding.systems; +import net.minecraft.ChatFormatting; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.Blocks; @@ -8,6 +9,7 @@ import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; +import net.minecraftforge.common.util.BlockSnapshot; import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.ServerConfig; import nl.requios.effortlessbuilding.utilities.*; @@ -17,11 +19,27 @@ import java.util.*; //Server only public class UndoRedo { + public class UndoSet { + public final List blockSnapshots; + + public UndoSet(List blockSnapshots) { + this.blockSnapshots = blockSnapshots; + } + } + public final Map> undoStacks = new HashMap<>(); public final Map> redoStacks = new HashMap<>(); + private boolean isAllowedToUndo(Player player) { + if (!player.isCreative()) { + return false; + } + + return true; + } + public void addUndo(Player player, BlockSet blockSet) { - if (blockSet.isEmpty()) return; + if (blockSet.isEmpty() || !isAllowedToUndo(player)) return; //If no stack exists, make one if (!undoStacks.containsKey(player.getUUID())) { @@ -32,7 +50,7 @@ public class UndoRedo { } public void addRedo(Player player, BlockSet blockSet) { - if (blockSet.isEmpty()) return; + if (blockSet.isEmpty() || !isAllowedToUndo(player)) return; //If no stack exists, make one if (!redoStacks.containsKey(player.getUUID())) { @@ -43,6 +61,11 @@ public class UndoRedo { } public boolean undo(Player player) { + if (!isAllowedToUndo(player)) { + EffortlessBuilding.log(player, ChatFormatting.RED + "You are not allowed to undo."); + return false; + } + if (!undoStacks.containsKey(player.getUUID())) return false; FixedStack undoStack = undoStacks.get(player.getUUID()); @@ -55,6 +78,11 @@ public class UndoRedo { } public boolean redo(Player player) { + if (!isAllowedToUndo(player)) { + EffortlessBuilding.log(player, ChatFormatting.RED + "You are not allowed to undo."); + return false; + } + if (!redoStacks.containsKey(player.getUUID())) return false; FixedStack redoStack = redoStacks.get(player.getUUID()); diff --git a/src/main/java/nl/requios/effortlessbuilding/utilities/BlockPlacerHelper.java b/src/main/java/nl/requios/effortlessbuilding/utilities/BlockPlacerHelper.java index 7e2c125..83efa7c 100644 --- a/src/main/java/nl/requios/effortlessbuilding/utilities/BlockPlacerHelper.java +++ b/src/main/java/nl/requios/effortlessbuilding/utilities/BlockPlacerHelper.java @@ -47,7 +47,6 @@ public class BlockPlacerHelper { return placeBlockWithoutItem(player, blockEntry); } else { var interactionResult = placeItem(player, blockEntry); - interactionResult.shouldSwing() return interactionResult == InteractionResult.SUCCESS; } } @@ -106,10 +105,7 @@ public class BlockPlacerHelper { ItemStack itemstack = block.itemStack; Level level = player.level; - if (player != null && !player.getAbilities().mayBuild) - return InteractionResult.PASS; - - if (itemstack != null && !itemstack.hasAdventureModePlaceTagForBlock(level.registryAccess().registryOrThrow(Registry.BLOCK_REGISTRY), new BlockInWorld(level, block.blockPos, false))) + if (player != null && !player.getAbilities().mayBuild && !itemstack.hasAdventureModePlaceTagForBlock(level.registryAccess().registryOrThrow(Registry.BLOCK_REGISTRY), new BlockInWorld(level, block.blockPos, false))) return InteractionResult.PASS; // handle all placement events here diff --git a/src/main/java/nl/requios/effortlessbuilding/utilities/BlockSet.java b/src/main/java/nl/requios/effortlessbuilding/utilities/BlockSet.java index b334f49..6408f64 100644 --- a/src/main/java/nl/requios/effortlessbuilding/utilities/BlockSet.java +++ b/src/main/java/nl/requios/effortlessbuilding/utilities/BlockSet.java @@ -51,9 +51,14 @@ public class BlockSet extends HashMap implements Iterable< public void add(BlockEntry blockEntry) { if (!containsKey(blockEntry.blockPos)) { - if (!DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> ClientSide.isFull(this))) { + //check if we are clientside + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { + if (!ClientSide.isFull(this)) + put(blockEntry.blockPos, blockEntry); + }); + DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER, () -> () -> { put(blockEntry.blockPos, blockEntry); - } + }); } else { if (logging) EffortlessBuilding.log("BlockSet already contains block at " + blockEntry.blockPos); }