9
0
mirror of https://github.com/Xiao-MoMi/Custom-Crops.git synced 2025-12-28 19:39:20 +00:00

Added unsafe commands

This commit is contained in:
XiaoMoMi
2024-09-15 17:18:33 +08:00
parent ce4c12da11
commit 389fa9e3c6
27 changed files with 412 additions and 107 deletions

View File

@@ -98,7 +98,7 @@ public class BukkitCustomCropsPluginImpl extends BukkitCustomCropsPlugin {
@Override
public InputStream getResourceStream(String filePath) {
return getBootstrap().getResource(filePath);
return getBootstrap().getResource(filePath.replace("\\", "/"));
}
@Override

View File

@@ -43,7 +43,9 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
new SetDateCommand(this),
new ForceTickCommand(this),
new DebugWorldsCommand(this),
new DebugInsightCommand(this)
new DebugInsightCommand(this),
new UnsafeRestoreCommand(this),
new UnsafeDeleteCommand(this)
);
private final Index<String, CommandFeature<CommandSender>> INDEX = Index.create(CommandFeature::getFeatureID, FEATURES);

View File

@@ -17,12 +17,14 @@
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.world.CustomCropsBlockState;
import net.momirealms.customcrops.api.core.world.Pos3;
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 org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.command.CommandSender;
@@ -52,22 +54,21 @@ public class DebugDataCommand extends BukkitCommandFeature<CommandSender> {
block = location.getBlock();
} else {
block = player.getTargetBlockExact(10);
if (block == null) return;
if (block == null) {
handleFeedback(context, MessageConstants.COMMAND_DEBUG_DATA_FAILURE);
return;
}
location = block.getLocation();
}
BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(location.getWorld()).ifPresent(world -> {
Optional<CustomCropsBlockState> state = world.getBlockState(Pos3.from(location));
if (state.isPresent()) {
BukkitCustomCropsPlugin.getInstance().getSenderFactory().wrap(player)
.sendMessage(AdventureHelper.miniMessage("<gold>" + state.get()));
} else {
BukkitCustomCropsPlugin.getInstance().getSenderFactory().wrap(player)
.sendMessage(AdventureHelper.miniMessage("<red>CustomCrops Data not found"));
}
state.ifPresent(customCropsBlockState ->
handleFeedback(context,
MessageConstants.COMMAND_DEBUG_DATA_SUCCESS_CUSTOM,
Component.text(customCropsBlockState.asString())));
});
String bData = block.getBlockData().getAsString();
BukkitCustomCropsPlugin.getInstance().getSenderFactory().wrap(player)
.sendMessage(AdventureHelper.miniMessage("<green>Vanilla crop data: <hover:show_text:'<yellow>Copy'><click:copy_to_clipboard:'"+bData+"'>" + bData + "</click>"));
handleFeedback(context, MessageConstants.COMMAND_DEBUG_DATA_SUCCESS_VANILLA, Component.text(bData));
});
}

View File

@@ -23,6 +23,7 @@ import net.momirealms.customcrops.api.util.LocationUtils;
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.plugin.scheduler.SchedulerTask;
import net.momirealms.sparrow.heart.SparrowHeart;
import net.momirealms.sparrow.heart.feature.color.NamedTextColor;
@@ -59,14 +60,13 @@ public class DebugInsightCommand extends BukkitCommandFeature<CommandSender> imp
Player player = context.sender();
if (player.hasMetadata("customcrops:insight")) {
player.removeMetadata("customcrops:insight", plugin.getBootstrap());
plugin.getSenderFactory().wrap(player).sendMessage(AdventureHelper.miniMessage("<red>Insight mode: OFF"));
handleFeedback(context, MessageConstants.COMMAND_DEBUG_INSIGHT_OFF);
return;
}
player.setMetadata("customcrops:insight", new FixedMetadataValue(plugin.getBootstrap(), 1));
new InsightPlayer(player.getUniqueId());
plugin.getSenderFactory().wrap(player).sendMessage(AdventureHelper.miniMessage("<green>Insight mode: ON"));
plugin.getSenderFactory().wrap(player).sendMessage(AdventureHelper.miniMessage("<white>Note that this only shows a snapshot of the data."));
handleFeedback(context, MessageConstants.COMMAND_DEBUG_INSIGHT_ON);
});
}

View File

@@ -17,17 +17,20 @@
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.world.CustomCropsWorld;
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.sender.Sender;
import net.momirealms.customcrops.common.locale.MessageConstants;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
import java.util.Optional;
public class DebugWorldsCommand extends BukkitCommandFeature<CommandSender> {
public DebugWorldsCommand(CustomCropsCommandManager<CommandSender> commandManager) {
@@ -38,14 +41,19 @@ public class DebugWorldsCommand extends BukkitCommandFeature<CommandSender> {
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.handler(context -> {
Sender sender = BukkitCustomCropsPlugin.getInstance().getSenderFactory().wrap(context.sender());
int worldCount = 0;
for (World world : Bukkit.getWorlds()) {
BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(world).ifPresent(w -> {
sender.sendMessage(AdventureHelper.miniMessage("<gold>World: " + world.getName() + "</gold>"));
sender.sendMessage(AdventureHelper.miniMessage(" - Loaded regions: " + w.loadedRegions().length));
sender.sendMessage(AdventureHelper.miniMessage(" - Loaded chunks: " + w.loadedChunks().length));
sender.sendMessage(AdventureHelper.miniMessage(" - Lazy chunks: " + w.lazyChunks().length));
});
Optional<CustomCropsWorld<?>> optional = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(world);
if (optional.isPresent()) {
worldCount++;
CustomCropsWorld<?> w = optional.get();
handleFeedback(context, MessageConstants.COMMAND_DEBUG_WORLDS_SUCCESS,
Component.text(world.getName()), Component.text(w.loadedRegions().length), Component.text(w.loadedChunks().length), Component.text(w.lazyChunks().length)
);
}
}
if (worldCount == 0) {
handleFeedback(context, MessageConstants.COMMAND_DEBUG_WORLDS_FAILURE);
}
});
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) <2024> <XiaoMoMi>
*
* 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 <https://www.gnu.org/licenses/>.
*/
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.world.ChunkPos;
import net.momirealms.customcrops.api.core.world.CustomCropsWorld;
import net.momirealms.customcrops.api.core.world.CustomCropsWorldImpl;
import net.momirealms.customcrops.bukkit.command.BukkitCommandFeature;
import net.momirealms.customcrops.common.command.CustomCropsCommandManager;
import net.momirealms.customcrops.common.locale.MessageConstants;
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 UnsafeDeleteCommand extends BukkitCommandFeature<CommandSender> {
public UnsafeDeleteCommand(CustomCropsCommandManager<CommandSender> commandManager) {
super(commandManager);
}
@Override
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.senderType(Player.class)
.flag(manager.flagBuilder("silent").build())
.handler(context -> {
Player player = context.sender();
Optional<CustomCropsWorld<?>> optional = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(player.getWorld());
if (optional.isEmpty()) {
handleFeedback(context, MessageConstants.COMMAND_DEBUG_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);
});
}
@Override
public String getFeatureID() {
return "unsafe_delete";
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) <2024> <XiaoMoMi>
*
* 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 <https://www.gnu.org/licenses/>.
*/
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.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.Map;
import java.util.Optional;
public class UnsafeRestoreCommand extends BukkitCommandFeature<CommandSender> {
public UnsafeRestoreCommand(CustomCropsCommandManager<CommandSender> commandManager) {
super(commandManager);
}
@Override
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.senderType(Player.class)
.flag(manager.flagBuilder("silent").build())
.handler(context -> {
Player player = context.sender();
World bukkitWorld = player.getWorld();
Optional<CustomCropsWorld<?>> optional = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(bukkitWorld);
if (optional.isEmpty()) {
handleFeedback(context, MessageConstants.COMMAND_DEBUG_RESTORE_FAILURE_WORLD, Component.text(bukkitWorld.getName()));
return;
}
ChunkPos chunkPos = ChunkPos.fromBukkitChunk(player.getLocation().getChunk());
CustomCropsWorld<?> world = optional.get();
Optional<CustomCropsChunk> chunk = world.getLoadedChunk(chunkPos);
if (chunk.isEmpty()) {
handleFeedback(context, MessageConstants.COMMAND_DEBUG_RESTORE_FAILURE_CHUNK);
return;
}
CustomCropsChunk customCropsChunk = chunk.get();
AbstractItemManager itemManager = BukkitCustomCropsPlugin.getInstance().getItemManager();
int totalBlocks = 0;
int restoredBlocks = 0;
for (CustomCropsSection section : customCropsChunk.sections()) {
for (Map.Entry<BlockPos, CustomCropsBlockState> entry : section.blockMap().entrySet()) {
totalBlocks++;
Pos3 pos3 = entry.getKey().toPos3(chunkPos);
Location location = pos3.toLocation(bukkitWorld);
String realID = itemManager.anyID(location);
if (!entry.getValue().type().isInstance(realID)) {
restoredBlocks++;
entry.getValue().type().restore(location, entry.getValue());
}
}
}
handleFeedback(context, MessageConstants.COMMAND_DEBUG_RESTORE_SUCCESS, Component.text(restoredBlocks), Component.text(totalBlocks));
});
}
@Override
public String getFeatureID() {
return "unsafe_restore";
}
}

View File

@@ -574,7 +574,7 @@ public class BukkitItemManager extends AbstractItemManager {
CustomCropsBlockState customCropsBlockState = optionalState.get();
String anyFurnitureID = furnitureID(location);
if (anyFurnitureID != null) {
if (!customCropsBlockState.type().isBlockInstance(anyFurnitureID)) {
if (!customCropsBlockState.type().isInstance(anyFurnitureID)) {
world.removeBlockState(pos3);
plugin.debug(() -> "[" + location.getWorld().getName() + "] Removed inconsistent block data at " + pos3 + " which used to be " + customCropsBlockState);
} else {
@@ -583,7 +583,7 @@ public class BukkitItemManager extends AbstractItemManager {
}
}
String anyBlockID = blockID(location);
if (!customCropsBlockState.type().isBlockInstance(anyBlockID)) {
if (!customCropsBlockState.type().isInstance(anyBlockID)) {
world.removeBlockState(pos3);
plugin.debug(() -> "[" + location.getWorld().getName() + "] Removed inconsistent block data at " + pos3 + " which used to be " + customCropsBlockState);
} else {

View File

@@ -86,4 +86,22 @@ force_tick:
permission: customcrops.command.force_tick
usage:
- /customcrops force-tick
- /ccrops force-tick
- /ccrops force-tick
# A command to restore the blocks by CustomCrops data in one chunk
# Usage: [COMMAND]
unsafe_restore:
enable: true
permission: customcrops.command.unsafe.restore
usage:
- /customcrops unsafe restore
- /ccrops unsafe restore
# A command to delete the CustomCrops data in one chunk
# Usage: [COMMAND]
unsafe_delete:
enable: true
permission: customcrops.command.unsafe.delete
usage:
- /customcrops unsafe delete
- /ccrops unsafe delete

View File

@@ -1,6 +1,11 @@
# Don"t change this
config-version: "38"
config-version: "41"
season.spring: "Spring"
season.summer: "Summer"
season.autumn: "Autumn"
season.winter: "Winter"
season.disable: "Disable"
exception.invalid_syntax: "<red>Invalid syntax. Correct syntax: <white><arg:0></white></red>"
exception.invalid_argument: "<red>Invalid argument. Reason: <white><arg:0></white></red>"
exception.invalid_sender: "<red><arg:0> is not allowed to execute that command. Must be of type <arg:1></red>"
@@ -57,8 +62,21 @@ command.date.set.failure.invalid: "<red>Invalid date [<arg:1>]</red>"
command.force_tick.success: "<white>Took <arg:0>ms ticking <arg:1> blocks</white>"
command.force_tick.failure.disable: "<red>CustomCrops is not enabled in world [<arg:0>]</red>"
command.force_tick.failure.type: "<red>Unknown type [<arg:0>]</red>"
season.spring: "Spring"
season.summer: "Summer"
season.autumn: "Autumn"
season.winter: "Winter"
season.disable: "Disable"
command.unsafe.delete.failure.world: "<red>CustomCrops is not enabled in world [<arg:0>]</red>"
command.unsafe.delete.success: "<white>Deleted block data in this chunk"
command.unsafe.restore.failure.world: "<red>CustomCrops is not enabled in world [<arg:0>]</red>"
command.unsafe.restore.failure.chunk: "<red>This chunk doesn't contain any data</red>"
command.unsafe.restore.success: "<white>Restored (<arg:0>/<arg:1>) blocks</white>"
command.debug.data.failure: "<red>No block selected</red>"
command.debug.data.success.vanilla: "<green>Vanilla block data: <hover:show_text:'<yellow>Copy'><click:copy_to_clipboard:'<arg:0>'><arg:0></click>"
command.debug.data.success.custom: "<gold>Custom block data: <hover:show_text:'<yellow>Copy'><click:copy_to_clipboard:'<arg:0>'><arg:0></click>"
command.debug.worlds.failure: "<red>There's no world loaded</red>"
command.debug.worlds.success:
- "<gold>World: <arg:0></gold>"
- " - Loaded regions: <arg:1>"
- " - Loaded chunks: <arg:2>"
- " - Lazy chunks: <arg:3>"
command.debug.insight.off: "<red>Insight mode: OFF</red>"
command.debug.insight.on:
- "<green>Insight mode: ON</green>"
- "<white>Note that this only shows a snapshot of the data."

View File

@@ -1,6 +1,11 @@
# 别动这个
config-version: "38"
config-version: "41"
season.spring: "春"
season.summer: "夏"
season.autumn: "秋"
season.winter: "冬"
season.disable: "未启用"
exception.invalid_syntax: "<red>无效语法. 正确语法:<white><arg:0></white></red>"
exception.invalid_argument: "<red>无效参数. 原因:<white><arg:0></white></red>"
exception.invalid_sender: "<red><arg:0> 不允许执行该命令. 执行者必须是 <arg:1></red>"
@@ -56,8 +61,21 @@ command.date.set.failure.invalid: "<red>无效的日期 [<arg:1>]</red>"
command.force_tick.success: "<white>花费 <arg:0>ms 更新了 <arg:1> 个方块</white>"
command.force_tick.failure.disable: "<red>CustomCrops没有在世界 [<arg:0>] 启用</red>"
command.force_tick.failure.type: "<red>未知的类型 [<arg:0>]</red>"
season.spring: "春"
season.summer: "夏"
season.autumn: "秋"
season.winter: "冬"
season.disable: "未启用"
command.unsafe.delete.failure.world: "<red>CustomCrops没有在世界 [<arg:0>] 启用</red>"
command.unsafe.delete.success: "<white>删除了这个区块的数据"
command.unsafe.restore.failure.world: "<red>CustomCrops没有在世界 [<arg:0>] 启用</red>"
command.unsafe.restore.failure.chunk: "<red>这个区块没有任何数据</red>"
command.unsafe.restore.success: "<white>恢复了 (<arg:0>/<arg:1>) 方块</white>"
command.debug.data.failure: "<red>未选中任何方块</red>"
command.debug.data.success.vanilla: "<green>原版方块数据: <hover:show_text:'<yellow>Copy'><click:copy_to_clipboard:'<arg:0>'><arg:0></click>"
command.debug.data.success.custom: "<gold>自定义方块数据: <hover:show_text:'<yellow>Copy'><click:copy_to_clipboard:'<arg:0>'><arg:0></click>"
command.debug.worlds.failure: "<red>没有农作物世界被加载</red>"
command.debug.worlds.success:
- "<gold>世界: <arg:0></gold>"
- " - 加载中的区域: <arg:1>"
- " - 加载中的区块: <arg:2>"
- " - 不活跃的区块: <arg:3>"
command.debug.insight.off: "<red>洞察模式: OFF</red>"
command.debug.insight.on:
- "<green>洞察模式: ON</green>"
- "<white>注意在这个模式下你只能看到数据的快照"