mirror of
https://github.com/Xiao-MoMi/Custom-Crops.git
synced 2025-12-28 03:19:15 +00:00
force tick
This commit is contained in:
@@ -40,7 +40,8 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
|
||||
new GetSeasonCommand(this),
|
||||
new SetSeasonCommand(this),
|
||||
new GetDateCommand(this),
|
||||
new SetDateCommand(this)
|
||||
new SetDateCommand(this),
|
||||
new ForceTickCommand(this)
|
||||
);
|
||||
|
||||
private final Index<String, CommandFeature<CommandSender>> INDEX = Index.create(CommandFeature::getFeatureID, FEATURES);
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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.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 net.momirealms.customcrops.common.util.Key;
|
||||
import net.momirealms.customcrops.common.util.QuadConsumer;
|
||||
import net.momirealms.customcrops.common.util.TriConsumer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.CommandManager;
|
||||
import org.incendo.cloud.bukkit.parser.NamespacedKeyParser;
|
||||
import org.incendo.cloud.bukkit.parser.WorldParser;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.standard.EnumParser;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ForceTickCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
public ForceTickCommand(CustomCropsCommandManager<CommandSender> commandManager) {
|
||||
super(commandManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||
return builder
|
||||
.required("world", WorldParser.worldParser())
|
||||
.required("type", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() {
|
||||
@Override
|
||||
public @NonNull CompletableFuture<? extends @NonNull Iterable<? extends @NonNull Suggestion>> suggestionsFuture(@NonNull CommandContext<Object> context, @NonNull CommandInput input) {
|
||||
int all = Registries.BLOCK.size();
|
||||
ArrayList<CustomCropsBlock> blocks = new ArrayList<>();
|
||||
for (int i = 0; i < all; i++) {
|
||||
blocks.add(Registries.BLOCK.byId(i));
|
||||
}
|
||||
return CompletableFuture.completedFuture(
|
||||
blocks.stream().map(block -> Suggestion.suggestion(block.type().asString())).toList()
|
||||
);
|
||||
}
|
||||
}))
|
||||
.required("mode", EnumParser.enumParser(Mode.class))
|
||||
.flag(manager.flagBuilder("silent").build())
|
||||
.handler(context -> {
|
||||
World world = context.get("world");
|
||||
NamespacedKey type = context.get("type");
|
||||
Mode mode = context.get("mode");
|
||||
Key key = Key.key(type.asString());
|
||||
CustomCropsBlock customCropsBlock = Registries.BLOCK.get(key);
|
||||
if (customCropsBlock == null) {
|
||||
handleFeedback(context.sender(), MessageConstants.COMMAND_FORCE_TICK_FAILURE_TYPE, Component.text(key.asString()));
|
||||
return;
|
||||
}
|
||||
Optional<CustomCropsWorld<?>> optionalWorld = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(world);
|
||||
if (optionalWorld.isEmpty()) {
|
||||
handleFeedback(context.sender(), MessageConstants.COMMAND_FORCE_TICK_FAILURE_DISABLE, Component.text(world.getName()));
|
||||
return;
|
||||
}
|
||||
CustomCropsWorld<?> customCropsWorld = optionalWorld.get();
|
||||
BukkitCustomCropsPlugin.getInstance().getScheduler().async().execute(() -> {
|
||||
int amount = 0;
|
||||
long time1 = System.currentTimeMillis();
|
||||
for (CustomCropsChunk customCropsChunk : customCropsWorld.loadedChunks()) {
|
||||
for (CustomCropsSection customCropsSection : customCropsChunk.sections()) {
|
||||
for (Map.Entry<BlockPos, CustomCropsBlockState> entry : customCropsSection.blockMap().entrySet()) {
|
||||
CustomCropsBlockState state = entry.getValue();
|
||||
if (state.type() == customCropsBlock) {
|
||||
Pos3 pos3 = entry.getKey().toPos3(customCropsChunk.chunkPos());
|
||||
mode.consumer.accept(customCropsBlock, state, customCropsWorld, pos3);
|
||||
amount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
handleFeedback(context.sender(), MessageConstants.COMMAND_FORCE_TICK_SUCCESS, Component.text(System.currentTimeMillis() - time1), Component.text(amount));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private enum Mode {
|
||||
|
||||
RANDOM_TICK(CustomCropsBlock::randomTick),
|
||||
SCHEDULED_TICK(CustomCropsBlock::scheduledTick),
|
||||
ALL((b, s, w, p) -> {
|
||||
b.randomTick(s, w, p);
|
||||
b.scheduledTick(s, w, p);
|
||||
});
|
||||
|
||||
private final QuadConsumer<CustomCropsBlock, CustomCropsBlockState, CustomCropsWorld<?>, Pos3> consumer;
|
||||
|
||||
Mode(QuadConsumer<CustomCropsBlock, CustomCropsBlockState, CustomCropsWorld<?>, Pos3> consumer) {
|
||||
this.consumer = consumer;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFeatureID() {
|
||||
return "force_tick";
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,9 @@ import net.momirealms.customcrops.api.core.*;
|
||||
import net.momirealms.customcrops.api.core.block.BreakReason;
|
||||
import net.momirealms.customcrops.api.core.block.CustomCropsBlock;
|
||||
import net.momirealms.customcrops.api.core.item.CustomCropsItem;
|
||||
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.WrappedInteractAirEvent;
|
||||
import net.momirealms.customcrops.api.core.wrapper.WrappedInteractEvent;
|
||||
@@ -454,8 +456,23 @@ public class BukkitItemManager extends AbstractItemManager {
|
||||
return;
|
||||
}
|
||||
|
||||
String itemID = id(itemInHand);
|
||||
CustomCropsWorld<?> world = optionalWorld.get();
|
||||
Pos3 pos3 = Pos3.from(location);
|
||||
Optional<CustomCropsBlockState> optionalState = world.getBlockState(pos3);
|
||||
if (optionalState.isPresent()) {
|
||||
CustomCropsBlockState customCropsBlockState = optionalState.get();
|
||||
String anyID = anyID(location);
|
||||
System.out.println(anyID);
|
||||
if (!customCropsBlockState.type().isBlockInstance(anyID)) {
|
||||
world.removeBlockState(pos3);
|
||||
plugin.debug("[" + location.getWorld().getName() + "] Removed inconsistent block data at " + pos3 + " which used to be " + customCropsBlockState);
|
||||
} else {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String itemID = id(itemInHand);
|
||||
WrappedPlaceEvent wrapped = new WrappedPlaceEvent(player, world, location, placedID, hand, itemInHand, itemID, event);
|
||||
CustomCropsBlock customCropsBlock = Registries.BLOCKS.get(placedID);
|
||||
if (customCropsBlock != null) {
|
||||
|
||||
@@ -50,3 +50,10 @@ debug_data:
|
||||
usage:
|
||||
- /customcrops debug data
|
||||
- /ccrops debug data
|
||||
|
||||
force_tick:
|
||||
enable: true
|
||||
permission: customcrops.command.force_tick
|
||||
usage:
|
||||
- /customcrops force-tick
|
||||
- /ccrops force-tick
|
||||
@@ -54,6 +54,9 @@ command.date.set.failure.disable: "<red>Date is disabled in world [<arg:0>]</red
|
||||
command.date.set.failure.reference: "<red>World [<arg:0>] is not the reference world</red>"
|
||||
command.date.set.failure.other: "<red>Can't set date for world [<arg:0>] because plugin [<arg:1>] takes over the calendar</red>"
|
||||
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"
|
||||
|
||||
@@ -53,6 +53,9 @@ command.date.set.success: "<white>成功设置世界 [<arg:0>] 的日期为 [<ar
|
||||
command.date.set.failure.reference: "<red>世界 [<arg:0>] 不是同步季节设置的参考世界</red>"
|
||||
command.date.set.failure.other: "<red>无法设置世界 [<arg:0>] 的日期,原因是插件 [<arg:1>] 接管了日历</red>"
|
||||
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: "秋"
|
||||
|
||||
Reference in New Issue
Block a user