From b2ab8c4f2a0ab61257ac4a65f8a5b66ed079edc3 Mon Sep 17 00:00:00 2001 From: UnRealDinnerbone Date: Wed, 21 Aug 2024 10:00:50 -0500 Subject: [PATCH 1/6] feat: add open_gui_as command and improve claim gui --- .../ftb/mods/ftbchunks/FTBChunksCommands.java | 13 + .../ftb/mods/ftbchunks/api/ChunkTeamData.java | 48 +- .../ftbchunks/client/FTBChunksClient.java | 10 +- .../ftbchunks/client/gui/ChunkScreen.java | 580 ++++++++---------- .../client/gui/ChunkScreenPanel.java | 363 +++++++++++ .../ftbchunks/data/ChunkTeamDataImpl.java | 17 +- .../net/ChunkChangeResponsePacket.java | 4 +- .../ftb/mods/ftbchunks/net/FTBChunksNet.java | 1 + .../ftbchunks/net/OpenClaimGUIPacket.java | 47 ++ .../net/RequestChunkChangePacket.java | 43 +- .../assets/ftbchunks/lang/en_us.json | 6 + .../assets/ftbchunks/textures/checkered.png | Bin 0 -> 300 bytes gradle.properties | 8 +- 13 files changed, 789 insertions(+), 351 deletions(-) create mode 100644 common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/ChunkScreenPanel.java create mode 100644 common/src/main/java/dev/ftb/mods/ftbchunks/net/OpenClaimGUIPacket.java create mode 100644 common/src/main/resources/assets/ftbchunks/textures/checkered.png diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/FTBChunksCommands.java b/common/src/main/java/dev/ftb/mods/ftbchunks/FTBChunksCommands.java index 2fb4afdb..bce00bfb 100644 --- a/common/src/main/java/dev/ftb/mods/ftbchunks/FTBChunksCommands.java +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/FTBChunksCommands.java @@ -1,5 +1,6 @@ package dev.ftb.mods.ftbchunks; +import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; @@ -18,6 +19,7 @@ import dev.ftb.mods.ftbchunks.data.ClaimedChunkManagerImpl; import dev.ftb.mods.ftbchunks.net.AddWaypointPacket; import dev.ftb.mods.ftbchunks.net.LoadedChunkViewPacket; +import dev.ftb.mods.ftbchunks.net.OpenClaimGUIPacket; import dev.ftb.mods.ftbchunks.net.RequestBlockColorPacket; import dev.ftb.mods.ftbchunks.net.SendGeneralDataPacket; import dev.ftb.mods.ftblibrary.math.ChunkDimPos; @@ -179,6 +181,11 @@ public static void registerCommands(CommandDispatcher dispat .executes(context -> viewLoadedChunks(context.getSource(), DimensionArgument.getDimension(context, "dimension"))) ) ) + .then(Commands.literal("open_claim_gui_as") + .then(Commands.argument("team", TeamArgument.create()) + .executes(FTBChunksCommands::openClaimGuiAs) + ) + ) ) .then(Commands.literal("block_color") // .requires(source -> source.getServer().isSingleplayer()) @@ -239,6 +246,12 @@ private static int bypassProtection(CommandSourceStack source) throws CommandSyn return 1; } + private static int openClaimGuiAs(CommandContext context) throws CommandSyntaxException { + Team team = TeamArgument.get(context, "team"); + NetworkManager.sendToPlayer(context.getSource().getPlayerOrException(), new OpenClaimGUIPacket(team.getTeamId())); + return Command.SINGLE_SUCCESS; + } + private interface ChunkCallback { void accept(ChunkTeamDataImpl data, ChunkDimPos pos) throws CommandSyntaxException; } diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/api/ChunkTeamData.java b/common/src/main/java/dev/ftb/mods/ftbchunks/api/ChunkTeamData.java index e1233103..65276c76 100644 --- a/common/src/main/java/dev/ftb/mods/ftbchunks/api/ChunkTeamData.java +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/api/ChunkTeamData.java @@ -69,10 +69,36 @@ public interface ChunkTeamData { * @param source the command source (player or console) unclaiming the chunk * @param pos the combined dimension and chunk pos * @param checkOnly true if just simulating the unclaim + * @param adminOverride if true, admins can unclaim regardless chunk ownership * * @return the result of the attempt */ - ClaimResult unclaim(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly); + ClaimResult unclaim(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly, boolean adminOverride); + + /** + * Try to release any claim on the given chunk for this team. + * + * @param source the command source (player or console) unclaiming the chunk + * @param pos the combined dimension and chunk pos + * @param checkOnly true if just simulating the unclaim + * + * @return the result of the attempt + */ + default ClaimResult unclaim(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly) { + return unclaim(source, pos, checkOnly, true); + } + + /** + * Try to force-load the given chunk for this team. + * + * @param source the command source (player or console) force-loading the chunk + * @param pos the combined dimension and chunk pos + * @param checkOnly true if just simulating the force-load + * @param adminOverride if true, admins can force-load regardless chunk ownership + * + * @return the result of the attempt + */ + ClaimResult forceLoad(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly, boolean adminOverride); /** * Try to force-load the given chunk for this team. @@ -83,7 +109,21 @@ public interface ChunkTeamData { * * @return the result of the attempt */ - ClaimResult forceLoad(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly); + default ClaimResult forceLoad(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly) { + return forceLoad(source, pos, checkOnly, true); + } + + /** + * Try to cancel any force-load this team has for the given chunk. + * + * @param source the command source (player or console) un-force-loading the chunk + * @param pos the combined dimension and chunk pos + * @param checkOnly true if just simulating the un-force-load + * @param adminOverride if true, admins can un-force regardless chunk ownership + * + * @return the un-force-load result + */ + ClaimResult unForceLoad(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly, boolean adminOverride); /** * Try to cancel any force-load this team has for the given chunk. @@ -94,7 +134,9 @@ public interface ChunkTeamData { * * @return the un-force-load result */ - ClaimResult unForceLoad(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly); + default ClaimResult unForceLoad(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly) { + return unForceLoad(source, pos, checkOnly, true); + } /** * Convenience method to check if the given player ID is a member of this team diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/client/FTBChunksClient.java b/common/src/main/java/dev/ftb/mods/ftbchunks/client/FTBChunksClient.java index 14f55a64..481dd3ef 100644 --- a/common/src/main/java/dev/ftb/mods/ftbchunks/client/FTBChunksClient.java +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/client/FTBChunksClient.java @@ -366,7 +366,11 @@ public EventResult keyPressed(Minecraft client, int keyCode, int scanCode, int a FTBChunksClientConfig.saveConfig(); return EventResult.interruptTrue(); } else if (doesKeybindMatch(openClaimManagerKey, keyCode, scanCode, modifiers)) { - ChunkScreen.openChunkScreen(); + try { + ChunkScreen.openChunkScreen(); + }catch (Exception e){ + e.printStackTrace(); + } return EventResult.interruptTrue(); } else if (doesKeybindMatch(zoomInKey, keyCode, scanCode, modifiers)) { return changeZoom(true); @@ -1167,6 +1171,10 @@ public List getChunkSummary() { return list; } + public GeneralChunkData getGeneralChunkData() { + return generalChunkData; + } + public int getMinimapTextureId() { return minimapTextureId; } diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/ChunkScreen.java b/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/ChunkScreen.java index cc149092..156c4933 100644 --- a/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/ChunkScreen.java +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/ChunkScreen.java @@ -1,339 +1,269 @@ package dev.ftb.mods.ftbchunks.client.gui; -import com.mojang.blaze3d.platform.InputConstants; -import com.mojang.blaze3d.systems.RenderSystem; -import dev.architectury.networking.NetworkManager; import dev.ftb.mods.ftbchunks.FTBChunks; -import dev.ftb.mods.ftbchunks.FTBChunksWorldConfig; -import dev.ftb.mods.ftbchunks.api.ClaimResult; -import dev.ftb.mods.ftbchunks.api.FTBChunksAPI; -import dev.ftb.mods.ftbchunks.api.client.icon.MapType; import dev.ftb.mods.ftbchunks.client.FTBChunksClient; -import dev.ftb.mods.ftbchunks.client.map.MapChunk; import dev.ftb.mods.ftbchunks.client.map.MapDimension; -import dev.ftb.mods.ftbchunks.client.map.MapManager; -import dev.ftb.mods.ftbchunks.client.map.RenderMapImageTask; -import dev.ftb.mods.ftbchunks.net.RequestChunkChangePacket; -import dev.ftb.mods.ftbchunks.net.RequestMapDataPacket; -import dev.ftb.mods.ftbchunks.net.UpdateForceLoadExpiryPacket; +import dev.ftb.mods.ftbchunks.net.SendGeneralDataPacket; import dev.ftb.mods.ftblibrary.icon.Color4I; -import dev.ftb.mods.ftblibrary.icon.FaceIcon; import dev.ftb.mods.ftblibrary.icon.Icons; -import dev.ftb.mods.ftblibrary.icon.ImageIcon; -import dev.ftb.mods.ftblibrary.math.MathUtils; -import dev.ftb.mods.ftblibrary.math.XZ; -import dev.ftb.mods.ftblibrary.ui.*; -import dev.ftb.mods.ftblibrary.ui.input.Key; -import dev.ftb.mods.ftblibrary.ui.input.MouseButton; +import dev.ftb.mods.ftblibrary.ui.Button; +import dev.ftb.mods.ftblibrary.ui.Panel; +import dev.ftb.mods.ftblibrary.ui.SimpleButton; +import dev.ftb.mods.ftblibrary.ui.Theme; +import dev.ftb.mods.ftblibrary.ui.ToggleableButton; +import dev.ftb.mods.ftblibrary.ui.misc.AbstractThreePanelScreen; import dev.ftb.mods.ftblibrary.ui.misc.KeyReferenceScreen; -import dev.ftb.mods.ftblibrary.util.TimeUtils; import dev.ftb.mods.ftblibrary.util.TooltipList; -import dev.ftb.mods.ftbteams.api.property.TeamProperties; +import dev.ftb.mods.ftbteams.api.Team; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.screens.Screen; +import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.ChunkPos; -import org.lwjgl.glfw.GLFW; - -import java.util.*; - -import static dev.ftb.mods.ftbchunks.net.RequestChunkChangePacket.ChunkChangeOp; - -public class ChunkScreen extends BaseScreen { - private static final ImageIcon FORCE_LOAD_ICON = new ImageIcon(FTBChunksAPI.rl("textures/force_loaded.png")); - - private final MapDimension dimension; - private final List chunkButtons = new ArrayList<>(); - private final Set selectedChunks = new HashSet<>(); - private ChunkUpdateInfo updateInfo; - - public ChunkScreen(MapDimension dimension) { - RenderMapImageTask.setAlwaysRenderChunksOnMap(true); - - this.dimension = dimension; - - MapManager.getInstance().ifPresent(m -> m.updateAllRegions(false)); - } - - public static void openChunkScreen() { - MapDimension.getCurrent().ifPresentOrElse( - mapDimension -> new ChunkScreen(mapDimension).openGui(), - () -> FTBChunks.LOGGER.warn("MapDimension data missing?? not opening chunk screen") - ); - } - - - public static void notifyChunkUpdates(int totalChunks, int changedChunks, EnumMap problems) { - if (Minecraft.getInstance().screen instanceof ScreenWrapper sw && sw.getGui() instanceof ChunkScreen cs) { - cs.updateInfo = new ChunkUpdateInfo(totalChunks, changedChunks, problems, Minecraft.getInstance().level.getGameTime()); - } - } - - @Override - public boolean onInit() { - return setFullscreen(); - } - - @Override - public void onClosed() { - RenderMapImageTask.setAlwaysRenderChunksOnMap(false); - - MapManager.getInstance().ifPresent(m -> m.updateAllRegions(false)); - - super.onClosed(); - } - - @Override - public void addWidgets() { - int sx = getX() + (width - FTBChunks.MINIMAP_SIZE) / 2; - int sy = getY() + (height - FTBChunks.MINIMAP_SIZE) / 2; - Player player = Minecraft.getInstance().player; - ChunkPos chunkPos = player.chunkPosition(); - int startX = chunkPos.x - FTBChunks.TILE_OFFSET; - int startZ = chunkPos.z - FTBChunks.TILE_OFFSET; - - chunkButtons.clear(); - for (int z = 0; z < FTBChunks.TILES; z++) { - for (int x = 0; x < FTBChunks.TILES; x++) { - ChunkButton button = new ChunkButton(this, XZ.of(startX + x, startZ + z)); - chunkButtons.add(button); - button.setPos(sx + x * FTBChunks.TILE_SIZE, sy + z * FTBChunks.TILE_SIZE); - } - } - - addAll(chunkButtons); - NetworkManager.sendToServer(new RequestMapDataPacket( - chunkPos.x - FTBChunks.TILE_OFFSET, chunkPos.z - FTBChunks.TILE_OFFSET, - chunkPos.x + FTBChunks.TILE_OFFSET, chunkPos.z + FTBChunks.TILE_OFFSET) - ); - - add(new SimpleButton(this, Component.translatable("ftbchunks.gui.large_map"), Icons.MAP, - (simpleButton, mouseButton) -> LargeMapScreen.openMap() - ).setPosAndSize(1, 1, 16, 16)); - - add(new SimpleButton(this, Component.translatable("ftbchunks.gui.chunk_info"), Icons.INFO, - (btn, mb) -> new ChunkMouseReferenceScreen().openGui() - ).setPosAndSize(1, 19, 16, 16)); - } - - @Override - public void mouseReleased(MouseButton button) { - super.mouseReleased(button); - - if (!selectedChunks.isEmpty()) { - NetworkManager.sendToServer(new RequestChunkChangePacket(ChunkChangeOp.create(button.isLeft(), isShiftKeyDown()), selectedChunks)); - selectedChunks.clear(); - playClickSound(); - } - } - - @Override - public boolean keyPressed(Key key) { - if (FTBChunksWorldConfig.playerHasMapStage(Minecraft.getInstance().player) && (key.is(GLFW.GLFW_KEY_M) || key.is(GLFW.GLFW_KEY_C))) { - LargeMapScreen.openMap(); - return true; - } - - return super.keyPressed(key); - } - - @Override - public void drawBackground(GuiGraphics graphics, Theme theme, int x, int y, int w, int h) { - Player player = Minecraft.getInstance().player; - - int sx = x + (w - FTBChunks.MINIMAP_SIZE) / 2; - int sy = y + (h - FTBChunks.MINIMAP_SIZE) / 2; - - RenderSystem.setShaderTexture(0, FTBChunksClient.INSTANCE.getMinimapTextureId()); - GuiHelper.drawTexturedRect(graphics, sx, sy, FTBChunks.MINIMAP_SIZE, FTBChunks.MINIMAP_SIZE, Color4I.WHITE, 0F, 0F, 1F, 1F); - - if (!InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_KEY_TAB)) { - for (int gy = 1; gy < FTBChunks.TILES; gy++) { - graphics.hLine(sx, sx + FTBChunks.MINIMAP_SIZE, sy + gy * FTBChunks.TILE_SIZE, 0x64464646); - } - for (int gx = 1; gx < FTBChunks.TILES; gx++) { - graphics.vLine(sx + gx * FTBChunks.TILE_SIZE, sy, sy + FTBChunks.MINIMAP_SIZE, 0x64464646); - } - } - - double hx = sx + FTBChunks.TILE_SIZE * FTBChunks.TILE_OFFSET + MathUtils.mod(player.getX(), 16D); - double hy = sy + FTBChunks.TILE_SIZE * FTBChunks.TILE_OFFSET + MathUtils.mod(player.getZ(), 16D); - new PointerIcon().draw(MapType.LARGE_MAP, graphics, (int) (hx - 4D), (int) (hy - 4D), 8, 8, false, 255); - FaceIcon.getFace(player.getGameProfile()).draw(graphics, (int) (hx - 4D), (int) (hy - 4D), 8, 8); - - List list = FTBChunksClient.INSTANCE.getChunkSummary(); - int fh = theme.getFontHeight() + 1; - for (int i = 0; i < list.size(); i++) { - theme.drawString(graphics, list.get(i), 3, getScreen().getGuiScaledHeight() - fh * (list.size() - i) - 1, Color4I.WHITE, Theme.SHADOW); - } - - if (updateInfo != null && updateInfo.shouldDisplay()) { - theme.drawString(graphics, updateInfo.summary(), sx + 2, sy + 2, Theme.SHADOW); - int line = 1; - for (Map.Entry entry : updateInfo.problems.entrySet()) { - ClaimResult.StandardProblem problem = entry.getKey(); - int count = entry.getValue(); - theme.drawString(graphics, problem.getMessage().append(": " + count), sx + 2, sy + 5 + theme.getFontHeight() * line++, Theme.SHADOW); - } - } - } - - private static class ChunkMouseReferenceScreen extends KeyReferenceScreen { - public ChunkMouseReferenceScreen() { - super("ftbchunks.gui.chunk_info.text"); - } - - @Override - public Component getTitle() { - return Component.translatable("ftbchunks.gui.chunk_info"); - } - } - - private class ChunkButton extends Button { - private final XZ chunkPos; - private final MapChunk chunk; - private long lastAdjust = 0L; - - public ChunkButton(Panel panel, XZ xz) { - super(panel, Component.empty(), Color4I.empty()); - setSize(FTBChunks.TILE_SIZE, FTBChunks.TILE_SIZE); - chunkPos = xz; - chunk = dimension.getRegion(XZ.regionFromChunk(chunkPos.x(), chunkPos.z())).getDataBlocking().getChunk(chunkPos); - } - - @Override - public void onClicked(MouseButton mouseButton) { - selectedChunks.add(chunkPos); - } - - @Override - public void drawBackground(GuiGraphics matrixStack, Theme theme, int x, int y, int w, int h) { - if (chunk.getForceLoadedDate().isPresent() && !InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_KEY_TAB)) { - chunk.getTeam().ifPresent(team -> { - Color4I teamColor = team.getProperties().get(TeamProperties.COLOR); - float[] hsb = Color4I.RGBtoHSB(teamColor.redi(), teamColor.greeni(), teamColor.bluei(), null); - hsb[0] = (hsb[0] + 0.5f) % 1f; - FORCE_LOAD_ICON.withColor(Color4I.hsb(hsb[0], hsb[1], hsb[2])).draw(matrixStack, x, y, FTBChunks.TILE_SIZE, FTBChunks.TILE_SIZE); - }); - } - if (isMouseOver() || selectedChunks.contains(chunkPos)) { - Color4I.WHITE.withAlpha(100).draw(matrixStack, x, y, w, h); - - if (isMouseButtonDown(MouseButton.LEFT) || isMouseButtonDown(MouseButton.RIGHT)) { - selectedChunks.add(chunkPos); - } - } - } - - @Override - @SuppressWarnings("deprecation") - public void addMouseOverText(TooltipList list) { - if (chunk == null) { - return; - } - chunk.getTeam().ifPresent(team -> { - list.add(team.getName().copy().withStyle(ChatFormatting.WHITE)); - - Date date = new Date(); - - chunk.getClaimedDate().ifPresent(claimedDate -> { - if (Screen.hasAltDown()) { - list.add(Component.literal(claimedDate.toLocaleString()).withStyle(ChatFormatting.GRAY)); - } else { - list.add(Component.literal(TimeUtils.prettyTimeString((date.getTime() - claimedDate.getTime()) / 1000L) + " ago").withStyle(ChatFormatting.GRAY)); - } - }); - - chunk.getForceLoadedDate().ifPresent(forceLoadedDate -> { - list.add(Component.translatable("ftbchunks.gui.force_loaded").withStyle(ChatFormatting.YELLOW)); - - String loadStr = Screen.hasAltDown() ? - " " + forceLoadedDate.toLocaleString() : - " " + TimeUtils.prettyTimeString((date.getTime() - forceLoadedDate.getTime()) / 1000L) + " ago"; - list.add(Component.literal(loadStr).withStyle(ChatFormatting.GRAY)); - - chunk.getForceLoadExpiryDate().ifPresent(expiryDate -> { - list.add(Component.translatable("ftbchunks.gui.force_load_expires").withStyle(ChatFormatting.GOLD)); - String expireStr = Screen.hasAltDown() ? - " " + expiryDate.toLocaleString() : - " " + TimeUtils.prettyTimeString((expiryDate.getTime() - date.getTime()) / 1000L) + " from now"; - list.add(Component.literal(expireStr).withStyle(ChatFormatting.GRAY)); - }); - - if (!Screen.hasAltDown()) { - list.add(Component.translatable("ftbchunks.gui.hold_alt_for_dates").withStyle(ChatFormatting.DARK_GRAY)); - } - if (team.getRankForPlayer(Minecraft.getInstance().player.getUUID()).isMemberOrBetter()){ - list.add(Component.translatable("ftbchunks.gui.mouse_wheel_expiry").withStyle(ChatFormatting.DARK_GRAY)); - } - }); - }); - } - - @Override - public boolean mouseScrolled(double scroll) { - return chunk.getForceLoadedDate().map(forceLoadedDate -> { - if (isMouseOver && chunk.isTeamMember(Minecraft.getInstance().player)) { - int dir = (int) Math.signum(scroll); - long now = System.currentTimeMillis(); - Date expiry = chunk.getForceLoadExpiryDate().orElse(new Date(now)); - long offset = calcOffset(expiry, now, dir); - chunk.updateForceLoadExpiryDate(now, offset * 1000L); - lastAdjust = now; - return true; - } - return super.mouseScrolled(scroll); - }).orElse(super.mouseScrolled(scroll)); - } - - private static long calcOffset(Date expiry, long now, int dir) { - long offset = (expiry.getTime() - now) / 1000L; - if (dir == 1) { - if (offset < 86400L) { - offset = offset + 3600L; // hour - } else if (offset < 604800L) { - offset = offset + 86400L; // day - } else { - offset = offset + 604800L; // week - } - } else if (dir == -1) { - if (offset <= 86400L) { - offset = Math.max(0L, offset - 3600L); - } else if (offset <= 604800L) { - offset = Math.max(86400L, offset - 86400L); - } else { - offset = Math.max(604800L, offset - 604800L); - } - } - return offset; - } - - @Override - public void tick() { - super.tick(); - - if (lastAdjust > 0L && System.currentTimeMillis() - lastAdjust > 1000L) { - // send update to server, but not more than once a second - avoid flood of updates while adjusting mouse wheel - NetworkManager.sendToServer(new UpdateForceLoadExpiryPacket(chunkPos.dim(Minecraft.getInstance().level), chunk.getForceLoadExpiryDate().orElse(null))); - lastAdjust = 0L; - } - } - } - - private record ChunkUpdateInfo(int totalChunks, int changedChunks, EnumMap problems, long timestamp) { - public boolean shouldDisplay() { - // display for 3 seconds + 1 second per line of problem data - long timeout = 60L + 20L * problems.size(); - return Minecraft.getInstance().level.getGameTime() - timestamp < timeout; - } - - public Component summary() { - ChatFormatting color = changedChunks == 0 ? ChatFormatting.RED : (changedChunks < totalChunks ? ChatFormatting.YELLOW : ChatFormatting.GREEN); - return Component.translatable("ftbchunks.claim_result", changedChunks, totalChunks).withStyle(ChatFormatting.UNDERLINE, color); - } - } - +import net.minecraft.network.chat.MutableComponent; +import org.jetbrains.annotations.Nullable; + +public class ChunkScreen extends AbstractThreePanelScreen { + + private final MapDimension dimension; + private final Team openedAs; + private ChunkScreenPanel chunkScreenPanel; + private SimpleButton largeMapButton; + + private ChunkScreen(MapDimension dimension, Team openedAs) { + this.dimension = dimension; + this.openedAs = openedAs; + showCloseButton(true); + showScrollBar(false); + } + + @Override + protected Panel createBottomPanel() { + return new CustomBottomPanel(); + } + + @Override + protected int getScrollbarWidth() { + return -1; + } + + @Override + public boolean onInit() { + int size = (int) (getScreen().getGuiScaledHeight() * 0.85f); + + setWidth(Math.min(size + 2, getScreen().getGuiScaledWidth() - 2)); + setHeight(Math.min(size + getTopPanelHeight() + getBottomPanelHeight(), getScreen().getGuiScaledHeight() - 2)); + + return true; + } + + + @Override + public void addWidgets() { + super.addWidgets(); + + add(largeMapButton = new SimpleButton(this, Component.translatable("ftbchunks.gui.large_map"), Icons.MAP, + (simpleButton, mouseButton) -> LargeMapScreen.openMap() + )); + } + + @Override + public void alignWidgets() { + super.alignWidgets(); + + largeMapButton.setPosAndSize(-getX() + 2, -getY() + 2, 16, 16); + } + + public static void openChunkScreen(@Nullable Team openedAs) { + MapDimension.getCurrent().ifPresentOrElse( + mapDimension -> new ChunkScreen(mapDimension, openedAs).openGui(), + () -> FTBChunks.LOGGER.warn("MapDimension data missing?? not opening chunk screen") + ); + } + + public static void openChunkScreen() { + openChunkScreen(null); + } + + public ChunkScreenPanel getChunkScreen() { + return chunkScreenPanel; + } + + @Override + protected void doCancel() { + closeGui(); + } + + @Override + protected void doAccept() { + + } + + @Override + protected int getTopPanelHeight() { + return 16; + } + + @Override + protected int getBottomPanelHeight() { + return openedAs == null ? super.getBottomPanelHeight() - 8 : super.getBottomPanelHeight(); + } + + @Override + protected ChunkScreenPanel createMainPanel() { + chunkScreenPanel = new ChunkScreenPanel(this); + return chunkScreenPanel; + } + + @Override + protected Panel createTopPanel() { + return new CustomTopPanel(); + } + + public Team getOpenedAs() { + return openedAs; + } + + public MapDimension getDimension() { + return dimension; + } + + protected class CustomTopPanel extends Panel { + private final Button closeButton; + private final Button removeAllClaims; + private final Button adminButton; + private final Button mouseReferenceButton; + + public CustomTopPanel() { + super(ChunkScreen.this); + + closeButton = new SimpleButton(this, Component.translatable("gui.close"), Icons.CLOSE, + (btn, mb) -> doCancel()) + .setForceButtonSize(false); + + mouseReferenceButton = new SimpleButton(this, Component.translatable("ftbchunks.gui.chunk_info"), Icons.INFO, + (btn, mb) -> new ChunkMouseReferenceScreen().openGui()) + .setForceButtonSize(false); + + removeAllClaims = new SimpleButton(this, Component.translatable("ftbchunks.gui.unclaim_all"), Icons.BIN, + (btn, mb) -> { + if (isShiftKeyDown()) { + chunkScreenPanel.removeAllClaims(); + } else { + getGui().openYesNo(Component.translatable("ftbchunks.gui.unclaim_all"), Component.translatable("ftbchunks.gui.unclaim_all.description"), () -> { + chunkScreenPanel.removeAllClaims(); + }); + } + }) + .setForceButtonSize(false); + + adminButton = new AdminButton().setForceButtonSize(false); + } + + @Override + public void addWidgets() { + add(closeButton); + add(removeAllClaims); + if (!Minecraft.getInstance().isSingleplayer() && openedAs == null && Minecraft.getInstance().player.hasPermissions(Commands.LEVEL_GAMEMASTERS)) { + add(adminButton); + } + add(mouseReferenceButton); + } + + @Override + public void alignWidgets() { + removeAllClaims.setPosAndSize(2, 2, 12, 12); + adminButton.setPosAndSize(18, 2, 12, 12); + + closeButton.setPosAndSize(width - 16, 2, 12, 12); + mouseReferenceButton.setPosAndSize(width - 32, 2, 12, 12); + + } + + @Override + public void drawBackground(GuiGraphics graphics, Theme theme, int x, int y, int w, int h) { + theme.drawPanelBackground(graphics, x, y, w, h); + Color4I.BLACK.withAlpha(80).draw(graphics, x, y + h - 1, w, 1); + } + + private class AdminButton extends ToggleableButton { + + private static final Component DISABLED = Component.translatable("ftbchunks.gui.admin_mode_disabled"); + private static final Component ENABLED = Component.translatable("ftbchunks.gui.admin_mode_enabled"); + private static final Component MORE_INFO = Component.translatable("ftbchunks.gui.admin_mode_info").withStyle(ChatFormatting.GRAY); + + public AdminButton() { + super(CustomTopPanel.this, false, Icons.LOCK_OPEN, Icons.LOCK, (btn, newState) -> { + ChunkScreen.this.getChunkScreen().isAdminEnabled = newState; + }); + setEnabledText(ENABLED); + setDisabledText(DISABLED); + } + + @Override + public void addMouseOverText(TooltipList list) { + super.addMouseOverText(list); + list.add(MORE_INFO); + } + } + } + + private static class ChunkMouseReferenceScreen extends KeyReferenceScreen { + public ChunkMouseReferenceScreen() { + super("ftbchunks.gui.chunk_info.text"); + } + + @Override + public Component getTitle() { + return Component.translatable("ftbchunks.gui.chunk_info"); + } + } + + private class CustomBottomPanel extends Panel { + + public CustomBottomPanel() { + super(ChunkScreen.this); + } + + @Override + public void addWidgets() { + } + + @Override + public void alignWidgets() { + + } + + @Override + public void drawBackground(GuiGraphics graphics, Theme theme, int x, int y, int w, int h) { + theme.drawPanelBackground(graphics, x, y, w, h); + + Color4I.GRAY.withAlpha(64).draw(graphics, x, y, w, 1); + SendGeneralDataPacket.GeneralChunkData generalChunkData = FTBChunksClient.INSTANCE.getGeneralChunkData(); + + int claimed = generalChunkData.claimed(); + int maxClaim = generalChunkData.maxClaimChunks(); + + MutableComponent claimedComponent = Component.translatable("ftbchunks.gui.claimed").append(Component.literal(": ") + .append(Component.literal(claimed + " / " + maxClaim) + .withStyle(claimed > maxClaim ? ChatFormatting.RED : claimed == maxClaim ? ChatFormatting.YELLOW : ChatFormatting.GREEN))); + theme.drawString(graphics, claimedComponent, x + 4, y + 4); + + int loaded = generalChunkData.loaded(); + int maxLoaded = generalChunkData.maxForceLoadChunks(); + + MutableComponent forceLoadComponent = Component.translatable("ftbchunks.gui.force_loaded").append(Component.literal(": ")) + .append(Component.literal(loaded + " / " + maxLoaded) + .withStyle(loaded > maxLoaded ? ChatFormatting.RED : loaded == maxLoaded ? ChatFormatting.YELLOW : ChatFormatting.GREEN)); + String forceLoadText = forceLoadComponent.getString(); + int forceLoadX = x + w - theme.getStringWidth(forceLoadText) - 2; + theme.drawString(graphics, forceLoadComponent, forceLoadX, y + 4); + + if (openedAs != null) { + String openAsMessage = Component.translatable("ftbchunks.gui.opened_as", openedAs.getName()).getString(); + int openAsX = x + w - theme.getStringWidth(openAsMessage) - 2; + theme.drawString(graphics, openAsMessage, openAsX, y + h - theme.getFontHeight(), Color4I.WHITE, Theme.SHADOW); + } + } + } } diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/ChunkScreenPanel.java b/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/ChunkScreenPanel.java new file mode 100644 index 00000000..5118f29d --- /dev/null +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/ChunkScreenPanel.java @@ -0,0 +1,363 @@ +package dev.ftb.mods.ftbchunks.client.gui; + +import com.mojang.blaze3d.platform.InputConstants; +import com.mojang.blaze3d.systems.RenderSystem; +import dev.architectury.networking.NetworkManager; +import dev.ftb.mods.ftbchunks.FTBChunks; +import dev.ftb.mods.ftbchunks.FTBChunksWorldConfig; +import dev.ftb.mods.ftbchunks.api.ClaimResult; +import dev.ftb.mods.ftbchunks.api.FTBChunksAPI; +import dev.ftb.mods.ftbchunks.api.client.icon.MapType; +import dev.ftb.mods.ftbchunks.client.FTBChunksClient; +import dev.ftb.mods.ftbchunks.client.map.MapChunk; +import dev.ftb.mods.ftbchunks.client.map.MapManager; +import dev.ftb.mods.ftbchunks.client.map.RenderMapImageTask; +import dev.ftb.mods.ftbchunks.net.RequestChunkChangePacket; +import dev.ftb.mods.ftbchunks.net.RequestMapDataPacket; +import dev.ftb.mods.ftbchunks.net.UpdateForceLoadExpiryPacket; +import dev.ftb.mods.ftblibrary.icon.Color4I; +import dev.ftb.mods.ftblibrary.icon.FaceIcon; +import dev.ftb.mods.ftblibrary.icon.ImageIcon; +import dev.ftb.mods.ftblibrary.math.MathUtils; +import dev.ftb.mods.ftblibrary.math.XZ; +import dev.ftb.mods.ftblibrary.ui.*; +import dev.ftb.mods.ftblibrary.ui.input.Key; +import dev.ftb.mods.ftblibrary.ui.input.MouseButton; +import dev.ftb.mods.ftblibrary.util.TimeUtils; +import dev.ftb.mods.ftblibrary.util.TooltipList; +import dev.ftb.mods.ftbteams.api.Team; +import dev.ftb.mods.ftbteams.api.property.TeamProperties; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.commands.Commands; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.ChunkPos; +import org.lwjgl.glfw.GLFW; + +import java.util.*; +import java.util.stream.Collectors; + +import static dev.ftb.mods.ftbchunks.net.RequestChunkChangePacket.ChunkChangeOp; + +public class ChunkScreenPanel extends Panel { + private static final ImageIcon FORCE_LOAD_ICON = new ImageIcon(FTBChunksAPI.rl("textures/force_loaded.png")); + private static final ImageIcon CHECKERED_ICON = new ImageIcon(FTBChunksAPI.rl("textures/checkered.png")); + + private final List chunkButtons = new ArrayList<>(); + private final Set selectedChunks = new HashSet<>(); + private final List chunkedPosList = new ArrayList<>(); + public boolean isAdminEnabled; + private ChunkScreenPanel.ChunkUpdateInfo updateInfo; + public int tileSizeX = 16; + public int tileSizeY = 16; + private final ChunkScreen chunkScreen; + + public ChunkScreenPanel(ChunkScreen panel) { + super(panel); + this.chunkScreen = panel; + RenderMapImageTask.setAlwaysRenderChunksOnMap(true); + + this.isAdminEnabled = Minecraft.getInstance().isSingleplayer(); + + + MapManager.getInstance().ifPresent(m -> m.updateAllRegions(false)); + + alignWidgets(); + + } + + public static void notifyChunkUpdates(int totalChunks, int changedChunks, EnumMap problems) { + if (Minecraft.getInstance().screen instanceof ScreenWrapper sw && sw.getGui() instanceof ChunkScreen cs) { + cs.getChunkScreen().updateInfo = new ChunkUpdateInfo(totalChunks, changedChunks, problems, Minecraft.getInstance().level.getGameTime()); + } + } + + @Override + public void onClosed() { + RenderMapImageTask.setAlwaysRenderChunksOnMap(false); + + MapManager.getInstance().ifPresent(m -> m.updateAllRegions(false)); + + super.onClosed(); + } + + @Override + public void addWidgets() { + Player player = Minecraft.getInstance().player; + ChunkPos chunkPos = player.chunkPosition(); + int startX = chunkPos.x - FTBChunks.TILE_OFFSET; + int startZ = chunkPos.z - FTBChunks.TILE_OFFSET; + + chunkButtons.clear(); + for (int z = 0; z < FTBChunks.TILES; z++) { + for (int x = 0; x < FTBChunks.TILES; x++) { + ChunkButton button = new ChunkButton(this, XZ.of(startX + x, startZ + z)); + chunkButtons.add(button); + chunkedPosList.add(new ChunkButtonPos(button, x , z)); + } + } + + addAll(chunkButtons); + + NetworkManager.sendToServer(new RequestMapDataPacket( + chunkPos.x - FTBChunks.TILE_OFFSET, chunkPos.z - FTBChunks.TILE_OFFSET, + chunkPos.x + FTBChunks.TILE_OFFSET, chunkPos.z + FTBChunks.TILE_OFFSET) + ); + + } + + @Override + public void alignWidgets() { + int maxWidth = getWidth() / FTBChunks.TILES * FTBChunks.TILES; + int maxHeight = getHeight() / FTBChunks.TILES * FTBChunks.TILES; + int xPos = (getWidth() - maxWidth) / 2; + int yPos = (getHeight() - maxHeight) / 2; + + this.tileSizeX = maxWidth / FTBChunks.TILES; + this.tileSizeY = maxHeight / FTBChunks.TILES; + for (ChunkButtonPos chunkedPos : chunkedPosList) { + chunkedPos.button.setPos(xPos + tileSizeX * chunkedPos.x, yPos + tileSizeY * chunkedPos.y); + chunkedPos.button.setSize(tileSizeX, tileSizeY); + } + } + + @Override + public void mouseReleased(MouseButton button) { + super.mouseReleased(button); + + if (!selectedChunks.isEmpty()) { + Optional teamId = Optional.ofNullable(chunkScreen.getOpenedAs()).map(Team::getTeamId); + NetworkManager.sendToServer(new RequestChunkChangePacket(ChunkChangeOp.create(button.isLeft(), isShiftKeyDown()), selectedChunks, canChangeAsAdmin(), teamId)); + selectedChunks.clear(); + playClickSound(); + } + } + + public void removeAllClaims() { + Optional teamId = Optional.ofNullable(chunkScreen.getOpenedAs()).map(Team::getTeamId); + Set allChunks = chunkedPosList.stream() + .map(ChunkButtonPos::button) + .map(ChunkButton::getChunkPos) + .collect(Collectors.toSet()); + NetworkManager.sendToServer(new RequestChunkChangePacket(ChunkChangeOp.UNCLAIM, allChunks, canChangeAsAdmin(), teamId)); + } + + @Override + public boolean keyPressed(Key key) { + if (FTBChunksWorldConfig.playerHasMapStage(Minecraft.getInstance().player) && (key.is(GLFW.GLFW_KEY_M) || key.is(GLFW.GLFW_KEY_C))) { + LargeMapScreen.openMap(); + return true; + } + + return super.keyPressed(key); + } + + @Override + public void drawBackground(GuiGraphics graphics, Theme theme, int x, int y, int w, int h) { + Player player = Minecraft.getInstance().player; + + // make sure the window is a multiple of the tile amount + int maxWidth = getWidth() / FTBChunks.TILES * FTBChunks.TILES; + int maxHeight = getHeight() / FTBChunks.TILES * FTBChunks.TILES; + int xPos = (getWidth() - maxWidth) / 2; + int yPos = (getHeight() - maxHeight) / 2; + + int sx = getX() + xPos; + int sy = getY() + yPos; + + RenderSystem.setShaderTexture(0, FTBChunksClient.INSTANCE.getMinimapTextureId()); + GuiHelper.drawTexturedRect(graphics, sx, sy, maxWidth, maxHeight, Color4I.WHITE, 0F, 0F, 1F, 1F); + + if (!InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_KEY_TAB)) { + for (int gy = 1; gy < FTBChunks.TILES; gy++) { + graphics.hLine(sx, sx + maxWidth - 1, sy + gy * tileSizeY, 0x64464646); + } + for (int gx = 1; gx < FTBChunks.TILES; gx++) { + graphics.vLine(sx + gx * tileSizeX, sy - 1, sy + maxHeight, 0x64464646); + } + } + + double hx = sx + tileSizeX * FTBChunks.TILE_OFFSET + MathUtils.mod(player.getX(), 16D); + double hy = sy + tileSizeY * FTBChunks.TILE_OFFSET + MathUtils.mod(player.getZ(), 16D); + + new PointerIcon().draw(MapType.LARGE_MAP, graphics, (int) (hx - 4D), (int) (hy - 4D), 8, 8, false, 255); + FaceIcon.getFace(player.getGameProfile()).draw(graphics, (int) (hx - 4D), (int) (hy - 4D), 8, 8); + + if (updateInfo != null && updateInfo.shouldDisplay()) { + theme.drawString(graphics, updateInfo.summary(), sx + 2, sy + 2, Theme.SHADOW); + int line = 1; + for (Map.Entry entry : updateInfo.problems.entrySet()) { + ClaimResult.StandardProblem problem = entry.getKey(); + int count = entry.getValue(); + theme.drawString(graphics, problem.getMessage().append(": " + count), sx + 2, sy + 5 + theme.getFontHeight() * line++, Theme.SHADOW); + } + } + } + + private boolean canChangeAsAdmin() { + return Minecraft.getInstance().player.hasPermissions(Commands.LEVEL_GAMEMASTERS) && chunkScreen.getOpenedAs() == null && isAdminEnabled; + } + + private class ChunkButton extends Button { + private final XZ chunkPos; + private final MapChunk chunk; + private long lastAdjust = 0L; + + public ChunkButton(Panel panel, XZ xz) { + super(panel, Component.empty(), Color4I.empty()); + setSize(FTBChunks.TILE_SIZE, FTBChunks.TILE_SIZE); + chunkPos = xz; + chunk = chunkScreen.getDimension().getRegion(XZ.regionFromChunk(chunkPos.x(), chunkPos.z())).getDataBlocking().getChunk(chunkPos); + } + + @Override + public void onClicked(MouseButton mouseButton) { + selectedChunks.add(chunkPos); + } + + @Override + public void drawBackground(GuiGraphics graphics, Theme theme, int x, int y, int w, int h) { + if (chunk.getForceLoadedDate().isPresent() && !InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_KEY_TAB)) { + chunk.getTeam().ifPresent(team -> { + Color4I teamColor = team.getProperties().get(TeamProperties.COLOR); + float[] hsb = Color4I.RGBtoHSB(teamColor.redi(), teamColor.greeni(), teamColor.bluei(), null); + hsb[0] = (hsb[0] + 0.5f) % 1f; + FORCE_LOAD_ICON.withColor(Color4I.hsb(hsb[0], hsb[1], hsb[2])).draw(graphics, x, y, w, h); + }); + } + if (isMouseOver() || selectedChunks.contains(chunkPos)) { + Color4I.WHITE.withAlpha(100).draw(graphics, x, y, w, h); + CHECKERED_ICON.withColor(Color4I.GRAY.withAlpha(150)).draw(graphics, x, y, w, h); + + } + } + + @Override + public boolean mouseDragged(int button, double dragX, double dragY) { + if (isMouseOver() && (isMouseButtonDown(MouseButton.LEFT) || isMouseButtonDown(MouseButton.RIGHT))) { + selectedChunks.add(chunkPos); + } + return super.mouseDragged(button, dragX, dragY); + } + + @Override + @SuppressWarnings("deprecation") + public void addMouseOverText(TooltipList list) { + if (chunk == null) { + return; + } + chunk.getTeam().ifPresent(team -> { + list.add(team.getName().copy().withStyle(ChatFormatting.WHITE)); + + Date date = new Date(); + + chunk.getClaimedDate().ifPresent(claimedDate -> { + if (Screen.hasAltDown()) { + list.add(Component.literal(claimedDate.toLocaleString()).withStyle(ChatFormatting.GRAY)); + } else { + list.add(Component.literal(TimeUtils.prettyTimeString((date.getTime() - claimedDate.getTime()) / 1000L) + " ago").withStyle(ChatFormatting.GRAY)); + } + }); + + chunk.getForceLoadedDate().ifPresent(forceLoadedDate -> { + list.add(Component.translatable("ftbchunks.gui.force_loaded").withStyle(ChatFormatting.YELLOW)); + + String loadStr = Screen.hasAltDown() ? + " " + forceLoadedDate.toLocaleString() : + " " + TimeUtils.prettyTimeString((date.getTime() - forceLoadedDate.getTime()) / 1000L) + " ago"; + list.add(Component.literal(loadStr).withStyle(ChatFormatting.GRAY)); + + chunk.getForceLoadExpiryDate().ifPresent(expiryDate -> { + list.add(Component.translatable("ftbchunks.gui.force_load_expires").withStyle(ChatFormatting.GOLD)); + String expireStr = Screen.hasAltDown() ? + " " + expiryDate.toLocaleString() : + " " + TimeUtils.prettyTimeString((expiryDate.getTime() - date.getTime()) / 1000L) + " from now"; + list.add(Component.literal(expireStr).withStyle(ChatFormatting.GRAY)); + }); + + if (!Screen.hasAltDown()) { + list.add(Component.translatable("ftbchunks.gui.hold_alt_for_dates").withStyle(ChatFormatting.DARK_GRAY)); + } + if (team.getRankForPlayer(Minecraft.getInstance().player.getUUID()).isMemberOrBetter()){ + list.add(Component.translatable("ftbchunks.gui.mouse_wheel_expiry").withStyle(ChatFormatting.DARK_GRAY)); + } + }); + }); + } + + @Override + public boolean mouseScrolled(double scroll) { + return chunk.getForceLoadedDate().map(forceLoadedDate -> { + LocalPlayer player = Minecraft.getInstance().player; + boolean teamMember = chunk.isTeamMember(player); + if (isMouseOver && (canChangeAsAdmin() || teamMember)) { + int dir = (int) Math.signum(scroll); + long now = System.currentTimeMillis(); + Date expiry = chunk.getForceLoadExpiryDate().orElse(new Date(now)); + long offset = calcOffset(expiry, now, dir); + chunk.updateForceLoadExpiryDate(now, offset * 1000L); + lastAdjust = now; + return true; + } + return super.mouseScrolled(scroll); + }).orElse(super.mouseScrolled(scroll)); + } + + private static long calcOffset(Date expiry, long now, int dir) { + long offset = (expiry.getTime() - now) / 1000L; + if (dir == 1) { + if (offset < 86400L) { + offset = offset + 3600L; // hour + } else if (offset < 604800L) { + offset = offset + 86400L; // day + } else { + offset = offset + 604800L; // week + } + } else if (dir == -1) { + if (offset <= 86400L) { + offset = Math.max(0L, offset - 3600L); + } else if (offset <= 604800L) { + offset = Math.max(86400L, offset - 86400L); + } else { + offset = Math.max(604800L, offset - 604800L); + } + } + return offset; + } + + @Override + public void tick() { + super.tick(); + + if (lastAdjust > 0L && System.currentTimeMillis() - lastAdjust > 1000L) { + // send update to server, but not more than once a second - avoid flood of updates while adjusting mouse wheel + NetworkManager.sendToServer(new UpdateForceLoadExpiryPacket(chunkPos.dim(Minecraft.getInstance().level), chunk.getForceLoadExpiryDate().orElse(null))); + lastAdjust = 0L; + } + } + + public XZ getChunkPos() { + return chunkPos; + } + } + + public record ChunkUpdateInfo(int totalChunks, int changedChunks, EnumMap problems, long timestamp) { + public boolean shouldDisplay() { + // display for 3 seconds + 1 second per line of problem data + long timeout = 60L + 20L * problems.size(); + return Minecraft.getInstance().level.getGameTime() - timestamp < timeout; + } + + public Component summary() { + ChatFormatting color = changedChunks == 0 ? ChatFormatting.RED : (changedChunks < totalChunks ? ChatFormatting.YELLOW : ChatFormatting.GREEN); + return Component.translatable("ftbchunks.claim_result", changedChunks, totalChunks).withStyle(ChatFormatting.UNDERLINE, color); + } + } + + private record ChunkButtonPos(ChunkButton button, int x , int y) {} + +} diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/data/ChunkTeamDataImpl.java b/common/src/main/java/dev/ftb/mods/ftbchunks/data/ChunkTeamDataImpl.java index ee05962c..1ba55745 100644 --- a/common/src/main/java/dev/ftb/mods/ftbchunks/data/ChunkTeamDataImpl.java +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/data/ChunkTeamDataImpl.java @@ -25,6 +25,7 @@ import net.minecraft.ChatFormatting; import net.minecraft.Util; import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; @@ -185,14 +186,14 @@ public ClaimResult claim(CommandSourceStack source, ChunkDimPos pos, boolean che } @Override - public ClaimResult unclaim(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly) { + public ClaimResult unclaim(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly, boolean adminOverride) { ClaimedChunkImpl chunk = manager.getChunk(pos); if (chunk == null) { return ClaimResult.StandardProblem.NOT_CLAIMED; - } else if (chunk.getTeamData() != this && !source.hasPermission(2) && !source.getServer().isSingleplayer()) { - return ClaimResult.StandardProblem.NOT_OWNER; - } + } else if (chunk.getTeamData() != this && !(adminOverride && source.hasPermission(Commands.LEVEL_GAMEMASTERS)) && !source.getServer().isSingleplayer()) { + return ClaimResult.StandardProblem.NOT_OWNER; + } ClaimResult result = ClaimedChunkEvent.BEFORE_UNCLAIM.invoker().before(source, chunk).object(); if (result == null) { @@ -209,12 +210,12 @@ public ClaimResult unclaim(CommandSourceStack source, ChunkDimPos pos, boolean c } @Override - public ClaimResult forceLoad(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly) { + public ClaimResult forceLoad(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly, boolean adminOverride) { ClaimedChunkImpl chunk = manager.getChunk(pos); if (chunk == null) { return ClaimResult.StandardProblem.NOT_CLAIMED; - } else if (chunk.getTeamData() != this && !source.hasPermission(2) && !source.getServer().isSingleplayer()) { + } else if (chunk.getTeamData() != this && !(adminOverride && source.hasPermission(Commands.LEVEL_GAMEMASTERS)) && !source.getServer().isSingleplayer()) { return ClaimResult.StandardProblem.NOT_OWNER; } else if (chunk.isForceLoaded()) { return ClaimResult.StandardProblem.ALREADY_LOADED; @@ -238,13 +239,13 @@ public ClaimResult forceLoad(CommandSourceStack source, ChunkDimPos pos, boolean } @Override - public ClaimResult unForceLoad(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly) { + public ClaimResult unForceLoad(CommandSourceStack source, ChunkDimPos pos, boolean checkOnly, boolean adminOverride) { ClaimedChunkImpl chunk = manager.getChunk(pos); if (chunk == null) { return ClaimResult.StandardProblem.NOT_CLAIMED; } else if (chunk.getTeamData() != this - && !source.hasPermission(2) + && !(adminOverride && source.hasPermission(Commands.LEVEL_GAMEMASTERS)) && !source.getServer().isSingleplayer() && !(source.getEntity() instanceof ServerPlayer && isTeamMember(source.getEntity().getUUID())) ) { diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/net/ChunkChangeResponsePacket.java b/common/src/main/java/dev/ftb/mods/ftbchunks/net/ChunkChangeResponsePacket.java index d073bbc9..b11ef830 100644 --- a/common/src/main/java/dev/ftb/mods/ftbchunks/net/ChunkChangeResponsePacket.java +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/net/ChunkChangeResponsePacket.java @@ -3,7 +3,7 @@ import dev.architectury.networking.NetworkManager; import dev.ftb.mods.ftbchunks.api.ClaimResult.StandardProblem; import dev.ftb.mods.ftbchunks.api.FTBChunksAPI; -import dev.ftb.mods.ftbchunks.client.gui.ChunkScreen; +import dev.ftb.mods.ftbchunks.client.gui.ChunkScreenPanel; import dev.ftb.mods.ftblibrary.util.NetworkHelper; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; @@ -28,6 +28,6 @@ public Type type() { } public static void handle(ChunkChangeResponsePacket message, NetworkManager.PacketContext context) { - context.queue(() -> ChunkScreen.notifyChunkUpdates(message.totalChunks, message.changedChunks, message.problems)); + context.queue(() -> ChunkScreenPanel.notifyChunkUpdates(message.totalChunks, message.changedChunks, message.problems)); } } diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/net/FTBChunksNet.java b/common/src/main/java/dev/ftb/mods/ftbchunks/net/FTBChunksNet.java index 4d0c3fed..ee8f31ac 100644 --- a/common/src/main/java/dev/ftb/mods/ftbchunks/net/FTBChunksNet.java +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/net/FTBChunksNet.java @@ -25,5 +25,6 @@ public static void init() { NetworkHelper.registerS2C(SendPlayerPositionPacket.TYPE, SendPlayerPositionPacket.STREAM_CODEC, SendPlayerPositionPacket::handle); NetworkHelper.registerS2C(ServerConfigResponsePacket.TYPE, ServerConfigResponsePacket.STREAM_CODEC, ServerConfigResponsePacket::handle); NetworkHelper.registerS2C(SyncRXPacket.TYPE, SyncRXPacket.STREAM_CODEC, SyncRXPacket::handle); + NetworkHelper.registerS2C(OpenClaimGUIPacket.TYPE, OpenClaimGUIPacket.STREAM_CODEC, OpenClaimGUIPacket::handle); } } \ No newline at end of file diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/net/OpenClaimGUIPacket.java b/common/src/main/java/dev/ftb/mods/ftbchunks/net/OpenClaimGUIPacket.java new file mode 100644 index 00000000..cc0cfae9 --- /dev/null +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/net/OpenClaimGUIPacket.java @@ -0,0 +1,47 @@ +package dev.ftb.mods.ftbchunks.net; + +import dev.architectury.networking.NetworkManager; +import dev.ftb.mods.ftbchunks.api.FTBChunksAPI; +import dev.ftb.mods.ftbchunks.client.gui.ChunkScreen; +import dev.ftb.mods.ftbteams.api.FTBTeamsAPI; +import dev.ftb.mods.ftbteams.api.Team; +import net.minecraft.ChatFormatting; +import net.minecraft.core.UUIDUtil; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.world.entity.player.Player; + +import java.util.Optional; +import java.util.UUID; + +public record OpenClaimGUIPacket(UUID teamId) implements CustomPacketPayload { + + public static final Type TYPE = new Type<>(FTBChunksAPI.rl("open_claim_gui_packet")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + UUIDUtil.STREAM_CODEC, OpenClaimGUIPacket::teamId, + OpenClaimGUIPacket::new + ); + + @Override + public Type type() { + return TYPE; + } + + public static void handle(OpenClaimGUIPacket message, NetworkManager.PacketContext context) { + context.queue(() -> { + Player player = context.getPlayer(); + + Optional teamByID = FTBTeamsAPI.api().getClientManager().getTeamByID(message.teamId); + if (teamByID.isEmpty()) { + player.sendSystemMessage(Component.translatable("ftbteams.team_not_found", message.teamId, ChatFormatting.RED)); + return; + } + + ChunkScreen.openChunkScreen(teamByID.get()); + }); + } + +} diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/net/RequestChunkChangePacket.java b/common/src/main/java/dev/ftb/mods/ftbchunks/net/RequestChunkChangePacket.java index 3f541ff4..8fcaf339 100644 --- a/common/src/main/java/dev/ftb/mods/ftbchunks/net/RequestChunkChangePacket.java +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/net/RequestChunkChangePacket.java @@ -8,8 +8,13 @@ import dev.ftb.mods.ftbchunks.data.ClaimedChunkManagerImpl; import dev.ftb.mods.ftblibrary.math.XZ; import dev.ftb.mods.ftblibrary.util.NetworkHelper; +import dev.ftb.mods.ftbteams.api.FTBTeamsAPI; +import dev.ftb.mods.ftbteams.api.Team; +import net.minecraft.ChatFormatting; import net.minecraft.commands.CommandSourceStack; +import net.minecraft.core.UUIDUtil; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; @@ -17,17 +22,20 @@ import java.util.EnumMap; import java.util.HashSet; +import java.util.Optional; import java.util.Set; +import java.util.UUID; import java.util.function.Function; -public record RequestChunkChangePacket(ChunkChangeOp action, Set chunks) implements CustomPacketPayload { +public record RequestChunkChangePacket(ChunkChangeOp action, Set chunks, boolean tryAdminChanges, Optional teamId) implements CustomPacketPayload { public static final Type TYPE = new Type<>(FTBChunksAPI.rl("request_chunk_change_packet")); public static final StreamCodec STREAM_CODEC = StreamCodec.composite( NetworkHelper.enumStreamCodec(ChunkChangeOp.class), RequestChunkChangePacket::action, XZ.STREAM_CODEC.apply(ByteBufCodecs.collection(HashSet::new)), RequestChunkChangePacket::chunks, - RequestChunkChangePacket::new - ); + ByteBufCodecs.BOOL, RequestChunkChangePacket::tryAdminChanges, + UUIDUtil.STREAM_CODEC.apply(ByteBufCodecs::optional), RequestChunkChangePacket::teamId, + RequestChunkChangePacket::new); @Override public Type type() { @@ -37,15 +45,30 @@ public Type type() { public static void handle(RequestChunkChangePacket message, NetworkManager.PacketContext context) { ServerPlayer player = (ServerPlayer) context.getPlayer(); CommandSourceStack source = player.createCommandSourceStack(); - ChunkTeamData data = ClaimedChunkManagerImpl.getInstance().getOrCreateData(player); + + ChunkTeamData chunkTeamData = null; + if (message.teamId().isPresent()) { + Optional team = FTBTeamsAPI.api().getManager().getTeamByID(message.teamId().get()); + if (team.isEmpty()) { + player.sendSystemMessage(Component.translatable("ftbteams.team_not_found", message.teamId, ChatFormatting.RED)); + return; + } + chunkTeamData = ClaimedChunkManagerImpl.getInstance().getOrCreateData(team.get()); + } + if (chunkTeamData == null) { + chunkTeamData = ClaimedChunkManagerImpl.getInstance().getOrCreateData(player); + } + + ChunkTeamData data = chunkTeamData; + Function consumer = switch (message.action) { case CLAIM -> pos -> data.claim(source, pos.dim(player.level()), false); - case UNCLAIM -> pos -> data.unclaim(source, pos.dim(player.level()), false); - case LOAD -> pos -> data.forceLoad(source, pos.dim(player.level()), false); - case UNLOAD -> pos -> data.unForceLoad(source, pos.dim(player.level()), false); + case UNCLAIM -> pos -> data.unclaim(source, pos.dim(player.level()), false, message.tryAdminChanges); + case LOAD -> pos -> data.forceLoad(source, pos.dim(player.level()), false, message.tryAdminChanges); + case UNLOAD -> pos -> data.unForceLoad(source, pos.dim(player.level()), false, message.tryAdminChanges); }; - EnumMap problems = new EnumMap<>(ClaimResult.StandardProblem.class); + EnumMap problems = new EnumMap<>(ClaimResult.StandardProblem.class); int changed = 0; for (XZ pos : message.chunks) { ClaimResult r = consumer.apply(pos); @@ -63,6 +86,10 @@ public static void handle(RequestChunkChangePacket message, NetworkManager.Packe NetworkManager.sendToPlayer(player, new ChunkChangeResponsePacket(message.chunks.size(), changed, problems)); SendGeneralDataPacket.send(data, player); + + if (message.teamId.isPresent()) { + SendGeneralDataPacket.send(chunkTeamData, data.getTeam().getOnlineMembers()); + } } public enum ChunkChangeOp { diff --git a/common/src/main/resources/assets/ftbchunks/lang/en_us.json b/common/src/main/resources/assets/ftbchunks/lang/en_us.json index 154bb12a..8610642f 100644 --- a/common/src/main/resources/assets/ftbchunks/lang/en_us.json +++ b/common/src/main/resources/assets/ftbchunks/lang/en_us.json @@ -118,6 +118,12 @@ "ftbchunks.gui.chunk_info.text": "Claiming\nLeft Button;Drag to claim an area\nRight Button;Drag to unclaim an area\n\nForceloading\nShift + Left Button;Drag to forceload an area\nShift + Right Button;Drag to unforceload an area\nMouse Wheel;Rotate on forceloaded chunk to adjust auto-expiry\n\nMisc\nTab;Hold to hide chunk grid\nAlt;Hold to show absolute chunk claim/force times", "ftbchunks.gui.delete": "Delete", "ftbchunks.gui.quick_delete": "Quick Delete", + "ftbchunks.gui.opened_as": "Opened as %s", + "ftbchunks.gui.admin_mode_disabled": "Admin Mode: Disabled", + "ftbchunks.gui.admin_mode_enabled": "Admin Mode: Enabled", + "ftbchunks.gui.admin_mode_info": "When enabled you can modify chunks, regardless of ownership", + "ftbchunks.gui.unclaim_all": "Unclaim All", + "ftbchunks.gui.unclaim_all.description": "Unclaim all chunks visible on the map?", "ftbteamsconfig.ftbchunks": "FTB Chunks Properties", "ftbteamsconfig.ftbchunks.allow_fake_players": "Allow All Fake Players", "ftbteamsconfig.ftbchunks.allow_fake_players.tooltip": "Treat ALL fake players as allies of the team.\nWARNING: Setting this to true could allow hostile players to access your claims via any fake player. Set this to false if you're unsure.", diff --git a/common/src/main/resources/assets/ftbchunks/textures/checkered.png b/common/src/main/resources/assets/ftbchunks/textures/checkered.png new file mode 100644 index 0000000000000000000000000000000000000000..b5b548982571d8fc3fae593604769fd7159d9160 GIT binary patch literal 300 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1quc!GoSIjv*HQy_0V9H5>3a@62)f@c;g)(`<8P zW!${EWHhs6)MJ=@nS2>e+1f4&Vml?AR5sDnv8ZBd&mX~!9(fhQeS91Ft=a24YMOmr zKDE3#^S)6VIaBuv(HgjN1LH{JTFVdQ&MBb@02xSe-~a#s literal 0 HcmV?d00001 diff --git a/gradle.properties b/gradle.properties index efbe1192..cbb1ccab 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,12 +16,12 @@ minecraft_version=1.21.1 neoforge_version=21.1.9 neoforge_version_range=[21.1.0,) neoforge_loader_version=4 -fabric_loader_version=0.15.11 -fabric_api_version=0.100.8+1.21 +fabric_loader_version=0.16.0 +fabric_api_version=0.102.1+1.21.1 fabric_api_version_range=>=0.100.1+1.21 -architectury_api_version=13.0.2 +architectury_api_version=13.0.6 -ftb_library_version=2101.1.0 +ftb_library_version=2101.1.2-SNAPSHOT ftb_teams_version=2101.1.0 curseforge_id_forge=314906 From 3bf16948cb2a4a7f5f123866ad5446aff40ab512 Mon Sep 17 00:00:00 2001 From: Des Herriott Date: Wed, 21 Aug 2024 16:16:40 +0100 Subject: [PATCH 2/6] build: version -> 2101.1.1, changelog updated --- CHANGELOG.md | 11 +++++++++++ gradle.properties | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b011321e..334e364d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2101.1.1] + +### Added +* Added `/ftbchunks admin open_claim_gui_as` command + * Allows server admins to open the chunk claim gui as any player + * Offline players are also supported (but names of offline players aren't suggested in command completion) + +### Changed +* Reworked the chunk claim GUI for a more polished visual appearance + * Added an "Unclaim All" button (trash can button, top-left) to reset all claims + ## [2101.1.0] ### Changed diff --git a/gradle.properties b/gradle.properties index cbb1ccab..34ccda27 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ readable_name=FTB Chunks maven_group=dev.ftb.mods mod_author=FTB Team -mod_version=2101.1.0 +mod_version=2101.1.1 minecraft_version=1.21.1 # Deps From 25426cda78ddcb1d485eab514acba12c49668fc3 Mon Sep 17 00:00:00 2001 From: Des Herriott Date: Mon, 9 Sep 2024 11:42:09 +0100 Subject: [PATCH 3/6] feat: add team property defaults in server config Applied when a new team is created. https://github.com/FTBTeam/FTB-Mods-Issues/issues/921 --- .../mods/ftbchunks/FTBChunksWorldConfig.java | 108 ++++++++++++++---- .../ftbchunks/api/FTBChunksProperties.java | 27 ++--- .../assets/ftbchunks/lang/en_us.json | 14 +++ 3 files changed, 111 insertions(+), 38 deletions(-) diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/FTBChunksWorldConfig.java b/common/src/main/java/dev/ftb/mods/ftbchunks/FTBChunksWorldConfig.java index 20846d82..443c92e2 100644 --- a/common/src/main/java/dev/ftb/mods/ftbchunks/FTBChunksWorldConfig.java +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/FTBChunksWorldConfig.java @@ -1,5 +1,6 @@ package dev.ftb.mods.ftbchunks; +import dev.architectury.platform.Platform; import dev.ftb.mods.ftbchunks.api.ChunkTeamData; import dev.ftb.mods.ftbchunks.api.ProtectionPolicy; import dev.ftb.mods.ftbchunks.data.AllyMode; @@ -11,6 +12,7 @@ import dev.ftb.mods.ftblibrary.config.NameMap; import dev.ftb.mods.ftblibrary.integration.stages.StageHelper; import dev.ftb.mods.ftblibrary.snbt.config.*; +import dev.ftb.mods.ftbteams.api.property.PrivacyMode; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; @@ -19,39 +21,95 @@ public interface FTBChunksWorldConfig { SNBTConfig CONFIG = SNBTConfig.create(FTBChunks.MOD_ID + "-world"); - BooleanValue DISABLE_PROTECTION = CONFIG.addBoolean("disable_protection", false).comment("Disables all land protection. Useful for private servers where everyone is trusted and claims are only used for force-loading"); - EnumValue ALLY_MODE = CONFIG.addEnum("ally_mode", AllyMode.NAME_MAP).comment("Forced modes won't let players change their ally settings"); - EnumValue PVP_MODE = CONFIG.addEnum("pvp_mode", PvPMode.NAME_MAP).comment("Should PvP combat be allowed in claimed chunks? Default is ALWAYS; NEVER prevents it in all claimed chunks; PER_TEAM allows teams to decide if PvP is allowed in their claims"); - BooleanValue NO_WILDERNESS = CONFIG.addBoolean("no_wilderness", false).comment("Requires you to claim chunks in order to edit and interact with blocks"); - StringListValue NO_WILDERNESS_DIMENSIONS = CONFIG.addStringList("no_wilderness_dimensions", Collections.emptyList()).comment("Dimension ID's where the no_wilderness rule is enforced - building is only allowed in claimed chunks. If this is non-empty, it overrides the 'no_wilderness' setting."); - BooleanValue FORCE_DISABLE_MINIMAP = CONFIG.addBoolean("force_disable_minimap", false).comment("Minimap for clients connecting to this server will be disabled"); - IntValue LONG_RANGE_TRACKER_INTERVAL = CONFIG.addInt("long_range_tracker_interval", 20, 0, Integer.MAX_VALUE).comment("Interval in ticks to send updates to clients with long-range player tracking data.","Lower values mean more frequent updates but more server load and network traffic; be careful with this, especially on busy servers.","Setting this to 0 disables long-range tracking."); - BooleanValue PROTECT_UNKNOWN_EXPLOSIONS = CONFIG.addBoolean("protect_unknown_explosions", true).comment("When true, standard FTB Chunk explosion protection is applied in protected chunks when the source of the explosion cannot be determined","(Ghast fireballs are a common case - vanilla supplies a null entity source)"); - BooleanValue REQUIRE_GAME_STAGE = CONFIG.addBoolean("require_game_stage", false).comment("If true, the player must have the 'ftbchunks_mapping' Game stage to be able to use the map and minimap.\nRequires KubeJS and/or Gamestages to be installed."); - BooleanValue LOCATION_MODE_OVERRIDE = CONFIG.addBoolean("location_mode_override", false).comment("If true, \"Location Visibility\" team settings are ignored, and all players can see each other anywhere on the map."); + BooleanValue DISABLE_PROTECTION = CONFIG.addBoolean("disable_protection", false) + .comment("Disables all land protection. Useful for private servers where everyone is trusted and claims are only used for force-loading"); + EnumValue ALLY_MODE = CONFIG.addEnum("ally_mode", AllyMode.NAME_MAP) + .comment("Forced modes won't let players change their ally settings"); + EnumValue PVP_MODE = CONFIG.addEnum("pvp_mode", PvPMode.NAME_MAP) + .comment("Should PvP combat be allowed in claimed chunks? Default is ALWAYS; NEVER prevents it in all claimed chunks; PER_TEAM allows teams to decide if PvP is allowed in their claims"); + BooleanValue NO_WILDERNESS = CONFIG.addBoolean("no_wilderness", false) + .comment("Requires you to claim chunks in order to edit and interact with blocks"); + StringListValue NO_WILDERNESS_DIMENSIONS = CONFIG.addStringList("no_wilderness_dimensions", Collections.emptyList()) + .comment("Dimension ID's where the no_wilderness rule is enforced - building is only allowed in claimed chunks. If this is non-empty, it overrides the 'no_wilderness' setting."); + BooleanValue FORCE_DISABLE_MINIMAP = CONFIG.addBoolean("force_disable_minimap", false) + .comment("Minimap for clients connecting to this server will be disabled"); + IntValue LONG_RANGE_TRACKER_INTERVAL = CONFIG.addInt("long_range_tracker_interval", 20, 0, Integer.MAX_VALUE) + .comment("Interval in ticks to send updates to clients with long-range player tracking data.","Lower values mean more frequent updates but more server load and network traffic; be careful with this, especially on busy servers.","Setting this to 0 disables long-range tracking."); + BooleanValue PROTECT_UNKNOWN_EXPLOSIONS = CONFIG.addBoolean("protect_unknown_explosions", true) + .comment("When true, standard FTB Chunk explosion protection is applied in protected chunks when the source of the explosion cannot be determined","(Ghast fireballs are a common case - vanilla supplies a null entity source)"); + BooleanValue REQUIRE_GAME_STAGE = CONFIG.addBoolean("require_game_stage", false) + .comment("If true, the player must have the 'ftbchunks_mapping' Game stage to be able to use the map and minimap.\nRequires KubeJS and/or Gamestages to be installed."); + BooleanValue LOCATION_MODE_OVERRIDE = CONFIG.addBoolean("location_mode_override", false) + .comment("If true, \"Location Visibility\" team settings are ignored, and all players can see each other anywhere on the map."); SNBTConfig FAKE_PLAYERS = CONFIG.addGroup("fake_players"); - EnumValue ALLOW_FAKE_PLAYERS = FAKE_PLAYERS.addEnum("fake_players", NameMap.of(ProtectionPolicy.CHECK, ProtectionPolicy.values()).create()).comment("Override to disable/enable fake players like miners and auto-clickers globally.","Default will check this setting for each team"); - IntValue MAX_PREVENTED_LOG_AGE = FAKE_PLAYERS.addInt("max_prevented_log_age", 7, 1, Integer.MAX_VALUE).comment("Maximum time in days to keep logs of prevented fakeplayer access to a team's claims."); + EnumValue ALLOW_FAKE_PLAYERS = FAKE_PLAYERS.addEnum("fake_players", NameMap.of(ProtectionPolicy.CHECK, ProtectionPolicy.values()).create()) + .comment("Override to disable/enable fake players like miners and auto-clickers globally.","Default will check this setting for each team"); + IntValue MAX_PREVENTED_LOG_AGE = FAKE_PLAYERS.addInt("max_prevented_log_age", 7, 1, Integer.MAX_VALUE) + .comment("Maximum time in days to keep logs of prevented fakeplayer access to a team's claims."); SNBTConfig CLAIMING = CONFIG.addGroup("claiming"); - IntValue MAX_CLAIMED_CHUNKS = CLAIMING.addInt("max_claimed_chunks", 500).comment("Max claimed chunks.", "You can override this with FTB Ranks 'ftbchunks.max_claimed' permission"); - StringListValue CLAIM_DIMENSION_BLACKLIST = CLAIMING.addStringList("claim_dimension_blacklist", Collections.emptyList()).comment("Dimension ID's where chunks may not be claimed. Add \"minecraft:the_end\" to this list if you want to disable chunk claiming in The End, or \"othermod:*\" to disable chunk claiming in *all* dimensions added by \"othermod\""); - StringListValue CLAIM_DIMENSION_WHITELIST = CLAIMING.addStringList("claim_dimension_whitelist", Collections.emptyList()).comment("Dimension ID's where chunks may be claimed. If non-empty, chunks may be claimed *only* in these dimensions (and the dimension is not in \"claim_dimension_blacklist\"). Same syntax as for \"claim_dimension_blacklist\"."); - DoubleValue MAX_IDLE_DAYS_BEFORE_UNCLAIM = CLAIMING.addDouble("max_idle_days_before_unclaim", 0D, 0D, 3650D).comment("Maximum time (in real-world days) where if no player in a team logs in, the team automatically loses their claims.", "Prevents chunks being claimed indefinitely by teams who no longer play.","Default of 0 means no automatic loss of claims."); - IntValue HARD_TEAM_CLAIM_LIMIT = CLAIMING.addInt("hard_team_claim_limit", 0, 0, Integer.MAX_VALUE).comment("Hard limit for the number of chunks a team can claim, regardless of how many members. Default of 0 means no hard limit."); - EnumValue PARTY_LIMIT_MODE = CLAIMING.addEnum("party_limit_mode", PartyLimitMode.NAME_MAP).comment("Method by which party claim & force-load limits are calculated.","LARGEST: use the limits of the member with the largest limits","SUM: add up all the members' limits","OWNER: use the party owner's limits only","AVERAGE: use the average of all members' limits."); + IntValue MAX_CLAIMED_CHUNKS = CLAIMING.addInt("max_claimed_chunks", 500) + .comment("Max claimed chunks.", "You can override this with FTB Ranks 'ftbchunks.max_claimed' permission"); + StringListValue CLAIM_DIMENSION_BLACKLIST = CLAIMING.addStringList("claim_dimension_blacklist", Collections.emptyList()) + .comment("Dimension ID's where chunks may not be claimed. Add \"minecraft:the_end\" to this list if you want to disable chunk claiming in The End, or \"othermod:*\" to disable chunk claiming in *all* dimensions added by \"othermod\""); + StringListValue CLAIM_DIMENSION_WHITELIST = CLAIMING.addStringList("claim_dimension_whitelist", Collections.emptyList()) + .comment("Dimension ID's where chunks may be claimed. If non-empty, chunks may be claimed *only* in these dimensions (and the dimension is not in \"claim_dimension_blacklist\"). Same syntax as for \"claim_dimension_blacklist\"."); + DoubleValue MAX_IDLE_DAYS_BEFORE_UNCLAIM = CLAIMING.addDouble("max_idle_days_before_unclaim", 0D, 0D, 3650D) + .comment("Maximum time (in real-world days) where if no player in a team logs in, the team automatically loses their claims.", "Prevents chunks being claimed indefinitely by teams who no longer play.","Default of 0 means no automatic loss of claims."); + IntValue HARD_TEAM_CLAIM_LIMIT = CLAIMING.addInt("hard_team_claim_limit", 0, 0, Integer.MAX_VALUE) + .comment("Hard limit for the number of chunks a team can claim, regardless of how many members. Default of 0 means no hard limit."); + EnumValue PARTY_LIMIT_MODE = CLAIMING.addEnum("party_limit_mode", PartyLimitMode.NAME_MAP) + .comment("Method by which party claim & force-load limits are calculated.","LARGEST: use the limits of the member with the largest limits","SUM: add up all the members' limits","OWNER: use the party owner's limits only","AVERAGE: use the average of all members' limits."); SNBTConfig FORCE_LOADING = CONFIG.addGroup("force_loading"); - EnumValue FORCE_LOAD_MODE = FORCE_LOADING.addEnum("force_load_mode", ForceLoadMode.NAME_MAP).comment("Control how force-loaded chunks work.","NEVER: only allow chunk force-loading if the owning team has at least one online player.","ALWAYS: always allow force-loading, even if no players are online.","DEFAULT: allow force-loading IF the team has at least one player with the 'ftbchunks.chunk_load_offline' FTB Ranks permission."); - IntValue MAX_FORCE_LOADED_CHUNKS = FORCE_LOADING.addInt("max_force_loaded_chunks", 25).comment("Max force loaded chunks.", "You can override this with FTB Ranks 'ftbchunks.max_force_loaded' permission"); - DoubleValue MAX_IDLE_DAYS_BEFORE_UNFORCE = FORCE_LOADING.addDouble("max_idle_days_before_unforce", 0D, 0D, 3650D).comment("Maximum time (in real-world days) where if no player in a team logs in, any forceloaded chunks owned by the team are no longer forceloaded.", "Prevents chunks being forceloaded indefinitely by teams who no longer play.","Default of 0 means no automatic loss of forceloading."); - IntValue HARD_TEAM_FORCE_LIMIT = FORCE_LOADING.addInt("hard_team_force_limit", 0, 0, Integer.MAX_VALUE).comment("Hard limit for the number of chunks a team can force-load, regardless of how many members. Default of 0 means no hard limit."); + EnumValue FORCE_LOAD_MODE = FORCE_LOADING.addEnum("force_load_mode", ForceLoadMode.NAME_MAP) + .comment("Control how force-loaded chunks work.","NEVER: only allow chunk force-loading if the owning team has at least one online player.","ALWAYS: always allow force-loading, even if no players are online.","DEFAULT: allow force-loading IF the team has at least one player with the 'ftbchunks.chunk_load_offline' FTB Ranks permission."); + IntValue MAX_FORCE_LOADED_CHUNKS = FORCE_LOADING.addInt("max_force_loaded_chunks", 25) + .comment("Max force loaded chunks.", "You can override this with FTB Ranks 'ftbchunks.max_force_loaded' permission"); + DoubleValue MAX_IDLE_DAYS_BEFORE_UNFORCE = FORCE_LOADING.addDouble("max_idle_days_before_unforce", 0D, 0D, 3650D) + .comment("Maximum time (in real-world days) where if no player in a team logs in, any forceloaded chunks owned by the team are no longer forceloaded.", "Prevents chunks being forceloaded indefinitely by teams who no longer play.","Default of 0 means no automatic loss of forceloading."); + IntValue HARD_TEAM_FORCE_LIMIT = FORCE_LOADING.addInt("hard_team_force_limit", 0, 0, Integer.MAX_VALUE) + .comment("Hard limit for the number of chunks a team can force-load, regardless of how many members. Default of 0 means no hard limit."); SNBTConfig WAYPOINT_SHARING = CONFIG.addGroup("waypoint_sharing"); - BooleanValue WAYPOINT_SHARING_SERVER = WAYPOINT_SHARING.addBoolean("waypoint_sharing_server", true).comment("Allow players to share waypoints with the entire server."); - BooleanValue WAYPOINT_SHARING_PARTY = WAYPOINT_SHARING.addBoolean("waypoint_sharing_party", true).comment("Allow players to share waypoints with their party."); - BooleanValue WAYPOINT_SHARING_PLAYERS = WAYPOINT_SHARING.addBoolean("waypoint_sharing_players", true).comment("Allow players to share waypoints with other players."); + BooleanValue WAYPOINT_SHARING_SERVER = WAYPOINT_SHARING.addBoolean("waypoint_sharing_server", true) + .comment("Allow players to share waypoints with the entire server."); + BooleanValue WAYPOINT_SHARING_PARTY = WAYPOINT_SHARING.addBoolean("waypoint_sharing_party", true) + .comment("Allow players to share waypoints with their party."); + BooleanValue WAYPOINT_SHARING_PLAYERS = WAYPOINT_SHARING.addBoolean("waypoint_sharing_players", true) + .comment("Allow players to share waypoints with other players."); + + SNBTConfig TEAM_PROP_DEFAULTS = CONFIG.addGroup("team_prop_defaults"); + BooleanValue DEF_ALLOW_FAKE_PLAYERS = TEAM_PROP_DEFAULTS.addBoolean("def_fake_players", false) + .comment("Default allow-fake-player setting for team properties"); + BooleanValue DEF_ALLOW_FAKE_PLAYER_IDS = TEAM_PROP_DEFAULTS.addBoolean("def_fake_player_ids", true) + .comment("Default allow fake player IDs which are the same as real permitted players"); + StringListValue DEF_ALLOW_NAMED_FAKE_PLAYERS = TEAM_PROP_DEFAULTS.addStringList("def_named_fake_players", Collections.emptyList()) + .comment("Default named fake players who should be allowed by default"); + EnumValue DEF_ENTITY_INTERACT = TEAM_PROP_DEFAULTS.addEnum("def_entity_interact", PrivacyMode.NAME_MAP, PrivacyMode.ALLIES) + .comment("Default mode for entity interaction in claimed chunks"); + EnumValue DEF_BLOCK_INTERACT = TEAM_PROP_DEFAULTS.addEnum("def_block_interact", PrivacyMode.NAME_MAP, PrivacyMode.ALLIES) + .comment("Default mode for block interaction (right-click) in claimed chunks (NeoForge only)") + .enabled(Platform::isForgeLike); + EnumValue DEF_BLOCK_EDIT = TEAM_PROP_DEFAULTS.addEnum("def_block_edit", PrivacyMode.NAME_MAP, PrivacyMode.ALLIES) + .comment("Default mode for block breaking and placing in claimed chunks (NeoForge only)") + .enabled(Platform::isForgeLike); + EnumValue DEF_BLOCK_EDIT_INTERACT = TEAM_PROP_DEFAULTS.addEnum("def_block_edit_interact", PrivacyMode.NAME_MAP, PrivacyMode.ALLIES) + .comment("Default mode for block interaction, breaking and placing in claimed chunks (Fabric only)") + .enabled(Platform::isFabric); + EnumValue DEF_NONLIVING_ENTITY_ATTACK = TEAM_PROP_DEFAULTS.addEnum("def_entity_attack", PrivacyMode.NAME_MAP, PrivacyMode.ALLIES) + .comment("Default mode for left-clicking non-living entities (armor stands, item frames...) in claimed chunks"); + BooleanValue DEF_ALLOW_EXPLOSIONS = TEAM_PROP_DEFAULTS.addBoolean("def_allow_explosions", false) + .comment("Default explosion protection for claimed chunks"); + BooleanValue DEF_MOB_GRIEFING = TEAM_PROP_DEFAULTS.addBoolean("def_mob_griefing", false) + .comment("Default mob griefing protection for claimed chunks"); + EnumValue DEF_CLAIM_VISIBILITY = TEAM_PROP_DEFAULTS.addEnum("def_claim_visibility", PrivacyMode.NAME_MAP, PrivacyMode.PUBLIC) + .comment("Default claim visibility for claimed chunks"); + EnumValue DEF_PLAYER_VISIBILITY = TEAM_PROP_DEFAULTS.addEnum("def_player_visibility", PrivacyMode.NAME_MAP, PrivacyMode.ALLIES) + .comment("Default long-range player visibility on map"); + BooleanValue DEF_PVP = TEAM_PROP_DEFAULTS.addBoolean("def_pvp", true) + .comment("Default PvP setting in claimed chunks"); static int getMaxClaimedChunks(ChunkTeamData playerData, ServerPlayer player) { if (player != null) { diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/api/FTBChunksProperties.java b/common/src/main/java/dev/ftb/mods/ftbchunks/api/FTBChunksProperties.java index b651ced0..73db5037 100644 --- a/common/src/main/java/dev/ftb/mods/ftbchunks/api/FTBChunksProperties.java +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/api/FTBChunksProperties.java @@ -1,5 +1,6 @@ package dev.ftb.mods.ftbchunks.api; +import dev.ftb.mods.ftbchunks.FTBChunksWorldConfig; import dev.ftb.mods.ftbteams.api.property.BooleanProperty; import dev.ftb.mods.ftbteams.api.property.PrivacyMode; import dev.ftb.mods.ftbteams.api.property.PrivacyProperty; @@ -12,34 +13,34 @@ */ public class FTBChunksProperties { public static final BooleanProperty ALLOW_ALL_FAKE_PLAYERS - = new BooleanProperty(FTBChunksAPI.rl("allow_fake_players"), false); + = new BooleanProperty(FTBChunksAPI.rl("allow_fake_players"), FTBChunksWorldConfig.DEF_ALLOW_FAKE_PLAYERS::get); public static final StringListProperty ALLOW_NAMED_FAKE_PLAYERS - = new StringListProperty(FTBChunksAPI.rl("allow_named_fake_players"), new ArrayList<>()); + = new StringListProperty(FTBChunksAPI.rl("allow_named_fake_players"), () -> new ArrayList<>(FTBChunksWorldConfig.DEF_ALLOW_NAMED_FAKE_PLAYERS.get())); public static final BooleanProperty ALLOW_FAKE_PLAYERS_BY_ID - = new BooleanProperty(FTBChunksAPI.rl("allow_fake_players_by_id"), true); + = new BooleanProperty(FTBChunksAPI.rl("allow_fake_players_by_id"), FTBChunksWorldConfig.DEF_ALLOW_FAKE_PLAYER_IDS::get); public static final PrivacyProperty ENTITY_INTERACT_MODE - = new PrivacyProperty(FTBChunksAPI.rl("entity_interact_mode"), PrivacyMode.ALLIES); + = new PrivacyProperty(FTBChunksAPI.rl("entity_interact_mode"), FTBChunksWorldConfig.DEF_ENTITY_INTERACT::get); public static final PrivacyProperty NONLIVING_ENTITY_ATTACK_MODE - = new PrivacyProperty(FTBChunksAPI.rl("nonliving_entity_attack_mode"), PrivacyMode.ALLIES); + = new PrivacyProperty(FTBChunksAPI.rl("nonliving_entity_attack_mode"), FTBChunksWorldConfig.DEF_NONLIVING_ENTITY_ATTACK::get); public static final BooleanProperty ALLOW_EXPLOSIONS - = new BooleanProperty(FTBChunksAPI.rl("allow_explosions"), false); + = new BooleanProperty(FTBChunksAPI.rl("allow_explosions"), FTBChunksWorldConfig.DEF_ALLOW_EXPLOSIONS::get); public static final BooleanProperty ALLOW_MOB_GRIEFING - = new BooleanProperty(FTBChunksAPI.rl("allow_mob_griefing"), false); + = new BooleanProperty(FTBChunksAPI.rl("allow_mob_griefing"), FTBChunksWorldConfig.DEF_MOB_GRIEFING::get); public static final PrivacyProperty CLAIM_VISIBILITY - = new PrivacyProperty(FTBChunksAPI.rl("claim_visibility"), PrivacyMode.PUBLIC); + = new PrivacyProperty(FTBChunksAPI.rl("claim_visibility"), FTBChunksWorldConfig.DEF_CLAIM_VISIBILITY::get); public static final PrivacyProperty LOCATION_MODE - = new PrivacyProperty(FTBChunksAPI.rl("location_mode"), PrivacyMode.ALLIES); + = new PrivacyProperty(FTBChunksAPI.rl("location_mode"), FTBChunksWorldConfig.DEF_PLAYER_VISIBILITY::get); public static final BooleanProperty ALLOW_PVP - = new BooleanProperty(FTBChunksAPI.rl("allow_pvp"), true); + = new BooleanProperty(FTBChunksAPI.rl("allow_pvp"), FTBChunksWorldConfig.DEF_PVP::get); // FTB Chunks on Forge adds two separate block edit & interact properties public static final PrivacyProperty BLOCK_EDIT_MODE - = new PrivacyProperty(FTBChunksAPI.rl("block_edit_mode"), PrivacyMode.ALLIES); + = new PrivacyProperty(FTBChunksAPI.rl("block_edit_mode"), FTBChunksWorldConfig.DEF_BLOCK_EDIT::get); public static final PrivacyProperty BLOCK_INTERACT_MODE - = new PrivacyProperty(FTBChunksAPI.rl("block_interact_mode"), PrivacyMode.ALLIES); + = new PrivacyProperty(FTBChunksAPI.rl("block_interact_mode"), FTBChunksWorldConfig.DEF_BLOCK_INTERACT::get); // FTB Chunks on Fabric adds a combined block edit & interact property public static final PrivacyProperty BLOCK_EDIT_AND_INTERACT_MODE - = new PrivacyProperty(FTBChunksAPI.rl("block_edit_and_interact_mode"), PrivacyMode.ALLIES); + = new PrivacyProperty(FTBChunksAPI.rl("block_edit_and_interact_mode"), FTBChunksWorldConfig.DEF_BLOCK_EDIT_INTERACT::get); } diff --git a/common/src/main/resources/assets/ftbchunks/lang/en_us.json b/common/src/main/resources/assets/ftbchunks/lang/en_us.json index 8610642f..ce275629 100644 --- a/common/src/main/resources/assets/ftbchunks/lang/en_us.json +++ b/common/src/main/resources/assets/ftbchunks/lang/en_us.json @@ -227,6 +227,20 @@ "ftbchunks.waypoint_sharing.waypoint_sharing_party": "Allow Sharing waypoints with Party", "ftbchunks.waypoint_sharing.waypoint_sharing_server": "Allow Sharing waypoints with Server", "ftbchunks.waypoint_sharing.waypoint_sharing_players": "Allow Sharing waypoints with Players", + "ftbchunks.team_prop_defaults": "Team Property Defaults", + "ftbchunks.team_prop_defaults.def_fake_players": "Allow All Fake Players", + "ftbchunks.team_prop_defaults.def_fake_player_ids": "Allow Fake Players by ID", + "ftbchunks.team_prop_defaults.def_named_fake_players": "Named Fake Players", + "ftbchunks.team_prop_defaults.def_allow_explosions": "Allow Explosion Damage", + "ftbchunks.team_prop_defaults.def_pvp": "Allow PvP Combat", + "ftbchunks.team_prop_defaults.def_mob_griefing": "Allow Mob Griefing Actions", + "ftbchunks.team_prop_defaults.def_block_edit_interact": "Block Edit/Interact Mode", + "ftbchunks.team_prop_defaults.def_block_edit": "Block Edit Mode", + "ftbchunks.team_prop_defaults.def_block_interact": "Block Interact Mode", + "ftbchunks.team_prop_defaults.def_entity_interact": "Entity Interact Mode", + "ftbchunks.team_prop_defaults.def_entity_attack": "Non-living Entity Attack Mode", + "ftbchunks.team_prop_defaults.def_player_visibility": "Location Visibility", + "ftbchunks.team_prop_defaults.def_claim_visibility": "Claim Visibility", "ftbchunks.map_mode.none": "None", "ftbchunks.map_mode.night": "Night", "ftbchunks.map_mode.topography": "Topography", From 3538bebca72fd9cd275d8ec54b797c58aef656ea Mon Sep 17 00:00:00 2001 From: Des Herriott Date: Mon, 9 Sep 2024 12:00:18 +0100 Subject: [PATCH 4/6] chore: better width calculation for waypoint manager screen --- .../client/gui/WaypointEditorScreen.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/WaypointEditorScreen.java b/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/WaypointEditorScreen.java index 2b399320..b688f41d 100644 --- a/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/WaypointEditorScreen.java +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/WaypointEditorScreen.java @@ -28,19 +28,24 @@ import net.minecraft.network.chat.Style; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import org.lwjgl.glfw.GLFW; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.*; import static dev.ftb.mods.ftblibrary.util.TextComponentUtils.hotkeyTooltip; public class WaypointEditorScreen extends AbstractButtonListScreen { + private static final Logger log = LoggerFactory.getLogger(WaypointEditorScreen.class); private final Map, Boolean> collapsed = new HashMap<>(); private final Map, List> waypoints = new HashMap<>(); private final Button buttonCollapseAll, buttonExpandAll; + private int widestWp = 0; public WaypointEditorScreen() { showBottomPanel(false); @@ -51,12 +56,23 @@ public WaypointEditorScreen() { waypoints.put(resourceKeyListEntry.getKey(), new ArrayList<>(resourceKeyListEntry.getValue())); } + calcWidestWpText(); + buttonExpandAll = new SimpleButton(topPanel, List.of(Component.translatable("gui.expand_all"), hotkeyTooltip("="), hotkeyTooltip("+")), Icons.UP, (widget, button) -> toggleAll(true)); buttonCollapseAll = new SimpleButton(topPanel, List.of(Component.translatable("gui.collapse_all"), hotkeyTooltip("-")), Icons.DOWN, (widget, button) -> toggleAll(false)); } + private void calcWidestWpText() { + widestWp = 0; + for (var dimKey : waypoints.entrySet()) { + for (var wp : dimKey.getValue()) { + widestWp = Math.max(widestWp, getTheme().getStringWidth(wp.getName())); + } + } + } + private void toggleAll(boolean collapsed) { boolean allOpen = this.collapsed.values().stream().noneMatch(b -> b); //Don't try and re-render if everything is already open @@ -78,7 +94,7 @@ protected void doAccept() { @Override public boolean onInit() { - setWidth(220); + setWidth(Mth.clamp(widestWp + 80, 220, getScreen().getGuiScaledWidth() * 4 / 5)); setHeight(getScreen().getGuiScaledHeight() * 4 / 5); return true; } @@ -290,6 +306,7 @@ public boolean mousePressed(MouseButton button) { if (accepted) { wp.setName(config.getValue()); } + calcWidestWpText(); openGui(); }); })); From fd6aa948d776d891c575a188f0c053795f1bc8b4 Mon Sep 17 00:00:00 2001 From: Des Herriott Date: Mon, 9 Sep 2024 12:00:35 +0100 Subject: [PATCH 5/6] chore: changelog updated --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 334e364d..d00c09cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added * Added `/ftbchunks admin open_claim_gui_as` command * Allows server admins to open the chunk claim gui as any player - * Offline players are also supported (but names of offline players aren't suggested in command completion) + * Offline players are also supported, but names of offline players aren't suggested in command tab-completion +* Added team property defaults in server config (see "Team Property Defaults" section) + * Properties for newly-created teams are now taken from these defaults ### Changed * Reworked the chunk claim GUI for a more polished visual appearance From d7cf41b91e76f8be6cafb120aa557c22560e0de4 Mon Sep 17 00:00:00 2001 From: Des Herriott Date: Mon, 9 Sep 2024 14:22:27 +0100 Subject: [PATCH 6/6] chore: bit of code cleanup --- .../ftbchunks/client/gui/ChunkScreenPanel.java | 2 -- .../ftbchunks/client/gui/WaypointEditorScreen.java | 14 +++++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/ChunkScreenPanel.java b/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/ChunkScreenPanel.java index 5118f29d..5f47e1fb 100644 --- a/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/ChunkScreenPanel.java +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/ChunkScreenPanel.java @@ -63,11 +63,9 @@ public ChunkScreenPanel(ChunkScreen panel) { this.isAdminEnabled = Minecraft.getInstance().isSingleplayer(); - MapManager.getInstance().ifPresent(m -> m.updateAllRegions(false)); alignWidgets(); - } public static void notifyChunkUpdates(int totalChunks, int changedChunks, EnumMap problems) { diff --git a/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/WaypointEditorScreen.java b/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/WaypointEditorScreen.java index b688f41d..db2a0ec8 100644 --- a/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/WaypointEditorScreen.java +++ b/common/src/main/java/dev/ftb/mods/ftbchunks/client/gui/WaypointEditorScreen.java @@ -45,7 +45,7 @@ public class WaypointEditorScreen extends AbstractButtonListScreen { private final Map, Boolean> collapsed = new HashMap<>(); private final Map, List> waypoints = new HashMap<>(); private final Button buttonCollapseAll, buttonExpandAll; - private int widestWp = 0; + private int widestWaypoint = 0; public WaypointEditorScreen() { showBottomPanel(false); @@ -56,7 +56,7 @@ public WaypointEditorScreen() { waypoints.put(resourceKeyListEntry.getKey(), new ArrayList<>(resourceKeyListEntry.getValue())); } - calcWidestWpText(); + computeWaypointTextWidth(); buttonExpandAll = new SimpleButton(topPanel, List.of(Component.translatable("gui.expand_all"), hotkeyTooltip("="), hotkeyTooltip("+")), Icons.UP, (widget, button) -> toggleAll(true)); @@ -64,11 +64,11 @@ public WaypointEditorScreen() { (widget, button) -> toggleAll(false)); } - private void calcWidestWpText() { - widestWp = 0; + private void computeWaypointTextWidth() { + widestWaypoint = 0; for (var dimKey : waypoints.entrySet()) { for (var wp : dimKey.getValue()) { - widestWp = Math.max(widestWp, getTheme().getStringWidth(wp.getName())); + widestWaypoint = Math.max(widestWaypoint, getTheme().getStringWidth(wp.getName())); } } } @@ -94,7 +94,7 @@ protected void doAccept() { @Override public boolean onInit() { - setWidth(Mth.clamp(widestWp + 80, 220, getScreen().getGuiScaledWidth() * 4 / 5)); + setWidth(Mth.clamp(widestWaypoint + 80, 220, getScreen().getGuiScaledWidth() * 4 / 5)); setHeight(getScreen().getGuiScaledHeight() * 4 / 5); return true; } @@ -306,7 +306,7 @@ public boolean mousePressed(MouseButton button) { if (accepted) { wp.setName(config.getValue()); } - calcWidestWpText(); + computeWaypointTextWidth(); openGui(); }); }));