diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/AbstractCustomCropsBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/AbstractCustomCropsBlock.java index c88884e..db3282b 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/AbstractCustomCropsBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/AbstractCustomCropsBlock.java @@ -53,6 +53,11 @@ public abstract class AbstractCustomCropsBlock implements CustomCropsBlock { return CustomCropsBlockState.create(this, compoundMap); } + @Override + public CustomCropsBlockState createBlockState(String itemID) { + return createBlockState(); + } + public String id(CustomCropsBlockState state) { return state.get("key").getAsStringTag() .map(StringTag::getValue) diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/CropBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/CropBlock.java index 76cbeda..ac2d9c7 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/CropBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/CropBlock.java @@ -275,6 +275,19 @@ public class CropBlock extends AbstractCustomCropsBlock { ActionManager.trigger(context, stageConfig.interactActions()); } + @Override + public CustomCropsBlockState createBlockState(String itemID) { + List configList = Registries.STAGE_TO_CROP_UNSAFE.get(itemID); + if (configList == null || configList.size() != 1) return null; + CropConfig cropConfig = configList.get(0); + CustomCropsBlockState state = createBlockState(); + CropStageConfig stageConfig = cropConfig.stageByID(itemID); + assert stageConfig != null; + point(state, stageConfig.point()); + id(state, cropConfig.id()); + return state; + } + public CustomCropsBlockState fixOrGetState(CustomCropsWorld world, Pos3 pos3, String stageID) { List configList = Registries.STAGE_TO_CROP_UNSAFE.get(stageID); if (configList == null) return null; @@ -296,7 +309,7 @@ public class CropBlock extends AbstractCustomCropsBlock { CropStageConfig stageConfig = cropConfig.stageByID(stageID); assert stageConfig != null; int point = stageConfig.point(); - CustomCropsBlockState state = BuiltInBlockMechanics.CROP.createBlockState(); + CustomCropsBlockState state = createBlockState(); point(state, point); id(state, cropConfig.id()); world.addBlockState(pos3, state).ifPresent(previous -> { diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/CustomCropsBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/CustomCropsBlock.java index eb89a69..d6f0672 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/CustomCropsBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/CustomCropsBlock.java @@ -27,6 +27,7 @@ import net.momirealms.customcrops.api.core.wrapper.WrappedPlaceEvent; import net.momirealms.customcrops.api.misc.NamedTextColor; import net.momirealms.customcrops.common.util.Key; import org.bukkit.Location; +import org.jetbrains.annotations.Nullable; public interface CustomCropsBlock { @@ -44,6 +45,14 @@ public interface CustomCropsBlock { */ CustomCropsBlockState createBlockState(); + /** + * Create a CustomCropsBlockState based on the item id + * + * @return CustomCropsBlockState + */ + @Nullable + CustomCropsBlockState createBlockState(String itemID); + /** * Create a CustomCropsBlockState based on this type and provided data * diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/DeadCrop.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/DeadCrop.java index 966479d..99bda0f 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/DeadCrop.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/DeadCrop.java @@ -26,7 +26,10 @@ import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; import net.momirealms.customcrops.api.core.world.CustomCropsWorld; import net.momirealms.customcrops.api.core.world.Pos3; +import net.momirealms.customcrops.api.core.wrapper.WrappedBreakEvent; import net.momirealms.customcrops.api.core.wrapper.WrappedInteractEvent; +import net.momirealms.customcrops.api.event.ScarecrowBreakEvent; +import net.momirealms.customcrops.api.util.EventUtils; import net.momirealms.customcrops.api.util.LocationUtils; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -47,6 +50,18 @@ public class DeadCrop extends AbstractCustomCropsBlock { // do not restore } + @Override + public CustomCropsBlockState createBlockState(String itemID) { + return null; + } + + @Override + public void onBreak(WrappedBreakEvent event) { + CustomCropsWorld world = event.world(); + Pos3 pos3 = Pos3.from(event.location()); + world.removeBlockState(pos3); + } + @Override public void onInteract(WrappedInteractEvent event) { final Player player = event.player(); diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/PotBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/PotBlock.java index 32334df..203b447 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/PotBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/PotBlock.java @@ -322,6 +322,18 @@ public class PotBlock extends AbstractCustomCropsBlock { return false; } + @Override + public CustomCropsBlockState createBlockState(String itemID) { + PotConfig potConfig = Registries.ITEM_TO_POT.get(itemID); + if (potConfig == null) { + return null; + } + CustomCropsBlockState state = createBlockState(); + id(state, potConfig.id()); + water(state, potConfig.isWet(itemID) ? 1 : 0); + return state; + } + public CustomCropsBlockState fixOrGetState(CustomCropsWorld world, Pos3 pos3, PotConfig potConfig, String blockID) { if (potConfig == null) return null; Optional optionalPotState = world.getBlockState(pos3); @@ -333,7 +345,7 @@ public class PotBlock extends AbstractCustomCropsBlock { } } } - CustomCropsBlockState state = BuiltInBlockMechanics.POT.createBlockState(); + CustomCropsBlockState state = createBlockState(); id(state, potConfig.id()); water(state, potConfig.isWet(blockID) ? 1 : 0); world.addBlockState(pos3, state).ifPresent(previous -> { diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/SprinklerBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/SprinklerBlock.java index e07600c..03a7701 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/SprinklerBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/SprinklerBlock.java @@ -232,6 +232,18 @@ public class SprinklerBlock extends AbstractCustomCropsBlock { ActionManager.trigger(context, config.interactActions()); } + @Override + public CustomCropsBlockState createBlockState(String itemID) { + SprinklerConfig config = Registries.ITEM_TO_SPRINKLER.get(itemID); + if (config == null) { + return null; + } + CustomCropsBlockState state = createBlockState(); + id(state, config.id()); + water(state, itemID.equals(config.threeDItemWithWater()) ? 1 : 0); + return state; + } + public CustomCropsBlockState fixOrGetState(CustomCropsWorld world, Pos3 pos3, SprinklerConfig sprinklerConfig, String blockID) { Optional optionalPotState = world.getBlockState(pos3); if (optionalPotState.isPresent()) { @@ -242,7 +254,7 @@ public class SprinklerBlock extends AbstractCustomCropsBlock { } } } - CustomCropsBlockState state = BuiltInBlockMechanics.SPRINKLER.createBlockState(); + CustomCropsBlockState state = createBlockState(); id(state, sprinklerConfig.id()); water(state, blockID.equals(sprinklerConfig.threeDItemWithWater()) ? 1 : 0); world.addBlockState(pos3, state).ifPresent(previous -> { diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsWorldImpl.java b/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsWorldImpl.java index 96a2a0d..c681281 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsWorldImpl.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsWorldImpl.java @@ -182,8 +182,6 @@ public class CustomCropsWorldImpl implements CustomCropsWorld { public Optional addBlockState(Pos3 location, CustomCropsBlockState block) { ChunkPos pos = location.toChunkPos(); CustomCropsChunk chunk = getOrCreateChunk(pos); - // to let the bukkit system trigger the ChunkUnloadEvent later - chunk.load(true); return chunk.addBlockState(location, block); } @@ -437,7 +435,10 @@ public class CustomCropsWorldImpl implements CustomCropsWorld { if (chunk != null) { return chunk; } - return this.adaptor.loadChunk(this, chunkPos, true); + chunk = this.adaptor.loadChunk(this, chunkPos, true); + // to let the bukkit system trigger the ChunkUnloadEvent later + chunk.load(true); + return chunk; })); } diff --git a/common/src/main/java/net/momirealms/customcrops/common/command/AbstractCommandManager.java b/common/src/main/java/net/momirealms/customcrops/common/command/AbstractCommandManager.java index 03327e5..0333670 100644 --- a/common/src/main/java/net/momirealms/customcrops/common/command/AbstractCommandManager.java +++ b/common/src/main/java/net/momirealms/customcrops/common/command/AbstractCommandManager.java @@ -69,6 +69,11 @@ public abstract class AbstractCommandManager implements CustomCropsCommandMan this.feedbackConsumer = feedbackConsumer; } + @Override + public TriConsumer feedbackConsumer() { + return feedbackConsumer; + } + @Override public TriConsumer defaultFeedbackConsumer() { return ((sender, node, component) -> { diff --git a/common/src/main/java/net/momirealms/customcrops/common/command/CustomCropsCommandManager.java b/common/src/main/java/net/momirealms/customcrops/common/command/CustomCropsCommandManager.java index b231727..6c2324d 100644 --- a/common/src/main/java/net/momirealms/customcrops/common/command/CustomCropsCommandManager.java +++ b/common/src/main/java/net/momirealms/customcrops/common/command/CustomCropsCommandManager.java @@ -42,6 +42,8 @@ public interface CustomCropsCommandManager { void setFeedbackConsumer(@NotNull TriConsumer feedbackConsumer); + TriConsumer feedbackConsumer(); + TriConsumer defaultFeedbackConsumer(); CommandConfig getCommandConfig(YamlDocument document, String featureID); diff --git a/common/src/main/java/net/momirealms/customcrops/common/locale/MessageConstants.java b/common/src/main/java/net/momirealms/customcrops/common/locale/MessageConstants.java index 45137b3..3ac8b06 100644 --- a/common/src/main/java/net/momirealms/customcrops/common/locale/MessageConstants.java +++ b/common/src/main/java/net/momirealms/customcrops/common/locale/MessageConstants.java @@ -53,9 +53,11 @@ public interface MessageConstants { TranslatableComponent.Builder COMMAND_DEBUG_WORLDS_SUCCESS = Component.translatable().key("command.debug.worlds.success"); TranslatableComponent.Builder COMMAND_DEBUG_INSIGHT_OFF = Component.translatable().key("command.debug.insight.off"); TranslatableComponent.Builder COMMAND_DEBUG_INSIGHT_ON = Component.translatable().key("command.debug.insight.on"); - TranslatableComponent.Builder COMMAND_DEBUG_DELETE_FAILURE_WORLD = Component.translatable().key("command.unsafe.delete.failure.world"); - TranslatableComponent.Builder COMMAND_DEBUG_DELETE_SUCCESS = Component.translatable().key("command.unsafe.delete.success"); - TranslatableComponent.Builder COMMAND_DEBUG_RESTORE_FAILURE_WORLD = Component.translatable().key("command.unsafe.restore.failure.world"); - TranslatableComponent.Builder COMMAND_DEBUG_RESTORE_FAILURE_CHUNK = Component.translatable().key("command.unsafe.restore.failure.chunk"); - TranslatableComponent.Builder COMMAND_DEBUG_RESTORE_SUCCESS = Component.translatable().key("command.unsafe.restore.success"); + TranslatableComponent.Builder COMMAND_UNSAFE_DELETE_FAILURE_WORLD = Component.translatable().key("command.unsafe.delete.failure.world"); + TranslatableComponent.Builder COMMAND_UNSAFE_DELETE_SUCCESS = Component.translatable().key("command.unsafe.delete.success"); + TranslatableComponent.Builder COMMAND_UNSAFE_RESTORE_FAILURE_WORLD = Component.translatable().key("command.unsafe.restore.failure.world"); + TranslatableComponent.Builder COMMAND_UNSAFE_RESTORE_FAILURE_CHUNK = Component.translatable().key("command.unsafe.restore.failure.chunk"); + TranslatableComponent.Builder COMMAND_UNSAFE_RESTORE_SUCCESS = Component.translatable().key("command.unsafe.restore.success"); + TranslatableComponent.Builder COMMAND_UNSAFE_FIX_FAILURE_WORLD = Component.translatable().key("command.unsafe.fix.failure.world"); + TranslatableComponent.Builder COMMAND_UNSAFE_FIX_SUCCESS = Component.translatable().key("command.unsafe.fix.success"); } diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/BukkitCommandManager.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/BukkitCommandManager.java index 2e426b7..ddf0279 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/BukkitCommandManager.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/BukkitCommandManager.java @@ -45,7 +45,8 @@ public class BukkitCommandManager extends AbstractCommandManager new DebugWorldsCommand(this), new DebugInsightCommand(this), new UnsafeRestoreCommand(this), - new UnsafeDeleteCommand(this) + new UnsafeDeleteCommand(this), + new UnsafeFixCommand(this) ); private final Index> INDEX = Index.create(CommandFeature::getFeatureID, FEATURES); diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/DebugDataCommand.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/DebugDataCommand.java index 56d35b1..23f55f8 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/DebugDataCommand.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/DebugDataCommand.java @@ -18,6 +18,8 @@ package net.momirealms.customcrops.bukkit.command.feature; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TranslatableComponent; +import net.kyori.adventure.text.event.ClickEvent; import net.momirealms.customcrops.api.BukkitCustomCropsPlugin; import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; import net.momirealms.customcrops.api.core.world.Pos3; @@ -25,12 +27,15 @@ import net.momirealms.customcrops.bukkit.command.BukkitCommandFeature; import net.momirealms.customcrops.common.command.CustomCropsCommandManager; import net.momirealms.customcrops.common.helper.AdventureHelper; import net.momirealms.customcrops.common.locale.MessageConstants; +import net.momirealms.customcrops.common.locale.TranslationManager; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.checkerframework.checker.units.qual.C; import org.incendo.cloud.Command; import org.incendo.cloud.CommandManager; +import org.incendo.cloud.context.CommandContext; import java.util.Optional; @@ -62,13 +67,19 @@ public class DebugDataCommand extends BukkitCommandFeature { } BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(location.getWorld()).ifPresent(world -> { Optional state = world.getBlockState(Pos3.from(location)); - state.ifPresent(customCropsBlockState -> - handleFeedback(context, - MessageConstants.COMMAND_DEBUG_DATA_SUCCESS_CUSTOM, - Component.text(customCropsBlockState.asString()))); + state.ifPresent(customCropsBlockState -> { + String cData = customCropsBlockState.asString(); + TranslatableComponent component = MessageConstants.COMMAND_DEBUG_DATA_SUCCESS_CUSTOM + .arguments(Component.text(cData)) + .build(); + commandManager.feedbackConsumer().accept(context.sender(), component.key(), TranslationManager.render(component).clickEvent(ClickEvent.copyToClipboard(cData))); + }); }); String bData = block.getBlockData().getAsString(); - handleFeedback(context, MessageConstants.COMMAND_DEBUG_DATA_SUCCESS_VANILLA, Component.text(bData)); + TranslatableComponent component = MessageConstants.COMMAND_DEBUG_DATA_SUCCESS_VANILLA + .arguments(Component.text(bData)) + .build(); + commandManager.feedbackConsumer().accept(context.sender(), component.key(), TranslationManager.render(component).clickEvent(ClickEvent.copyToClipboard(bData))); }); } @@ -76,4 +87,6 @@ public class DebugDataCommand extends BukkitCommandFeature { public String getFeatureID() { return "debug_data"; } + + } diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/UnsafeDeleteCommand.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/UnsafeDeleteCommand.java index 918c8bd..2cd53cf 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/UnsafeDeleteCommand.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/UnsafeDeleteCommand.java @@ -47,14 +47,14 @@ public class UnsafeDeleteCommand extends BukkitCommandFeature { Player player = context.sender(); Optional> optional = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(player.getWorld()); if (optional.isEmpty()) { - handleFeedback(context, MessageConstants.COMMAND_DEBUG_DELETE_FAILURE_WORLD, Component.text(player.getWorld().getName())); + handleFeedback(context, MessageConstants.COMMAND_UNSAFE_DELETE_FAILURE_WORLD, Component.text(player.getWorld().getName())); return; } CustomCropsWorld world = optional.get(); CustomCropsWorldImpl customCropsWorld = (CustomCropsWorldImpl) world; ChunkPos chunkPos = ChunkPos.fromBukkitChunk(player.getLocation().getChunk()); customCropsWorld.deleteChunk(chunkPos); - handleFeedback(context, MessageConstants.COMMAND_DEBUG_DELETE_SUCCESS); + handleFeedback(context, MessageConstants.COMMAND_UNSAFE_DELETE_SUCCESS); }); } diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/UnsafeFixCommand.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/UnsafeFixCommand.java new file mode 100644 index 0000000..8ddbbf8 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/UnsafeFixCommand.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) <2024> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customcrops.bukkit.command.feature; + +import net.kyori.adventure.text.Component; +import net.momirealms.customcrops.api.BukkitCustomCropsPlugin; +import net.momirealms.customcrops.api.core.AbstractItemManager; +import net.momirealms.customcrops.api.core.Registries; +import net.momirealms.customcrops.api.core.block.CustomCropsBlock; +import net.momirealms.customcrops.api.core.world.*; +import net.momirealms.customcrops.bukkit.command.BukkitCommandFeature; +import net.momirealms.customcrops.common.command.CustomCropsCommandManager; +import net.momirealms.customcrops.common.locale.MessageConstants; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.incendo.cloud.Command; +import org.incendo.cloud.CommandManager; + +import java.util.Optional; + +public class UnsafeFixCommand extends BukkitCommandFeature { + + public UnsafeFixCommand(CustomCropsCommandManager commandManager) { + super(commandManager); + } + + @Override + public Command.Builder assembleCommand(CommandManager manager, Command.Builder builder) { + return builder + .senderType(Player.class) + .flag(manager.flagBuilder("silent").build()) + .handler(context -> { + Player player = context.sender(); + World bukkitWorld = player.getWorld(); + Optional> optional = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(bukkitWorld); + if (optional.isEmpty()) { + handleFeedback(context, MessageConstants.COMMAND_UNSAFE_FIX_FAILURE_WORLD, Component.text(bukkitWorld.getName())); + return; + } + ChunkPos chunkPos = ChunkPos.fromBukkitChunk(player.getLocation().getChunk()); + CustomCropsWorld world = optional.get(); + CustomCropsChunk chunk = world.getOrCreateChunk(chunkPos); + + CustomCropsSection section = chunk.getSection(BlockPos.fromPos3( Pos3.from(player.getLocation())).sectionID()); + AbstractItemManager itemManager = BukkitCustomCropsPlugin.getInstance().getItemManager(); + Location baseLocation = new Location(bukkitWorld, chunkPos.x() * 16, section.getSectionID() * 16, chunkPos.z() * 16); + + int fixedBlocks = 0; + int corruptedBlocks = 0; + + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + for (int y = 0; y < 16; y++) { + Location temp = baseLocation.clone().add(x, y, z); + String id = itemManager.anyID(temp); + Pos3 pos3 = Pos3.from(temp); + Optional previousState = chunk.getBlockState(pos3); + if (previousState.isPresent()) { + CustomCropsBlockState state = previousState.get(); + if (state.type().isInstance(id)) { + continue; + } else { + corruptedBlocks++; + chunk.removeBlockState(pos3); + } + } + CustomCropsBlock customCropsBlock = Registries.BLOCKS.get(id); + if (customCropsBlock == null) { + continue; + } + CustomCropsBlockState state = customCropsBlock.createBlockState(id); + if (state != null) { + chunk.addBlockState(pos3, state); + fixedBlocks++; + } + } + } + } + + handleFeedback(context, MessageConstants.COMMAND_UNSAFE_FIX_SUCCESS, Component.text(fixedBlocks), Component.text(corruptedBlocks)); + }); + } + + @Override + public String getFeatureID() { + return "unsafe_fix"; + } +} diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/UnsafeRestoreCommand.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/UnsafeRestoreCommand.java index 152f2ed..d0a805e 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/UnsafeRestoreCommand.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/UnsafeRestoreCommand.java @@ -50,14 +50,14 @@ public class UnsafeRestoreCommand extends BukkitCommandFeature { World bukkitWorld = player.getWorld(); Optional> optional = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(bukkitWorld); if (optional.isEmpty()) { - handleFeedback(context, MessageConstants.COMMAND_DEBUG_RESTORE_FAILURE_WORLD, Component.text(bukkitWorld.getName())); + handleFeedback(context, MessageConstants.COMMAND_UNSAFE_RESTORE_FAILURE_WORLD, Component.text(bukkitWorld.getName())); return; } ChunkPos chunkPos = ChunkPos.fromBukkitChunk(player.getLocation().getChunk()); CustomCropsWorld world = optional.get(); Optional chunk = world.getLoadedChunk(chunkPos); if (chunk.isEmpty()) { - handleFeedback(context, MessageConstants.COMMAND_DEBUG_RESTORE_FAILURE_CHUNK); + handleFeedback(context, MessageConstants.COMMAND_UNSAFE_RESTORE_FAILURE_CHUNK); return; } CustomCropsChunk customCropsChunk = chunk.get(); @@ -76,7 +76,7 @@ public class UnsafeRestoreCommand extends BukkitCommandFeature { } } } - handleFeedback(context, MessageConstants.COMMAND_DEBUG_RESTORE_SUCCESS, Component.text(restoredBlocks), Component.text(totalBlocks)); + handleFeedback(context, MessageConstants.COMMAND_UNSAFE_RESTORE_SUCCESS, Component.text(restoredBlocks), Component.text(totalBlocks)); }); } diff --git a/plugin/src/main/resources/commands.yml b/plugin/src/main/resources/commands.yml index 7932202..e4b1ab2 100644 --- a/plugin/src/main/resources/commands.yml +++ b/plugin/src/main/resources/commands.yml @@ -104,4 +104,13 @@ unsafe_delete: permission: customcrops.command.unsafe.delete usage: - /customcrops unsafe delete - - /ccrops unsafe delete \ No newline at end of file + - /ccrops unsafe delete + +# A command to fix the CustomCrops data in one section(16x16x16) +# Usage: [COMMAND] +unsafe_fix: + enable: true + permission: customcrops.command.unsafe.fix + usage: + - /customcrops unsafe fix + - /ccrops unsafe fix \ No newline at end of file diff --git a/plugin/src/main/resources/translations/en.yml b/plugin/src/main/resources/translations/en.yml index e459760..d40a95b 100644 --- a/plugin/src/main/resources/translations/en.yml +++ b/plugin/src/main/resources/translations/en.yml @@ -67,9 +67,13 @@ command.unsafe.delete.success: "Deleted block data in this chunk" command.unsafe.restore.failure.world: "CustomCrops is not enabled in world []" command.unsafe.restore.failure.chunk: "This chunk doesn't contain any data" command.unsafe.restore.success: "Restored (/) blocks" +command.unsafe.fix.failure.world: "CustomCrops is not enabled in world []" +command.unsafe.fix.success: + - "Fixed blocks" + - "Removed corrupt blocks" command.debug.data.failure: "No block selected" -command.debug.data.success.vanilla: "Vanilla block data: Copy'>'>" -command.debug.data.success.custom: "Custom block data: Copy'>'>" +command.debug.data.success.vanilla: "Vanilla block data: Copy'>" +command.debug.data.success.custom: "Custom block data: Copy'>" command.debug.worlds.failure: "There's no world loaded" command.debug.worlds.success: - "World: " diff --git a/plugin/src/main/resources/translations/zh_cn.yml b/plugin/src/main/resources/translations/zh_cn.yml index fd3c72d..724a411 100644 --- a/plugin/src/main/resources/translations/zh_cn.yml +++ b/plugin/src/main/resources/translations/zh_cn.yml @@ -66,9 +66,13 @@ command.unsafe.delete.success: "删除了这个区块的数据" command.unsafe.restore.failure.world: "CustomCrops没有在世界 [] 启用" command.unsafe.restore.failure.chunk: "这个区块没有任何数据" command.unsafe.restore.success: "恢复了 (/) 方块" +command.unsafe.fix.failure.world: "CustomCrops没有在世界 [] 启用" +command.unsafe.fix.success: + - "修复了 个方块数据" + - "移除了 个损坏数据" command.debug.data.failure: "未选中任何方块" -command.debug.data.success.vanilla: "原版方块数据: 复制'>'>" -command.debug.data.success.custom: "自定义方块数据: 复制'>'>" +command.debug.data.success.vanilla: "原版方块数据: 复制'>" +command.debug.data.success.custom: "自定义方块数据: 复制'>" command.debug.worlds.failure: "没有农作物世界被加载" command.debug.worlds.success: - "世界: "