Skip to content

Commit

Permalink
Allow specifying names for watched chunks, and display ticket level c…
Browse files Browse the repository at this point in the history
…hanges for watched chunks
  • Loading branch information
pupnewfster committed Jan 4, 2025
1 parent 1b375fc commit e667948
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 39 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -1053,12 +1053,19 @@ private void addMisc() {
add(MekanismLang.HOLD_FOR_MODULES, "Hold %1$s for installed modules.");
add(MekanismLang.HOLD_FOR_SUPPORTED_ITEMS, "Hold %1$s for supporting items and conflicting modules.");
//Commands
add(MekanismLang.COMMAND_ERROR_NOT_WATCHED, "Chunk (%1$s) is not being watched.");
add(MekanismLang.COMMAND_CHUNK_WATCH, "Chunk (%1$s) added to watch list.");
add(MekanismLang.COMMAND_CHUNK_WATCH_NAMED, "Chunk %1$s (%2$s) added to watch list.");
add(MekanismLang.COMMAND_CHUNK_UNWATCH, "Chunk (%1$s) removed from watch list.");
add(MekanismLang.COMMAND_CHUNK_UNWATCH_NAMED, "Chunk %1$s (%2$s) removed from watch list.");
add(MekanismLang.COMMAND_CHUNK_CLEAR, "%1$s chunks removed from watch list.");
add(MekanismLang.COMMAND_CHUNK_FLUSH, "%1$s chunks unloaded.");
add(MekanismLang.COMMAND_CHUNK_LOADED, "Loaded chunk (%1$s).");
add(MekanismLang.COMMAND_CHUNK_LOADED_NAMED, "Loaded chunk %1$s (%2$s).");
add(MekanismLang.COMMAND_CHUNK_UNLOADED, "Unloaded chunk (%1$s).");
add(MekanismLang.COMMAND_CHUNK_UNLOADED_NAMED, "Unloaded chunk %1$s (%2$s).");
add(MekanismLang.COMMAND_CHUNK_TICKET_LEVEL_CHANGED, "Chunk (%1$s) ticket level changed from: %2$s to: %3$s.");
add(MekanismLang.COMMAND_CHUNK_TICKET_LEVEL_CHANGED_NAMED, "Chunk %1$s (%2$s) ticket level changed from: %3$s to: %4$s.");
add(MekanismLang.COMMAND_DEBUG, "Toggled debug mode: %1$s.");
add(MekanismLang.COMMAND_TEST_RULES, "Enabled keepInventory, and disabled doMobSpawning, doDaylightCycle, doWeatherCycle and mobGriefing!");
add(MekanismLang.COMMAND_TP, "Teleported to (%1$s) - saved last position on stack.");
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/mekanism/common/MekanismLang.java
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,19 @@ public enum MekanismLang implements ILangEntry {
HOLD_FOR_MODULES("tooltip", "hold_for_modules"),
HOLD_FOR_SUPPORTED_ITEMS("tooltip", "hold_for_supported_items"),
//Commands
COMMAND_ERROR_NOT_WATCHED("command", "error.watch.not_watched"),
COMMAND_CHUNK_WATCH("command", "chunk.watch"),
COMMAND_CHUNK_WATCH_NAMED("command", "chunk.watch.named"),
COMMAND_CHUNK_UNWATCH("command", "chunk.unwatch"),
COMMAND_CHUNK_UNWATCH_NAMED("command", "chunk.unwatch.named"),
COMMAND_CHUNK_CLEAR("command", "chunk.clear"),
COMMAND_CHUNK_FLUSH("command", "chunk.flush"),
COMMAND_CHUNK_LOADED("command", "chunk.loaded"),
COMMAND_CHUNK_LOADED_NAMED("command", "chunk.loaded.named"),
COMMAND_CHUNK_UNLOADED("command", "chunk.unloaded"),
COMMAND_CHUNK_UNLOADED_NAMED("command", "chunk.unloaded.named"),
COMMAND_CHUNK_TICKET_LEVEL_CHANGED("command", "chunk.ticket_level_changed"),
COMMAND_CHUNK_TICKET_LEVEL_CHANGED_NAMED("command", "chunk.ticket_level_changed.named"),
COMMAND_DEBUG("command", "debug"),
COMMAND_TEST_RULES("command", "testrules"),
COMMAND_TP("command", "tp"),
Expand Down
135 changes: 102 additions & 33 deletions src/main/java/mekanism/common/command/ChunkCommand.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,47 @@
package mekanism.common.command;

import com.mojang.brigadier.Command;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.ArgumentBuilder;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import com.mojang.brigadier.context.CommandContext;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import mekanism.api.text.EnumColor;
import mekanism.api.text.ILangEntry;
import mekanism.api.text.TextComponentUtil;
import mekanism.common.MekanismLang;
import mekanism.common.base.MekanismPermissions;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.coordinates.ColumnPosArgument;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ColumnPos;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.level.ChunkEvent;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.neoforge.event.level.ChunkTicketLevelUpdatedEvent;
import org.jetbrains.annotations.Nullable;

public class ChunkCommand {

private ChunkCommand() {
}

private static final LongSet chunkWatchers = new LongOpenHashSet();
private static final String NAME_PARAM = "name";
private static final String POS_PARAM = "pos";

private static final LangData WATCH = new LangData(MekanismLang.COMMAND_CHUNK_WATCH, MekanismLang.COMMAND_CHUNK_WATCH_NAMED);
private static final LangData UNWATCH = new LangData(MekanismLang.COMMAND_CHUNK_UNWATCH, MekanismLang.COMMAND_CHUNK_UNWATCH_NAMED);
private static final LangData LOADED = new LangData(MekanismLang.COMMAND_CHUNK_LOADED, MekanismLang.COMMAND_CHUNK_LOADED_NAMED);
private static final LangData UNLOADED = new LangData(MekanismLang.COMMAND_CHUNK_UNLOADED, MekanismLang.COMMAND_CHUNK_UNLOADED_NAMED);
//TODO: Allow specifying watches for chunks in different dimensions?
private static final Long2ObjectMap<ChunkWatchSettings> chunkWatchers = new Long2ObjectOpenHashMap<>();

static ArgumentBuilder<CommandSourceStack, ?> register() {
NeoForge.EVENT_BUS.register(ChunkCommand.class);
Expand All @@ -42,20 +58,30 @@ private static class WatchCommand {
static ArgumentBuilder<CommandSourceStack, ?> register() {
return Commands.literal("watch")
.requires(MekanismPermissions.COMMAND_CHUNK_WATCH)
.executes(ctx -> {
CommandSourceStack source = ctx.getSource();
return watch(source, new ChunkPos(BlockPos.containing(source.getPosition())));
}).then(Commands.argument("pos", ColumnPosArgument.columnPos())
.executes(ctx -> {
ColumnPos column = ColumnPosArgument.getColumnPos(ctx, "pos");
return watch(ctx.getSource(), column.toChunkPos());
}));
.executes(ctx -> watch(ctx, false, false))
.then(Commands.argument(POS_PARAM, ColumnPosArgument.columnPos())
.executes(ctx -> watch(ctx, true, false))
.then(Commands.argument(NAME_PARAM, StringArgumentType.word())
.executes(ctx -> watch(ctx, true, true))
)
)
.then(Commands.argument(NAME_PARAM, StringArgumentType.word())
.executes(ctx -> watch(ctx, false, true))
);
}

private static int watch(CommandSourceStack source, ChunkPos chunkPos) {
chunkWatchers.add(ChunkPos.asLong(chunkPos.x, chunkPos.z));
source.sendSuccess(() -> MekanismLang.COMMAND_CHUNK_WATCH.translateColored(EnumColor.GRAY, EnumColor.INDIGO, getPosition(chunkPos)), true);
return 0;
private static int watch(CommandContext<CommandSourceStack> ctx, boolean positionFromArgument, boolean hasName) {
ChunkPos chunkPos;
if (positionFromArgument) {
chunkPos = ColumnPosArgument.getColumnPos(ctx, POS_PARAM).toChunkPos();
} else {
chunkPos = new ChunkPos(BlockPos.containing(ctx.getSource().getPosition()));
}
String name = hasName ? StringArgumentType.getString(ctx, NAME_PARAM) : null;
ChunkWatchSettings settings = new ChunkWatchSettings(name, chunkPos);
chunkWatchers.put(ChunkPos.asLong(chunkPos.x, chunkPos.z), settings);
ctx.getSource().sendSuccess(() -> settings.translate(WATCH), true);
return Command.SINGLE_SUCCESS;
}
}

Expand All @@ -67,17 +93,21 @@ private static class UnwatchCommand {
.executes(ctx -> {
CommandSourceStack source = ctx.getSource();
return unwatch(source, new ChunkPos(BlockPos.containing(source.getPosition())));
}).then(Commands.argument("pos", ColumnPosArgument.columnPos())
}).then(Commands.argument(POS_PARAM, ColumnPosArgument.columnPos())
.executes(ctx -> {
ColumnPos column = ColumnPosArgument.getColumnPos(ctx, "pos");
ColumnPos column = ColumnPosArgument.getColumnPos(ctx, POS_PARAM);
return unwatch(ctx.getSource(), column.toChunkPos());
}));
}

private static int unwatch(CommandSourceStack source, ChunkPos chunkPos) {
chunkWatchers.remove(ChunkPos.asLong(chunkPos.x, chunkPos.z));
source.sendSuccess(() -> MekanismLang.COMMAND_CHUNK_UNWATCH.translateColored(EnumColor.GRAY, EnumColor.INDIGO, getPosition(chunkPos)), true);
return 0;
ChunkWatchSettings settings = chunkWatchers.remove(ChunkPos.asLong(chunkPos.x, chunkPos.z));
if (settings == null) {
source.sendFailure(MekanismLang.COMMAND_ERROR_NOT_WATCHED.translate(MekanismLang.GENERIC_WITH_COMMA.translate(chunkPos.x, chunkPos.z)));
return 0;
}
source.sendSuccess(() -> settings.translate(UNWATCH), true);
return Command.SINGLE_SUCCESS;
}
}

Expand All @@ -90,7 +120,7 @@ private static class ClearCommand {
int count = chunkWatchers.size();
chunkWatchers.clear();
ctx.getSource().sendSuccess(() -> MekanismLang.COMMAND_CHUNK_CLEAR.translateColored(EnumColor.GRAY, EnumColor.INDIGO, count), true);
return 0;
return Command.SINGLE_SUCCESS;
});
}
}
Expand All @@ -106,37 +136,76 @@ private static class FlushCommand {
int startCount = sp.getLoadedChunksCount();
//TODO: Check this
//sp.queueUnloadAll();
sp.tick(() -> false, false);
sp.tick(() -> true, false);
source.sendSuccess(() -> MekanismLang.COMMAND_CHUNK_FLUSH.translateColored(EnumColor.GRAY, EnumColor.INDIGO, startCount - sp.getLoadedChunksCount()), true);
return 0;
return Command.SINGLE_SUCCESS;
});
}
}

@SubscribeEvent
public static void onChunkLoad(ChunkEvent.Load event) {
handleChunkEvent(event, MekanismLang.COMMAND_CHUNK_LOADED);
handleChunkEvent(event, LOADED);
}

@SubscribeEvent
public static void onChunkUnload(ChunkEvent.Unload event) {
handleChunkEvent(event, MekanismLang.COMMAND_CHUNK_UNLOADED);
handleChunkEvent(event, UNLOADED);
}

private static void handleChunkEvent(ChunkEvent event, ILangEntry direction) {
if (event.getLevel() == null || event.getLevel().isClientSide()) {
@SubscribeEvent
public static void onTicketLevelChange(ChunkTicketLevelUpdatedEvent event) {
if (chunkWatchers.isEmpty() || event.getLevel().players().isEmpty()) {
return;
}
ChunkPos pos = event.getChunk().getPos();
if (chunkWatchers.contains(pos.toLong())) {
Component message = direction.translateColored(EnumColor.GRAY, EnumColor.INDIGO, getPosition(pos));
ChunkWatchSettings settings = chunkWatchers.get(event.getChunkPos());
if (settings != null) {
Component message = settings.translateTicketLevel(event.getOldTicketLevel(), event.getNewTicketLevel());
for (Player player : event.getLevel().players()) {
player.sendSystemMessage(message);
}
}
}

private static Component getPosition(ChunkPos pos) {
return MekanismLang.GENERIC_WITH_COMMA.translate(pos.x, pos.z);
private static void handleChunkEvent(ChunkEvent event, LangData direction) {
LevelAccessor level = event.getLevel();
if (level != null && !level.isClientSide()) {
if (chunkWatchers.isEmpty() || level.players().isEmpty()) {
return;
}
ChunkWatchSettings settings = chunkWatchers.get(event.getChunk().getPos().toLong());
if (settings != null) {
Component message = settings.translate(direction);
for (Player player : level.players()) {
player.sendSystemMessage(message);
}
}
}
}

private record LangData(ILangEntry unnamed, ILangEntry named) {
}

private record ChunkWatchSettings(Component name, Component position) {

private ChunkWatchSettings(@Nullable String name, ChunkPos pos) {
this(name == null ? CommonComponents.EMPTY : TextComponentUtil.getString(name), MekanismLang.GENERIC_WITH_COMMA.translate(pos.x, pos.z));
}

public Component translate(LangData langData) {
if (name == CommonComponents.EMPTY) {
return langData.unnamed().translateColored(EnumColor.GRAY, EnumColor.INDIGO, position);
}
return langData.named().translateColored(EnumColor.GRAY, EnumColor.INDIGO, name, EnumColor.INDIGO, position);
}

public Component translateTicketLevel(int oldLevel, int newLevel) {
if (name == CommonComponents.EMPTY) {
return MekanismLang.COMMAND_CHUNK_TICKET_LEVEL_CHANGED.translateColored(EnumColor.GRAY, EnumColor.INDIGO, position, EnumColor.INDIGO, oldLevel,
EnumColor.INDIGO, newLevel);
}
return MekanismLang.COMMAND_CHUNK_TICKET_LEVEL_CHANGED_NAMED.translateColored(EnumColor.GRAY, EnumColor.INDIGO, name, EnumColor.INDIGO, position,
EnumColor.INDIGO, oldLevel, EnumColor.INDIGO, newLevel);
}
}
}

0 comments on commit e667948

Please sign in to comment.