From 0e77509e0c0e905fa9715a565a2c8cada342d31d Mon Sep 17 00:00:00 2001 From: Light_Quanta Date: Fri, 23 May 2025 15:41:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=9B=B4=E6=96=B0=E7=8B=97?= =?UTF-8?q?=E7=89=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/ClientRenderHandler.java | 1 + .../client/overlay/KillMessageOverlay.java | 61 ++++ .../client/screens/DogTagEditorScreen.java | 280 ++++++++++++++++++ .../tooltip/ClientDogTagImageTooltip.java | 80 +++++ .../component/DogTagImageComponent.java | 21 ++ .../client/DisplayClothConfig.java | 16 + .../component/ModDataComponents.java | 5 + .../config/client/DisplayConfig.java | 8 + .../superbwarfare/init/ModMenuTypes.java | 9 +- .../superbwarfare/init/ModScreens.java | 6 +- .../atsuishio/superbwarfare/item/DogTag.java | 52 ++++ .../superbwarfare/menu/DogTagEditorMenu.java | 106 +++++++ .../network/ClientPacketHandler.java | 13 + .../network/NetworkRegistry.java | 2 + .../message/receive/DogTagEditorMessage.java | 31 ++ .../message/send/DogTagFinishEditMessage.java | 39 +++ .../assets/superbwarfare/lang/en_us.json | 9 +- .../assets/superbwarfare/lang/zh_cn.json | 7 +- .../textures/gui/dog_tag_editor.png | Bin 0 -> 2671 bytes .../resources/data/curios/slots/dog_tag.json | 5 + 20 files changed, 736 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/screens/DogTagEditorScreen.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientDogTagImageTooltip.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/DogTagImageComponent.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/menu/DogTagEditorMenu.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/network/message/receive/DogTagEditorMessage.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/network/message/send/DogTagFinishEditMessage.java create mode 100644 src/main/resources/assets/superbwarfare/textures/gui/dog_tag_editor.png create mode 100644 src/main/resources/data/curios/slots/dog_tag.json diff --git a/src/main/java/com/atsuishio/superbwarfare/client/ClientRenderHandler.java b/src/main/java/com/atsuishio/superbwarfare/client/ClientRenderHandler.java index b4959b124..c001ea5c2 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/ClientRenderHandler.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/ClientRenderHandler.java @@ -25,6 +25,7 @@ public class ClientRenderHandler { event.register(LauncherImageComponent.class, ClientLauncherImageTooltip::new); event.register(SecondaryCataclysmImageComponent.class, ClientSecondaryCataclysmImageTooltip::new); event.register(ChargingStationImageComponent.class, ClientChargingStationImageTooltip::new); + event.register(DogTagImageComponent.class, ClientDogTagImageTooltip::new); } @SubscribeEvent diff --git a/src/main/java/com/atsuishio/superbwarfare/client/overlay/KillMessageOverlay.java b/src/main/java/com/atsuishio/superbwarfare/client/overlay/KillMessageOverlay.java index cfd4cb9bd..3995b4b88 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/overlay/KillMessageOverlay.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/overlay/KillMessageOverlay.java @@ -1,27 +1,35 @@ package com.atsuishio.superbwarfare.client.overlay; import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.client.RenderHelper; +import com.atsuishio.superbwarfare.client.screens.DogTagEditorScreen; +import com.atsuishio.superbwarfare.client.tooltip.ClientDogTagImageTooltip; +import com.atsuishio.superbwarfare.config.client.DisplayConfig; import com.atsuishio.superbwarfare.config.client.KillMessageConfig; import com.atsuishio.superbwarfare.entity.vehicle.base.ArmedVehicleEntity; import com.atsuishio.superbwarfare.entity.vehicle.base.VehicleEntity; import com.atsuishio.superbwarfare.event.KillMessageHandler; import com.atsuishio.superbwarfare.init.ModDamageTypes; import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.item.DogTag; import com.atsuishio.superbwarfare.item.gun.GunItem; import com.atsuishio.superbwarfare.tools.DamageTypeTool; import com.atsuishio.superbwarfare.tools.PlayerKillRecord; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.ChatFormatting; import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.LayeredDraw; +import net.minecraft.client.renderer.RenderType; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; @@ -176,6 +184,12 @@ public class KillMessageOverlay implements LayeredDraw.Layer { false ); + // 渲染狗牌图标 + if (record.target instanceof LivingEntity living && shouldRenderDogTagIcon(living)) { + currentPosX -= 14; + renderDogTagIcon(guiGraphics, living, currentPosX, top - 0.5f); + } + // 渲染伤害类型图标 ResourceLocation damageTypeIcon = getDamageTypeIcon(record); if (damageTypeIcon != null) { @@ -222,9 +236,21 @@ public class KillMessageOverlay implements LayeredDraw.Layer { record.attacker.getTeamColor(), false ); + + // 渲染狗牌图标 + if (shouldRenderDogTagIcon(record.attacker)) { + currentPosX -= 14; + renderDogTagIcon(guiGraphics, record.attacker, currentPosX, top - 0.5f); + } } else { float currentPosX = width + 10f; + // 渲染狗牌图标 + if (shouldRenderDogTagIcon(record.attacker)) { + renderDogTagIcon(guiGraphics, record.attacker, currentPosX, top - 0.5f); + currentPosX += 14; + } + // 渲染击杀者名称 String attackerName = getEntityName(record.attacker); guiGraphics.drawString( @@ -272,6 +298,12 @@ public class KillMessageOverlay implements LayeredDraw.Layer { currentPosX += 18; } + // 渲染狗牌图标 + if (record.target instanceof LivingEntity living && shouldRenderDogTagIcon(living)) { + renderDogTagIcon(guiGraphics, living, currentPosX, top - 0.5f); + currentPosX += 14; + } + // 渲染被击杀者名称 guiGraphics.drawString( Minecraft.getInstance().font, @@ -370,4 +402,33 @@ public class KillMessageOverlay implements LayeredDraw.Layer { } return null; } + + public static boolean shouldRenderDogTagIcon(LivingEntity living) { + return CuriosApi.getCuriosInventory(living) + .flatMap(c -> c.findFirstCurio(ModItems.DOG_TAG.get())) + .map(s -> ClientDogTagImageTooltip.shouldRenderIcon(s.stack())) + .orElse(false) + && DisplayConfig.DOG_TAG_ICON_VISIBLE.get(); + } + + public static void renderDogTagIcon(GuiGraphics guiGraphics, LivingEntity living, float x, float y) { + CuriosApi.getCuriosInventory(living).flatMap(c -> c.findFirstCurio(ModItems.DOG_TAG.get())).ifPresent(s -> { + short[][] icon = DogTag.getColors(s.stack()); + guiGraphics.pose().pushPose(); + + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + if (icon[i][j] == -1) continue; + + var color = ChatFormatting.getById(icon[i][j]); + RenderHelper.fill(guiGraphics, RenderType.gui(), + x + i * 0.6f, y + j * 0.6f, x + (i + 1) * 0.6f, y + (j + 1) * 0.6f, + 0, DogTagEditorScreen.getColorFromFormatting(color) + ); + } + } + + guiGraphics.pose().popPose(); + }); + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/client/screens/DogTagEditorScreen.java b/src/main/java/com/atsuishio/superbwarfare/client/screens/DogTagEditorScreen.java new file mode 100644 index 000000000..db71be82b --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/screens/DogTagEditorScreen.java @@ -0,0 +1,280 @@ +package com.atsuishio.superbwarfare.client.screens; + +import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.item.DogTag; +import com.atsuishio.superbwarfare.menu.DogTagEditorMenu; +import com.atsuishio.superbwarfare.network.message.send.DogTagFinishEditMessage; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractButton; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.core.component.DataComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ServerboundRenameItemPacket; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import net.neoforged.neoforge.network.PacketDistributor; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Arrays; + +@OnlyIn(Dist.CLIENT) +public class DogTagEditorScreen extends AbstractContainerScreen { + + private static final ResourceLocation TEXTURE = Mod.loc("textures/gui/dog_tag_editor.png"); + + public EditBox name; + private short currentColor = 0; + private short[][] icon = new short[16][16]; + public ItemStack stack; + private boolean init = false; + + public DogTagEditorScreen(DogTagEditorMenu pMenu, Inventory pPlayerInventory, Component pTitle) { + super(pMenu, pPlayerInventory, pTitle); + this.stack = pMenu.stack; + imageWidth = 207; + imageHeight = 185; + } + + @Override + protected void renderBg(GuiGraphics pGuiGraphics, float pPartialTick, int pMouseX, int pMouseY) { + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + pGuiGraphics.blit(TEXTURE, i, j, 0, 0, this.imageWidth, this.imageHeight, 256, 256); + + ItemStack stack = DogTagEditorScreen.this.menu.stack; + pGuiGraphics.renderItem(stack, i + 18, j + 36); + + var pose = pGuiGraphics.pose(); + + pose.pushPose(); + + for (int x = 0; x < this.icon.length; x++) { + for (int y = 0; y < this.icon.length; y++) { + int num = this.icon[x][y]; + if (num != -1) { + var color = ChatFormatting.getById(num); + pGuiGraphics.fill(i + 66 + x * 9, j + 44 + y * 9, i + 58 + x * 9, j + 36 + y * 9, + getColorFromFormatting(color)); + } + } + } + + pose.popPose(); + } + + @Override + public void render(@NotNull GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + this.renderBackground(pGuiGraphics, pMouseX, pMouseY, pPartialTick); + super.render(pGuiGraphics, pMouseX, pMouseY, pPartialTick); + this.name.render(pGuiGraphics, pMouseX, pMouseY, pPartialTick); + this.renderTooltip(pGuiGraphics, pMouseX, pMouseY); + } + + @Override + public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { + this.drawColor(pMouseX, pMouseY, pButton); + return super.mouseClicked(pMouseX, pMouseY, pButton); + } + + @Override + public boolean mouseDragged(double pMouseX, double pMouseY, int pButton, double pDragX, double pDragY) { + this.drawColor(pMouseX, pMouseY, pButton); + return super.mouseDragged(pMouseX, pMouseY, pButton, pDragX, pDragY); + } + + private void drawColor(double pMouseX, double pMouseY, int pButton) { + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + + if (pMouseX >= i + 57 && pMouseX <= i + 201 && pMouseY >= j + 36 && pMouseY <= j + 179) { + double posX = pMouseX - i - 57; + double posY = pMouseY - j - 36; + if (Math.ceil(posX) % 9 == 0 || Math.ceil(posY) % 9 == 0) + return; + + int x = (int) Math.floor(posX / 9); + int y = (int) Math.floor(posY / 9); + + this.icon[Mth.clamp(x, 0, 15)][Mth.clamp(y, 0, 15)] = pButton == 0 ? this.currentColor : -1; + } + } + + @Override + public void containerTick() { + super.containerTick(); +// this.name.tick(); + if (!this.init) { + if (!this.stack.isEmpty()) { + this.name.setValue(this.stack.getHoverName().getString()); + this.icon = DogTag.getColors(this.stack); + } + this.init = true; + } + } + + @Override + protected void init() { + super.init(); + this.subInit(); + + this.clearColors(); + + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + + for (short k = 0; k < 16; k++) { + var button = new ColorButton(k, i + 6 + (k % 2) * 22, j + 62 + (k / 2) * 10, 18, 8); + this.addRenderableWidget(button); + } + var eraserButton = new ColorButton((short) -1, i + 17, j + 143, 18, 8); + this.addRenderableWidget(eraserButton); + + var finishButton = new FinishButton(i + 6, j + 167, 40, 13); + this.addRenderableWidget(finishButton); + } + + protected void subInit() { + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + this.name = new EditBox(this.font, i + 9, j + 11, 180, 12, Component.literal("")); + this.name.setCanLoseFocus(false); + this.name.setTextColor(-1); + this.name.setTextColorUneditable(-1); + this.name.setBordered(false); + this.name.setMaxLength(30); + this.name.setResponder(this::onNameChanged); +// this.name.setValue(this.stack.getHoverName().getString()); + this.addWidget(this.name); + this.setInitialFocus(this.name); + this.name.setEditable(true); + } + + private void onNameChanged(String name) { + String s = name; + ItemStack stack = DogTagEditorScreen.this.menu.stack; + if (!stack.has(DataComponents.CUSTOM_NAME)) { + s = ""; + } + + if (this.menu.setItemName(s)) { + if (this.minecraft != null && this.minecraft.player != null) { + this.minecraft.player.connection.send(new ServerboundRenameItemPacket(s)); + } + } + } + + // 留空 + @Override + protected void renderLabels(@NotNull GuiGraphics pGuiGraphics, int pMouseX, int pMouseY) { + } + + public void clearColors() { + for (var el : this.icon) { + Arrays.fill(el, (short) -1); + } + } + + @OnlyIn(Dist.CLIENT) + class ColorButton extends AbstractButton { + + short color; + + public ColorButton(short color, int pX, int pY, int pWidth, int pHeight) { + super(pX, pY, pWidth, pHeight, Component.literal("")); + this.color = color; + } + + @Override + public void onPress() { + DogTagEditorScreen.this.currentColor = this.color; + if (this.color == -1 && Screen.hasShiftDown()) { + DogTagEditorScreen.this.clearColors(); + } + } + + @Override + protected void updateWidgetNarration(@NotNull NarrationElementOutput pNarrationElementOutput) { + } + + @Override + protected void renderWidget(@NotNull GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + if (this.isHovered || DogTagEditorScreen.this.currentColor == this.color) { + if (this.color == -1) { + pGuiGraphics.blit(TEXTURE, this.getX(), this.getY(), 19, 186, + 18, 8, 256, 256); + } else { + pGuiGraphics.blit(TEXTURE, this.getX(), this.getY(), 0, 186, + 18, 8, 256, 256); + } + } + } + } + + @OnlyIn(Dist.CLIENT) + class FinishButton extends AbstractButton { + + public FinishButton(int pX, int pY, int pWidth, int pHeight) { + super(pX, pY, pWidth, pHeight, Component.literal("")); + } + + @Override + public void onPress() { + if (!DogTagEditorScreen.this.init) return; + var colors = new ArrayList(DogTagEditorScreen.this.icon.length * DogTagEditorScreen.this.icon[0].length); + + for (var row : DogTagEditorScreen.this.icon) { + for (var color : row) { + colors.add(color); + } + } + + PacketDistributor.sendToServer(new DogTagFinishEditMessage(colors, DogTagEditorScreen.this.name.getValue())); + } + + @Override + protected void renderWidget(@NotNull GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + if (this.isHovered) { + pGuiGraphics.blit(TEXTURE, this.getX(), this.getY(), 0, 195, + 40, 13, 256, 256); + } + } + + @Override + protected void updateWidgetNarration(@NotNull NarrationElementOutput pNarrationElementOutput) { + } + } + + public static int getColorFromFormatting(ChatFormatting chatFormatting) { + if (chatFormatting == null) { + return -1; + } + return switch (chatFormatting) { + case BLACK -> 0xFF000000; + case DARK_BLUE -> 0xFF0000AA; + case DARK_GREEN -> 0xFF00AA00; + case DARK_AQUA -> 0xFF00AAAA; + case DARK_RED -> 0xFFAA0000; + case DARK_PURPLE -> 0xFFAA00AA; + case GOLD -> 0xFFFFAA00; + case GRAY -> 0xFFAAAAAA; + case DARK_GRAY -> 0xFF555555; + case BLUE -> 0xFF5555FF; + case GREEN -> 0xFF55FF55; + case AQUA -> 0xFF55FFFF; + case RED -> 0xFFFF5555; + case LIGHT_PURPLE -> 0xFFFF55FF; + case YELLOW -> 0xFFFFFF55; + case WHITE -> 0xFFFFFFFF; + default -> -1; + }; + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientDogTagImageTooltip.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientDogTagImageTooltip.java new file mode 100644 index 000000000..3c9ee0b0d --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientDogTagImageTooltip.java @@ -0,0 +1,80 @@ +package com.atsuishio.superbwarfare.client.tooltip; + +import com.atsuishio.superbwarfare.client.screens.DogTagEditorScreen; +import com.atsuishio.superbwarfare.client.tooltip.component.DogTagImageComponent; +import com.atsuishio.superbwarfare.item.DogTag; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.ParametersAreNonnullByDefault; + +public class ClientDogTagImageTooltip implements ClientTooltipComponent { + + protected final int width; + protected final int height; + protected final ItemStack stack; + + public ClientDogTagImageTooltip(DogTagImageComponent tooltip) { + this.width = tooltip.width; + this.height = tooltip.height; + this.stack = tooltip.stack; + } + + @Override + @ParametersAreNonnullByDefault + public void renderImage(Font pFont, int pX, int pY, GuiGraphics pGuiGraphics) { + short[][] colors = DogTag.getColors(this.stack); + if (isAllMinusOne(colors)) return; + + pGuiGraphics.pose().pushPose(); + + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + if (colors[i][j] == -1) continue; + var color = ChatFormatting.getById(colors[i][j]); + pGuiGraphics.fill(5 + pX + i * 4 + 4, 5 + pY + j * 4 + 4, 5 + pX + i * 4, 5 + pY + j * 4, + DogTagEditorScreen.getColorFromFormatting(color)); + } + } + + pGuiGraphics.pose().popPose(); + } + + @Override + public int getHeight() { + return !shouldRenderIcon(this.stack) ? 0 : this.height; + } + + @Override + public int getWidth(@NotNull Font pFont) { + return !shouldRenderIcon(this.stack) ? 0 : this.width; + } + + public static boolean shouldRenderIcon(ItemStack stack) { + short[][] colors = DogTag.getColors(stack); + return !isAllMinusOne(colors); + } + + public static boolean isAllMinusOne(short[][] arr) { + if (arr == null) { + return false; + } + + for (short[] row : arr) { + if (row == null) { + return false; + } + for (short element : row) { + if (element != (short) -1) { + return false; + } + } + } + + return true; + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/DogTagImageComponent.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/DogTagImageComponent.java new file mode 100644 index 000000000..432f335ec --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/DogTagImageComponent.java @@ -0,0 +1,21 @@ +package com.atsuishio.superbwarfare.client.tooltip.component; + +import net.minecraft.world.inventory.tooltip.TooltipComponent; +import net.minecraft.world.item.ItemStack; + +public class DogTagImageComponent implements TooltipComponent { + + public int width; + public int height; + public ItemStack stack; + + public DogTagImageComponent(int width, int height, ItemStack stack) { + this.width = width; + this.height = height; + this.stack = stack; + } + + public DogTagImageComponent(ItemStack stack) { + this(80, 80, stack); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/compat/clothconfig/client/DisplayClothConfig.java b/src/main/java/com/atsuishio/superbwarfare/compat/clothconfig/client/DisplayClothConfig.java index b8f4a3077..d5e2fc087 100644 --- a/src/main/java/com/atsuishio/superbwarfare/compat/clothconfig/client/DisplayClothConfig.java +++ b/src/main/java/com/atsuishio/superbwarfare/compat/clothconfig/client/DisplayClothConfig.java @@ -59,6 +59,22 @@ public class DisplayClothConfig { .build() ); + category.addEntry(entryBuilder + .startBooleanToggle(Component.translatable("config.superbwarfare.client.display.dog_tag_name_visible"), DisplayConfig.DOG_TAG_NAME_VISIBLE.get()) + .setDefaultValue(true) + .setSaveConsumer(DisplayConfig.DOG_TAG_NAME_VISIBLE::set) + .setTooltip(Component.translatable("config.superbwarfare.client.display.dog_tag_name_visible.des")) + .build() + ); + + category.addEntry(entryBuilder + .startBooleanToggle(Component.translatable("config.superbwarfare.client.display.dog_tag_icon_visible"), DisplayConfig.DOG_TAG_ICON_VISIBLE.get()) + .setDefaultValue(false) + .setSaveConsumer(DisplayConfig.DOG_TAG_ICON_VISIBLE::set) + .setTooltip(Component.translatable("config.superbwarfare.client.display.dog_tag_icon_visible.des")) + .build() + ); + category.addEntry(entryBuilder .startIntSlider(Component.translatable("config.superbwarfare.client.display.weapon_screen_shake"), DisplayConfig.WEAPON_SCREEN_SHAKE.get(), 0, 100) diff --git a/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java b/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java index 8f1335774..13712144d 100644 --- a/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java +++ b/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java @@ -49,6 +49,11 @@ public class ModDataComponents { builder -> builder.persistent(AmmoBoxInfo.CODEC) ); + public static final DeferredHolder, DataComponentType>> DOG_TAG_IMAGE = register( + "dog_tag_image", + builder -> builder.persistent(Codec.SHORT.listOf()) + ); + private static DeferredHolder, DataComponentType> register(String name, UnaryOperator> builderOperator) { return DATA_COMPONENT_TYPES.register(name, () -> builderOperator.apply(DataComponentType.builder()).build()); } diff --git a/src/main/java/com/atsuishio/superbwarfare/config/client/DisplayConfig.java b/src/main/java/com/atsuishio/superbwarfare/config/client/DisplayConfig.java index 7d2e2c83f..d0dc5542e 100644 --- a/src/main/java/com/atsuishio/superbwarfare/config/client/DisplayConfig.java +++ b/src/main/java/com/atsuishio/superbwarfare/config/client/DisplayConfig.java @@ -10,6 +10,8 @@ public class DisplayConfig { public static ModConfigSpec.BooleanValue CAMERA_ROTATE; public static ModConfigSpec.BooleanValue ARMOR_PLATE_HUD; public static ModConfigSpec.BooleanValue STAMINA_HUD; + public static ModConfigSpec.BooleanValue DOG_TAG_NAME_VISIBLE; + public static ModConfigSpec.BooleanValue DOG_TAG_ICON_VISIBLE; public static ModConfigSpec.IntValue WEAPON_SCREEN_SHAKE; public static ModConfigSpec.IntValue EXPLOSION_SCREEN_SHAKE; public static ModConfigSpec.IntValue SHOCK_SCREEN_SHAKE; @@ -35,6 +37,12 @@ public class DisplayConfig { builder.comment("Set true to enable stamina hud"); STAMINA_HUD = builder.define("stamina_hud", true); + builder.comment("Set true to show the name of dog tag in kill messages"); + DOG_TAG_NAME_VISIBLE = builder.define("dog_tag_name_visible", true); + + builder.comment("Set true to show the icon of dog tag in kill messages"); + DOG_TAG_ICON_VISIBLE = builder.define("dog_tag_icon_visible", false); + builder.comment("The strength of screen shaking while firing with a weapon"); WEAPON_SCREEN_SHAKE = builder.defineInRange("weapon_screen_shake", 100, 0, 100); diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModMenuTypes.java b/src/main/java/com/atsuishio/superbwarfare/init/ModMenuTypes.java index 2242c7948..36042791d 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModMenuTypes.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModMenuTypes.java @@ -1,10 +1,7 @@ package com.atsuishio.superbwarfare.init; import com.atsuishio.superbwarfare.Mod; -import com.atsuishio.superbwarfare.menu.ChargingStationMenu; -import com.atsuishio.superbwarfare.menu.FuMO25Menu; -import com.atsuishio.superbwarfare.menu.ReforgingTableMenu; -import com.atsuishio.superbwarfare.menu.VehicleMenu; +import com.atsuishio.superbwarfare.menu.*; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.inventory.MenuType; import net.neoforged.neoforge.common.extensions.IMenuTypeExtension; @@ -28,4 +25,8 @@ public class ModMenuTypes { public static final Supplier> FUMO_25_MENU = REGISTRY.register("fumo_25_menu", () -> IMenuTypeExtension.create((windowId, inv, data) -> new FuMO25Menu(windowId, inv))); + + public static final Supplier> DOG_TAG_EDITOR_MENU = + REGISTRY.register("dog_tag_editor_menu", + () -> IMenuTypeExtension.create((windowId, inv, data) -> new DogTagEditorMenu(windowId))); } diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModScreens.java b/src/main/java/com/atsuishio/superbwarfare/init/ModScreens.java index 7ef1fa0cb..9218b2b7f 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModScreens.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModScreens.java @@ -1,10 +1,7 @@ package com.atsuishio.superbwarfare.init; import com.atsuishio.superbwarfare.Mod; -import com.atsuishio.superbwarfare.client.screens.ChargingStationScreen; -import com.atsuishio.superbwarfare.client.screens.FuMO25Screen; -import com.atsuishio.superbwarfare.client.screens.ReforgingTableScreen; -import com.atsuishio.superbwarfare.client.screens.VehicleScreen; +import com.atsuishio.superbwarfare.client.screens.*; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; @@ -19,5 +16,6 @@ public class ModScreens { event.register(ModMenuTypes.CHARGING_STATION_MENU.get(), ChargingStationScreen::new); event.register(ModMenuTypes.VEHICLE_MENU.get(), VehicleScreen::new); event.register(ModMenuTypes.FUMO_25_MENU.get(), FuMO25Screen::new); + event.register(ModMenuTypes.DOG_TAG_EDITOR_MENU.get(), DogTagEditorScreen::new); } } diff --git a/src/main/java/com/atsuishio/superbwarfare/item/DogTag.java b/src/main/java/com/atsuishio/superbwarfare/item/DogTag.java index f46905be2..9a0c00cbb 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/DogTag.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/DogTag.java @@ -1,15 +1,30 @@ package com.atsuishio.superbwarfare.item; +import com.atsuishio.superbwarfare.client.tooltip.component.DogTagImageComponent; +import com.atsuishio.superbwarfare.component.ModDataComponents; +import com.atsuishio.superbwarfare.menu.DogTagEditorMenu; +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.SimpleMenuProvider; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.inventory.tooltip.TooltipComponent; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; import top.theillusivec4.curios.api.CuriosApi; import top.theillusivec4.curios.api.SlotContext; import top.theillusivec4.curios.api.type.capability.ICurioItem; +import java.util.Arrays; +import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; public class DogTag extends Item implements ICurioItem { + public DogTag() { super(new Properties().stacksTo(1)); } @@ -22,4 +37,41 @@ public class DogTag extends Item implements ICurioItem { return flag.get(); } + + @Override + public @NotNull InteractionResultHolder use(Level level, Player player, @NotNull InteractionHand usedHand) { + ItemStack stack = player.getItemInHand(usedHand); + if (level.isClientSide) { + return InteractionResultHolder.success(stack); + } else { + player.openMenu(new SimpleMenuProvider((i, inventory, p) -> + new DogTagEditorMenu(i, ContainerLevelAccess.create(level, p.getOnPos()), stack), Component.literal(""))); + return InteractionResultHolder.consume(stack); + } + } + + @Override + public @NotNull Optional getTooltipImage(@NotNull ItemStack pStack) { + return Optional.of(new DogTagImageComponent(pStack)); + } + + public static short[][] getColors(ItemStack stack) { + short[][] colors = new short[16][16]; + for (var el : colors) { + Arrays.fill(el, (short) -1); + } + + var data = stack.get(ModDataComponents.DOG_TAG_IMAGE); + if (data == null) return colors; + + var index = 0; + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + colors[i][j] = data.get(index); + index++; + } + } + + return colors; + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/menu/DogTagEditorMenu.java b/src/main/java/com/atsuishio/superbwarfare/menu/DogTagEditorMenu.java new file mode 100644 index 000000000..d929bfac4 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/menu/DogTagEditorMenu.java @@ -0,0 +1,106 @@ +package com.atsuishio.superbwarfare.menu; + +import com.atsuishio.superbwarfare.component.ModDataComponents; +import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.init.ModMenuTypes; +import com.atsuishio.superbwarfare.network.message.receive.DogTagEditorMessage; +import net.minecraft.core.component.DataComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.StringUtil; +import net.minecraft.world.Container; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.item.ItemStack; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.entity.player.PlayerContainerEvent; +import net.neoforged.neoforge.network.PacketDistributor; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; +import java.util.List; + +@EventBusSubscriber(bus = EventBusSubscriber.Bus.GAME) +public class DogTagEditorMenu extends AbstractContainerMenu { + + protected final Container container; + protected final ContainerLevelAccess access; + @Nullable + private String itemName; + + public ItemStack stack; + + public DogTagEditorMenu(int pContainerId) { + this(pContainerId, new SimpleContainer(0), ContainerLevelAccess.NULL, ItemStack.EMPTY); + } + + public DogTagEditorMenu(int pContainerId, ContainerLevelAccess access, ItemStack stack) { + this(pContainerId, new SimpleContainer(0), access, stack); + } + + public DogTagEditorMenu(int pContainerId, Container container, ContainerLevelAccess pContainerLevelAccess, ItemStack stack) { + super(ModMenuTypes.DOG_TAG_EDITOR_MENU.get(), pContainerId); + + checkContainerSize(container, 0); + + this.container = container; + this.access = pContainerLevelAccess; + this.stack = stack; + } + + @Override + public @NotNull ItemStack quickMoveStack(@NotNull Player player, int index) { + return ItemStack.EMPTY; + } + + @Override + public boolean stillValid(Player pPlayer) { + return pPlayer.isAlive(); + } + + public boolean setItemName(String name) { + String s = validateName(name); + if (s != null && !s.equals(this.itemName)) { + this.itemName = s; + if (!this.stack.isEmpty()) { + if (StringUtil.isBlank(s)) { + this.stack.remove(DataComponents.CUSTOM_NAME); + } else { + this.stack.set(DataComponents.CUSTOM_NAME, Component.literal(s)); + } + } + return true; + } else { + return false; + } + } + + @Nullable + private static String validateName(String pItemName) { + String s = StringUtil.filterText(pItemName); + return s.length() <= 30 ? s : null; + } + + @SubscribeEvent + public static void onContainerOpened(PlayerContainerEvent.Open event) { + if (event.getContainer() instanceof DogTagEditorMenu menu && event.getEntity() instanceof ServerPlayer serverPlayer) { + var stack = serverPlayer.getItemInHand(serverPlayer.getUsedItemHand()); + if (stack.is(ModItems.DOG_TAG.get())) { + PacketDistributor.sendToPlayer(serverPlayer, new DogTagEditorMessage(menu.containerId, stack)); + } + } + } + + public void finishEdit(List colors, String name) { + if (this.stack.isEmpty()) return; + + stack.set(ModDataComponents.DOG_TAG_IMAGE, colors); + + if (!name.isEmpty()) { + this.stack.set(DataComponents.CUSTOM_NAME, Component.literal(name)); + } + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/network/ClientPacketHandler.java b/src/main/java/com/atsuishio/superbwarfare/network/ClientPacketHandler.java index 1eca487eb..704165ccf 100644 --- a/src/main/java/com/atsuishio/superbwarfare/network/ClientPacketHandler.java +++ b/src/main/java/com/atsuishio/superbwarfare/network/ClientPacketHandler.java @@ -1,9 +1,12 @@ package com.atsuishio.superbwarfare.network; +import com.atsuishio.superbwarfare.client.screens.DogTagEditorScreen; import com.atsuishio.superbwarfare.event.ClientEventHandler; +import com.atsuishio.superbwarfare.menu.DogTagEditorMenu; import net.minecraft.client.CameraType; import net.minecraft.client.Minecraft; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; import java.util.Objects; @@ -22,4 +25,14 @@ public class ClientPacketHandler { Minecraft.getInstance().options.setCameraType(Objects.requireNonNullElse(ClientEventHandler.lastCameraType, CameraType.FIRST_PERSON)); } + + public static void handleDogTagEditorMessage(int containerId, ItemStack stack) { + Minecraft mc = Minecraft.getInstance(); + if (mc.player != null && mc.player.containerMenu.containerId == containerId) { + ((DogTagEditorMenu) mc.player.containerMenu).stack = stack; + if (mc.screen instanceof DogTagEditorScreen dogTagEditorScreen) { + dogTagEditorScreen.stack = stack; + } + } + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java b/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java index 3233875f0..714b2e2fd 100644 --- a/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java +++ b/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java @@ -23,6 +23,7 @@ public class NetworkRegistry { registrar.playToClient(RadarMenuCloseMessage.TYPE, RadarMenuCloseMessage.STREAM_CODEC, RadarMenuCloseMessage::handler); registrar.playToClient(SimulationDistanceMessage.TYPE, SimulationDistanceMessage.STREAM_CODEC, SimulationDistanceMessage::handler); registrar.playToClient(ClientTacticalSprintSyncMessage.TYPE, ClientTacticalSprintSyncMessage.STREAM_CODEC, (msg, ctx) -> ClientTacticalSprintSyncMessage.handler(msg)); + registrar.playToClient(DogTagEditorMessage.TYPE, DogTagEditorMessage.STREAM_CODEC, (msg, ctx) -> DogTagEditorMessage.handler(msg)); registrar.playToServer(LaserShootMessage.TYPE, LaserShootMessage.STREAM_CODEC, LaserShootMessage::handler); registrar.playToServer(ShootMessage.TYPE, ShootMessage.STREAM_CODEC, ShootMessage::handler); @@ -55,5 +56,6 @@ public class NetworkRegistry { registrar.playToServer(ChangeVehicleSeatMessage.TYPE, ChangeVehicleSeatMessage.STREAM_CODEC, ChangeVehicleSeatMessage::handler); registrar.playToServer(ShowChargingRangeMessage.TYPE, ShowChargingRangeMessage.STREAM_CODEC, ShowChargingRangeMessage::handler); registrar.playToServer(TacticalSprintMessage.TYPE, TacticalSprintMessage.STREAM_CODEC, TacticalSprintMessage::handler); + registrar.playToServer(DogTagFinishEditMessage.TYPE, DogTagFinishEditMessage.STREAM_CODEC, DogTagFinishEditMessage::handler); } } diff --git a/src/main/java/com/atsuishio/superbwarfare/network/message/receive/DogTagEditorMessage.java b/src/main/java/com/atsuishio/superbwarfare/network/message/receive/DogTagEditorMessage.java new file mode 100644 index 000000000..5c85ee9d3 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/network/message/receive/DogTagEditorMessage.java @@ -0,0 +1,31 @@ +package com.atsuishio.superbwarfare.network.message.receive; + +import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.network.ClientPacketHandler; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +public record DogTagEditorMessage(int containerId, ItemStack stack) implements CustomPacketPayload { + + public static final Type TYPE = new Type<>(Mod.loc("dog_tag_editor")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.INT, DogTagEditorMessage::containerId, + ItemStack.STREAM_CODEC, DogTagEditorMessage::stack, + DogTagEditorMessage::new + ); + + + public static void handler(DogTagEditorMessage message) { + ClientPacketHandler.handleDogTagEditorMessage(message.containerId, message.stack); + } + + @Override + public @NotNull Type type() { + return TYPE; + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/network/message/send/DogTagFinishEditMessage.java b/src/main/java/com/atsuishio/superbwarfare/network/message/send/DogTagFinishEditMessage.java new file mode 100644 index 000000000..4f85c35ab --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/network/message/send/DogTagFinishEditMessage.java @@ -0,0 +1,39 @@ +package com.atsuishio.superbwarfare.network.message.send; + +import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.menu.DogTagEditorMenu; +import io.netty.buffer.ByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.server.level.ServerPlayer; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public record DogTagFinishEditMessage(List colors, String name) implements CustomPacketPayload { + public static final Type TYPE = new Type<>(Mod.loc("dog_tag_finish_edit")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.SHORT.apply(ByteBufCodecs.list()), DogTagFinishEditMessage::colors, + ByteBufCodecs.STRING_UTF8, DogTagFinishEditMessage::name, + DogTagFinishEditMessage::new + ); + + + public static void handler(DogTagFinishEditMessage message, final IPayloadContext context) { + ServerPlayer serverPlayer = (ServerPlayer) context.player(); + + if (serverPlayer.containerMenu instanceof DogTagEditorMenu menu) { + menu.finishEdit(message.colors, message.name); + } + + serverPlayer.closeContainer(); + } + + @Override + public @NotNull Type type() { + return TYPE; + } +} diff --git a/src/main/resources/assets/superbwarfare/lang/en_us.json b/src/main/resources/assets/superbwarfare/lang/en_us.json index 11318e3fc..1b636b269 100644 --- a/src/main/resources/assets/superbwarfare/lang/en_us.json +++ b/src/main/resources/assets/superbwarfare/lang/en_us.json @@ -169,12 +169,10 @@ "item.superbwarfare.wire_guide_missile": "Wire Guide Missile", "des.superbwarfare.wire_guide_missile": "Suitable for BMP-2", "item.superbwarfare.swarm_drone": "Swarm Drone", - "des.superbwarfare.swarm_drone": "Suitable for YX-100 MBT", "item.superbwarfare.medium_aerial_bomb": "Medium Aerial Bomb", "des.superbwarfare.medium_aerial_bomb": "Suitable for A-10 Thunderbolt II", "item.superbwarfare.agm": "Air-to-ground Missile", "des.superbwarfare.agm": "Suitable for A-10 Thunderbolt II", - "item.superbwarfare.beast": "BEAST", "des.superbwarfare.beast": "You are one one one...", "item.superbwarfare.firing_parameters": "Firing Parameters", @@ -256,7 +254,6 @@ "block.superbwarfare.silver_block": "Silver Block", "block.superbwarfare.cemented_carbide_block": "Cemented Carbide Block", "block.superbwarfare.charging_station": "Charging Station", - "des.superbwarfare.charging_station": "Charge nearby entities and adjacent blocks", "des.superbwarfare.charging_station.energy": "Energy: %1$s / %2$s FE", "block.superbwarfare.creative_charging_station": "Creative Charging Station", "des.superbwarfare.creative_charging_station": "Charge nearby entities and adjacent blocks, can also be used as a power source item", @@ -542,8 +539,8 @@ "tips.superbwarfare.shoot.rings": "Rings", "tips.superbwarfare.annihilator.energy_not_enough": "Insufficient Power!", "tips.superbwarfare.target.down": "Target Down %1$s", - "tips.superbwarfare.target.damage": "Damage: %1$s Distance: %2$s", "tips.superbwarfare.dps_generator.dps": "DPS: %1$s", + "tips.superbwarfare.target.damage": "Damage: %1$s Distance: %2$s", "tips.superbwarfare.mortar.range": "Range: ", "tips.superbwarfare.mortar.yaw": "Yaw: ", "tips.superbwarfare.mortar.pitch": "Pitch: ", @@ -595,6 +592,10 @@ "config.superbwarfare.client.display.explosion_screen_shake.des": "The strength of the screen shake caused by explosions", "config.superbwarfare.client.display.shock_screen_shake": "Shock Screen Shake Strength", "config.superbwarfare.client.display.shock_screen_shake.des": "The strength of the screen shake caused by shock effect", + "config.superbwarfare.client.display.dog_tag_name_visible": "Dog Tag Name Visibility", + "config.superbwarfare.client.display.dog_tag_name_visible.des": "Whether to display the name of dog tag in kill messages", + "config.superbwarfare.client.display.dog_tag_icon_visible": "Dog Tag Icon Visibility", + "config.superbwarfare.client.display.dog_tag_icon_visible.des": "Whether to display the icon of dog tag in kill messages", "config.superbwarfare.client.vehicle": "Control Vehicle", "config.superbwarfare.client.vehicle.invert_aircraft_control": "Invert Aircraft Control", "config.superbwarfare.client.vehicle.left_click_reload.des": "Set TRUE to invert aircraft control", diff --git a/src/main/resources/assets/superbwarfare/lang/zh_cn.json b/src/main/resources/assets/superbwarfare/lang/zh_cn.json index ef523e85d..9b13d3bed 100644 --- a/src/main/resources/assets/superbwarfare/lang/zh_cn.json +++ b/src/main/resources/assets/superbwarfare/lang/zh_cn.json @@ -169,12 +169,10 @@ "item.superbwarfare.wire_guide_missile": "线控导弹", "des.superbwarfare.wire_guide_missile": "适配BMP-2步兵战车", "item.superbwarfare.swarm_drone": "蜂群无人机", - "des.superbwarfare.swarm_drone": "适配YX-100主战坦克", "item.superbwarfare.medium_aerial_bomb": "中型航空炸弹", "des.superbwarfare.medium_aerial_bomb": "适配A-10攻击机", "item.superbwarfare.agm": "空对地导弹", "des.superbwarfare.agm": "适配A-10攻击机", - "item.superbwarfare.beast": "BEAST", "des.superbwarfare.beast": "你是一个一个一个......", "item.superbwarfare.firing_parameters": "射击诸元", @@ -256,7 +254,6 @@ "block.superbwarfare.silver_block": "银块", "block.superbwarfare.cemented_carbide_block": "硬质合金块", "block.superbwarfare.charging_station": "充电站", - "des.superbwarfare.charging_station": "充能附近的实体和相邻方块", "des.superbwarfare.charging_station.energy": "能量:%1$s / %2$s FE", "block.superbwarfare.creative_charging_station": "创造模式充电站", "des.superbwarfare.creative_charging_station": "充能附近的实体和相邻方块,也可以作为电源物品使用", @@ -595,6 +592,10 @@ "config.superbwarfare.client.display.explosion_screen_shake.des": "爆炸时,屏幕抖动的强度", "config.superbwarfare.client.display.shock_screen_shake": "电击屏幕抖动", "config.superbwarfare.client.display.shock_screen_shake.des": "受到电击效果时,屏幕抖动的强度", + "config.superbwarfare.client.display.dog_tag_name_visible": "狗牌名称可见性", + "config.superbwarfare.client.display.dog_tag_name_visible.des": "是否在击杀提示中显示狗牌的名称", + "config.superbwarfare.client.display.dog_tag_icon_visible": "狗牌图标可见性", + "config.superbwarfare.client.display.dog_tag_icon_visible.des": "是否在击杀提示中显示狗牌的图标", "config.superbwarfare.client.vehicle": "载具控制", "config.superbwarfare.client.vehicle.invert_aircraft_control": "飞行器鼠标反转", "config.superbwarfare.client.vehicle.left_click_reload.des": "开启飞行器鼠标反转", diff --git a/src/main/resources/assets/superbwarfare/textures/gui/dog_tag_editor.png b/src/main/resources/assets/superbwarfare/textures/gui/dog_tag_editor.png new file mode 100644 index 0000000000000000000000000000000000000000..3a84ae36beb3fc82e6195fa8ce0dd58d8761ec6d GIT binary patch literal 2671 zcmb7_c|6oxAIHxu%#g;o$j(f9+0s~2wlFou@+d}1No3!KxQs1>-=J=}*>Z1nwNPYV znWCq6kE&f!m`2u zfbG^+=0^d5@rN*g7UXxQLkoTQlO%r>l=pN&g29>Y93JHPT`F zCO<8L9yXTd{GQ*wkm}?4oluCCQy2gQ<;@2cb0J}rlYEm5 zjeL?u3JwbLK1&0nP;Ymdw-+wbpXP_Nv_3*P!N5oXfVQ+YKX@$a&$(e8Klu}~s0DqC zwhR?qx4V>Bp%q$iBIME2)jorJb+{7yv7Xa}-?=T4<^5%paBj6fGu_tvib|hlgVCYa|WcJ=2lJmvsk|DxN{X~t>0jU4tY^J-cH5w zg?p~wwbDQm)Z(IIb6=_z)xR5m2L?w*mK`q0L_|iC(0GwwT6fJO2{+e>T#_q68s0hZ ztd#XAX1V+&KIX=a8)NM$a$f|9X#C|4&kAt=4QDwsPHzbf_~Q9B4Tu210Tw_2AOY?N zQ&V47tzy&CQpBUMsZ_C@RJ&}`=X*i<8J41=DScWJD8irs^5}1e_Y2CTSXjH_x}7y_ z60#c*YUdhnXKQ*LTk9u0*>N!BaTe^N+4E<}^5$WYc_4fG@B_J|p24!$7YZ~#F77Cs zjzrzQ?_4tOn^Ey_ngi~#6{4P&dDNziT(NO;_LZU+3tP zIwjW##_c+L(`rK(Jz%sySOUaVf=jPTOm=}hDzCLH#fjs;{z zf;cIltMY^9^y1&;389O9?<#8^JI4G~O^sFzi&}WH^6GLLxH!mn7sTwSrc%c`lth^a z^4GGtMRH0h#DC(#5yGP7Lc+rKe*PMpE0keaeZlpzjo+d zCL(8G=6t?$kQ7;md9vP!qbbYK+gvy%$8h|R%u>q=H^vAi_RcK2s=tw%Qs`N1fDE^^ z`t3()%cdN%mvGmX)-(EF9uAJR6^mp0 zys6rO+m~b~JgJoz{gHj>R}u94fkYOBVD$x!o|x5SkBuEfwzSW((u*(A^GMXGA~jVnikZB+mgf_@VsoUW%i6Ip!Y@PxuCK_&F@kgI^-rrbY&zuD2$tzF>2nFGx=~n3=v6ApYwXG?CkJ zCyKh>?fK@-K)?<6qb5Fdnj1Z!UA4;sSC1e~rU4@u-bDr0tk4w5AN7M?A@m=DO?jSL zv{yod3vzFS(ELcq-LSl-WTGQ7z}OUy^KeAo-$@zbJ}npPoNr41q72y*JLwprDlV_9 z9*kn#_VaQ3Z=rNMnx{}EBwZ?m?&6`-;VDE}#-FMD`n~>L>}v}g2M$?6C*C8Ix~Dev zw!?b8o7KIvQ9$#P!lq}vEeZ>Ft&Be)0}HKH{|m|zlJMKgpdK6s2c4s0{209C`8Yp( zOJi4pL+3ZbIhFi5vQMv2^ZG@EODWnI+e)=42bok^TZ10R{W6g?|0*q(ukib-=E^S zR80a+HQ-aW$WsY#`~{$)%r@3?K_zQ-xppHrhQm`%!nU-(h&LP8+Q8~G#Kw1>MN!t8=q-j=@iF`-LX zxW{cb&aDhmwm)eOj^Wc=IPg-}I{9`>l<(#>_xIbcjWUX!^bZ}XUBK^DNY~`E*J)=e zGFo*~bx_!};bE8Mkf_FL$^jlzKE>jt>u89}gLI!&4#AT?CzL+Jj}z(=3$>?JC8jURX+K=Zw)F<4esW}&Lqb^n0VBWBNH z8<$&@#yiLLn5%_SfA@A`*M*mGnIGM>)k=8Wsc1q@%vAx@=06Izo4h#tn91y)MlR0} zZ_~1a+ZqqdH8wgZ#n)EZ#}M3LFpA{aT=6J5EYNL0OwY=N>4RI;Ve~7>BL^!XP?*ds z8RDHTHUW_l5lMg+_;LT}$2k~UQxnu_#Mvb9$>yx!GeIQ^=Oqi4K+|oz%(%DOE@1}#&*reEH0~h0!)eO5YICPG+19-LkXypP0X^As AlmGw# literal 0 HcmV?d00001 diff --git a/src/main/resources/data/curios/slots/dog_tag.json b/src/main/resources/data/curios/slots/dog_tag.json new file mode 100644 index 000000000..7972cb9e7 --- /dev/null +++ b/src/main/resources/data/curios/slots/dog_tag.json @@ -0,0 +1,5 @@ +{ + "order": 114, + "size": 1, + "icon": "superbwarfare:slot/dog_tag_slot" +} \ No newline at end of file