From 9586526142b387ff444dd8d0ffecfe33039a2fcc Mon Sep 17 00:00:00 2001 From: Light_Quanta Date: Wed, 26 Mar 2025 06:15:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0KeyMapping=EF=BC=8CScreen?= =?UTF-8?q?=E5=92=8C=E5=85=B6=E4=BB=96=E6=9D=82=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/atsuishio/superbwarfare/ModUtils.java | 6 +- .../capability/player/PlayerVariable.java | 1 + .../superbwarfare/client/ModRenderTypes.java | 33 ++ .../entity/AbstractLaserEntityRenderer.java | 162 +++++++++ .../renderer/entity/LaserEntityRenderer.java | 87 +++++ .../client/screens/ChargingStationScreen.java | 116 ++++++ .../client/screens/FuMO25Screen.java | 337 ++++++++++++++++++ .../client/screens/FuMO25ScreenHelper.java | 58 +++ .../client/screens/ReforgingTableScreen.java | 218 +++++++++++ .../client/screens/VehicleScreen.java | 47 +++ .../screens/modsell/ModSellWarningScreen.java | 116 ++++++ .../screens/modsell/TranslationRecord.java | 46 +++ .../superbwarfare/init/ModAttributes.java | 37 ++ .../init/ModEntityRenderers.java | 48 +++ .../superbwarfare/init/ModItems.java | 7 +- .../superbwarfare/init/ModKeyMappings.java | 94 +++++ .../superbwarfare/init/ModScreens.java | 20 ++ .../CreativeChargingStationBlockItem.java | 23 ++ .../network/NetworkRegistry.java | 7 + .../network/message/BreathMessage.java | 29 ++ 20 files changed, 1485 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/ModRenderTypes.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/AbstractLaserEntityRenderer.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/LaserEntityRenderer.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/screens/ChargingStationScreen.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/screens/FuMO25Screen.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/screens/FuMO25ScreenHelper.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/screens/ReforgingTableScreen.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/screens/VehicleScreen.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/screens/modsell/ModSellWarningScreen.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/screens/modsell/TranslationRecord.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/init/ModAttributes.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/init/ModEntityRenderers.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/init/ModKeyMappings.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/init/ModScreens.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/item/CreativeChargingStationBlockItem.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/network/message/BreathMessage.java diff --git a/src/main/java/com/atsuishio/superbwarfare/ModUtils.java b/src/main/java/com/atsuishio/superbwarfare/ModUtils.java index 1cb500437..79b8a9325 100644 --- a/src/main/java/com/atsuishio/superbwarfare/ModUtils.java +++ b/src/main/java/com/atsuishio/superbwarfare/ModUtils.java @@ -41,15 +41,15 @@ public class ModUtils { // ModSerializers.REGISTRY.register(bus); ModSounds.REGISTRY.register(bus); ModBlocks.REGISTRY.register(bus); -// ModBlockEntities.REGISTRY.register(bus); + ModBlockEntities.REGISTRY.register(bus); ModItems.register(bus); ModDataComponents.register(bus); ModTabs.TABS.register(bus); -// ModEntities.REGISTRY.register(bus); + ModEntities.REGISTRY.register(bus); // ModMobEffects.REGISTRY.register(bus); ModParticleTypes.REGISTRY.register(bus); // ModPotion.POTIONS.register(bus); -// ModMenuTypes.REGISTRY.register(bus); + ModMenuTypes.REGISTRY.register(bus); ModVillagers.register(bus); // ModRecipes.RECIPE_SERIALIZERS.register(bus); diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/player/PlayerVariable.java b/src/main/java/com/atsuishio/superbwarfare/capability/player/PlayerVariable.java index 438807469..950b0b3de 100644 --- a/src/main/java/com/atsuishio/superbwarfare/capability/player/PlayerVariable.java +++ b/src/main/java/com/atsuishio/superbwarfare/capability/player/PlayerVariable.java @@ -13,6 +13,7 @@ import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.neoforge.event.entity.player.PlayerEvent; import net.neoforged.neoforge.network.PacketDistributor; +// TODO 在退出世界时正确持久化弹药数量 @EventBusSubscriber(modid = ModUtils.MODID) public class PlayerVariable { public boolean zoom = false; diff --git a/src/main/java/com/atsuishio/superbwarfare/client/ModRenderTypes.java b/src/main/java/com/atsuishio/superbwarfare/client/ModRenderTypes.java new file mode 100644 index 000000000..ca5b8ea29 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/ModRenderTypes.java @@ -0,0 +1,33 @@ +package com.atsuishio.superbwarfare.client; + +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.Util; +import net.minecraft.client.renderer.RenderStateShard; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.resources.ResourceLocation; + +import java.util.function.Function; + +public class ModRenderTypes extends RenderType { + + public ModRenderTypes(String pName, VertexFormat pFormat, VertexFormat.Mode pMode, int pBufferSize, boolean pAffectsCrumbling, boolean pSortOnUpload, Runnable pSetupState, Runnable pClearState) { + super(pName, pFormat, pMode, pBufferSize, pAffectsCrumbling, pSortOnUpload, pSetupState, pClearState); + } + + public static final Function LASER = Util.memoize((location) -> { + TextureStateShard shard = new TextureStateShard(location, false, false); + CompositeState state = CompositeState.builder().setTextureState(shard) + .setShaderState(RENDERTYPE_ENTITY_TRANSLUCENT_EMISSIVE_SHADER).setTransparencyState(ADDITIVE_TRANSPARENCY) + .setCullState(NO_CULL).setOverlayState(OVERLAY).setWriteMaskState(COLOR_WRITE).createCompositeState(false); + return RenderType.create("laser", DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS, 256, true, false, state); + }); + + public static final Function ILLUMINATED = Util.memoize((location) -> { + TextureStateShard shard = new TextureStateShard(location, false, false); + CompositeState state = CompositeState.builder().setTextureState(shard) + .setShaderState(RENDERTYPE_ENTITY_TRANSLUCENT_EMISSIVE_SHADER).setTransparencyState(RenderStateShard.GLINT_TRANSPARENCY) + .setCullState(NO_CULL).setOverlayState(NO_OVERLAY).setWriteMaskState(COLOR_WRITE).createCompositeState(false); + return RenderType.create("illuminated", DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS, 256, true, false, state); + }); +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/AbstractLaserEntityRenderer.java b/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/AbstractLaserEntityRenderer.java new file mode 100644 index 000000000..3a421a8d2 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/AbstractLaserEntityRenderer.java @@ -0,0 +1,162 @@ +package com.atsuishio.superbwarfare.client.renderer.entity; + +import com.atsuishio.superbwarfare.client.ModRenderTypes; +import com.atsuishio.superbwarfare.entity.projectile.AbstractLaserEntity; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Axis; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import org.jetbrains.annotations.NotNull; +import org.joml.Matrix3f; +import org.joml.Matrix4f; +import org.joml.Quaternionf; + +/** + * Code based on @BobMowzie's MowziesMobs and @EEEAB's EEEABsMobs + */ +@OnlyIn(Dist.CLIENT) +public abstract class AbstractLaserEntityRenderer extends EntityRenderer { + + private static final float TEXTURE_WIDTH = 256; + private static final float TEXTURE_HEIGHT = 32; + private final float quadRadius; + private final float beamRadius; + + public AbstractLaserEntityRenderer(EntityRendererProvider.Context context, float quadRadius, float beamRadius) { + super(context); + this.quadRadius = quadRadius; + this.beamRadius = beamRadius; + } + + @Override + public abstract @NotNull ResourceLocation getTextureLocation(@NotNull T entity); + + @Override + public void render(T beam, float entityYaw, float delta, @NotNull PoseStack matrixStackIn, @NotNull MultiBufferSource bufferIn, int packedLightIn) { + double collidePosX = beam.prevCollidePosX + (beam.collidePosX - beam.prevCollidePosX) * delta; + double collidePosY = beam.prevCollidePosY + (beam.collidePosY - beam.prevCollidePosY) * delta; + double collidePosZ = beam.prevCollidePosZ + (beam.collidePosZ - beam.prevCollidePosZ) * delta; + double posX = beam.xo + (beam.getX() - beam.xo) * delta; + double posY = beam.yo + (beam.getY() - beam.yo) * delta; + double posZ = beam.zo + (beam.getZ() - beam.zo) * delta; + float yaw = beam.preYaw + (beam.yaw - beam.preYaw) * delta; + float pitch = beam.prePitch + (beam.pitch - beam.prePitch) * delta; + + float length = (float) Math.sqrt(Math.pow(collidePosX - posX, 2) + Math.pow(collidePosY - posY, 2) + Math.pow(collidePosZ - posZ, 2)); + int frame = Mth.floor((beam.ticker.getTick() - 1 + delta) * 2); + if (frame < 0) { + frame = 6; + } + + if (!beam.isAccumulating()) return; + VertexConsumer vertex$builder = bufferIn.getBuffer(ModRenderTypes.LASER.apply(getTextureLocation(beam))); + renderStart(beam, frame, matrixStackIn, vertex$builder, delta, packedLightIn); + renderBeam(length, 180f / (float) Math.PI * yaw, 180f / (float) Math.PI * pitch, frame, matrixStackIn, vertex$builder, packedLightIn); + matrixStackIn.pushPose(); + matrixStackIn.translate(collidePosX - posX, collidePosY - posY, collidePosZ - posZ); + renderEnd(beam, frame, beam.blockSide, matrixStackIn, vertex$builder, delta, packedLightIn); + matrixStackIn.popPose(); + } + + protected void renderFlatQuad(int frame, PoseStack matrixStackIn, VertexConsumer builder, int packedLightIn, boolean inGround) { + float minU = 0 + 16F / TEXTURE_WIDTH * frame; + float minV = 0; + float maxU = minU + 16F / TEXTURE_WIDTH; + float maxV = minV + 16F / TEXTURE_HEIGHT; + float SIZE = this.quadRadius + (inGround ? 0.2F : 0); + PoseStack.Pose matrix$stack$entry = matrixStackIn.last(); + Matrix4f matrix4f = matrix$stack$entry.pose(); + Matrix3f matrix3f = matrix$stack$entry.normal(); + drawVertex(matrix4f, matrix3f, builder, -SIZE, -SIZE, 0, minU, minV, packedLightIn); + drawVertex(matrix4f, matrix3f, builder, -SIZE, SIZE, 0, minU, maxV, packedLightIn); + drawVertex(matrix4f, matrix3f, builder, SIZE, SIZE, 0, maxU, maxV, packedLightIn); + drawVertex(matrix4f, matrix3f, builder, SIZE, -SIZE, 0, maxU, minV, packedLightIn); + } + + protected void renderStart(T entity, int frame, PoseStack matrixStackIn, VertexConsumer builder, float delta, int packedLightIn) { + matrixStackIn.pushPose(); + Quaternionf quaternionf = this.entityRenderDispatcher.cameraOrientation(); + matrixStackIn.mulPose(quaternionf); + renderFlatQuad(frame, matrixStackIn, builder, packedLightIn, false); + matrixStackIn.popPose(); + } + + protected void renderEnd(T entity, int frame, Direction side, PoseStack matrixStackIn, VertexConsumer builder, float delta, int packedLightIn) { + matrixStackIn.pushPose(); + Quaternionf quaternionf = this.entityRenderDispatcher.cameraOrientation(); + matrixStackIn.mulPose(quaternionf); + renderFlatQuad(frame, matrixStackIn, builder, packedLightIn, false); + matrixStackIn.popPose(); + + if (side == null) { + return; + } + + matrixStackIn.pushPose(); + Quaternionf rotation = side.getRotation(); + rotation.mul(Axis.XP.rotationDegrees(90F)); + matrixStackIn.mulPose(rotation); + matrixStackIn.translate(0, 0, -0.01f); + renderFlatQuad(frame, matrixStackIn, builder, packedLightIn, true); + matrixStackIn.popPose(); + } + + protected void renderBeam(float length, float yaw, float pitch, int frame, PoseStack matrixStackIn, VertexConsumer builder, int packedLightIn) { + matrixStackIn.pushPose(); + + matrixStackIn.mulPose(Axis.XP.rotationDegrees(90F)); + matrixStackIn.mulPose(Axis.ZP.rotationDegrees(yaw - 90F)); + matrixStackIn.mulPose(Axis.XP.rotationDegrees(-pitch)); + + matrixStackIn.pushPose(); + matrixStackIn.mulPose(Axis.YP.rotationDegrees(Minecraft.getInstance().gameRenderer.getMainCamera().getXRot() + 90F)); + drawBeam(length, frame, matrixStackIn, builder, packedLightIn); + matrixStackIn.popPose(); + + matrixStackIn.pushPose(); + matrixStackIn.mulPose(Axis.YP.rotationDegrees(-Minecraft.getInstance().gameRenderer.getMainCamera().getXRot() - 90F)); + drawBeam(length, frame, matrixStackIn, builder, packedLightIn); + matrixStackIn.popPose(); + + matrixStackIn.pushPose(); + matrixStackIn.mulPose(Axis.YP.rotationDegrees(-Minecraft.getInstance().gameRenderer.getMainCamera().getXRot() + 180F)); + drawBeam(length, frame, matrixStackIn, builder, packedLightIn); + matrixStackIn.popPose(); + + matrixStackIn.pushPose(); + matrixStackIn.mulPose(Axis.YP.rotationDegrees(-Minecraft.getInstance().gameRenderer.getMainCamera().getXRot() - 180F)); + drawBeam(length, frame, matrixStackIn, builder, packedLightIn); + matrixStackIn.popPose(); + + matrixStackIn.popPose(); + } + + protected void drawBeam(float length, int frame, PoseStack matrixStackIn, VertexConsumer builder, int packedLightIn) { + float minU = 0; + float minV = 16 / TEXTURE_HEIGHT + 1 / TEXTURE_HEIGHT * frame; + float maxU = minU + 20 / TEXTURE_WIDTH; + float maxV = minV + 1 / TEXTURE_HEIGHT; + PoseStack.Pose matrix$stack$entry = matrixStackIn.last(); + Matrix4f matrix4f = matrix$stack$entry.pose(); + Matrix3f matrix3f = matrix$stack$entry.normal(); + float offset = 0; + float size = this.beamRadius; + drawVertex(matrix4f, matrix3f, builder, -size, offset, 0, minU, minV, packedLightIn); + drawVertex(matrix4f, matrix3f, builder, -size, length, 0, minU, maxV, packedLightIn); + drawVertex(matrix4f, matrix3f, builder, size, length, 0, maxU, maxV, packedLightIn); + drawVertex(matrix4f, matrix3f, builder, size, offset, 0, maxU, minV, packedLightIn); + } + + protected void drawVertex(Matrix4f matrix, Matrix3f normals, VertexConsumer vertexBuilder, float offsetX, float offsetY, float offsetZ, float textureX, float textureY, int packedLightIn) { +// vertexBuilder.addVertex(matrix, offsetX, offsetY, offsetZ).setColor(1F, 1F, 1F, 1F).setUv(textureX, textureY).setOverlay(OverlayTexture.NO_OVERLAY).setLight(packedLightIn).setNormal(normals, 0.0F, 1.0F, 0.0F).endVertex(); + } + +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/LaserEntityRenderer.java b/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/LaserEntityRenderer.java new file mode 100644 index 000000000..31c3399b1 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/LaserEntityRenderer.java @@ -0,0 +1,87 @@ +package com.atsuishio.superbwarfare.client.renderer.entity; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.entity.projectile.LaserEntity; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.CameraType; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import org.jetbrains.annotations.NotNull; +import org.joml.Matrix3f; +import org.joml.Matrix4f; + +/** + * Code based on @BobMowzie's MowziesMobs and @EEEAB's EEEABsMobs + */ +@OnlyIn(Dist.CLIENT) +public class LaserEntityRenderer extends AbstractLaserEntityRenderer { + + private boolean playerView; + + private static final float TEXTURE_WIDTH = 256; + private static final float TEXTURE_HEIGHT = 32; + + public static final ResourceLocation TEXTURE = ModUtils.loc("textures/entity/temp_laser.png"); + + public LaserEntityRenderer(EntityRendererProvider.Context context) { + super(context, 0.8f, 0.6f); + } + + @Override + public @NotNull ResourceLocation getTextureLocation(@NotNull LaserEntity entity) { + return TEXTURE; + } + + @Override + public void render(LaserEntity beam, float entityYaw, float delta, @NotNull PoseStack matrixStackIn, @NotNull MultiBufferSource bufferIn, int packedLightIn) { + this.playerView = beam.caster instanceof Player && Minecraft.getInstance().player == beam.caster + && Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON; +// if (this.playerView) return; + super.render(beam, entityYaw, delta, matrixStackIn, bufferIn, packedLightIn); + } + + @Override + protected void renderFlatQuad(int frame, PoseStack matrixStackIn, VertexConsumer builder, int packedLightIn, boolean inGround) { + float minU = 0 + 16F / TEXTURE_WIDTH * frame; + float minV = 0; + float maxU = minU + 16F / TEXTURE_WIDTH; + float maxV = minV + 16F / TEXTURE_HEIGHT; + float size = 0.25f; + PoseStack.Pose matrix$stack$entry = matrixStackIn.last(); + Matrix4f matrix4f = matrix$stack$entry.pose(); + Matrix3f matrix3f = matrix$stack$entry.normal(); + drawVertex(matrix4f, matrix3f, builder, -size, -size, 0, minU, minV, packedLightIn); + drawVertex(matrix4f, matrix3f, builder, -size, size, 0, minU, maxV, packedLightIn); + drawVertex(matrix4f, matrix3f, builder, size, size, 0, maxU, maxV, packedLightIn); + drawVertex(matrix4f, matrix3f, builder, size, -size, 0, maxU, minV, packedLightIn); + } + + @Override + protected void renderStart(LaserEntity laser, int frame, PoseStack matrixStackIn, VertexConsumer builder, float delta, int packedLightIn) { + if (this.playerView) return; + super.renderStart(laser, frame, matrixStackIn, builder, delta, packedLightIn); + } + + @Override + protected void drawBeam(float length, int frame, PoseStack matrixStackIn, VertexConsumer builder, int packedLightIn) { + float minU = 0; + float minV = 16 / TEXTURE_HEIGHT + 1 / TEXTURE_HEIGHT * frame; + float maxU = minU + 20 / TEXTURE_WIDTH; + float maxV = minV + 1 / TEXTURE_HEIGHT; + PoseStack.Pose matrix$stack$entry = matrixStackIn.last(); + Matrix4f matrix4f = matrix$stack$entry.pose(); + Matrix3f matrix3f = matrix$stack$entry.normal(); + float offset = playerView ? -1 : 0; + float size = 0.2f; + drawVertex(matrix4f, matrix3f, builder, -size, offset, 0, minU, minV, packedLightIn); + drawVertex(matrix4f, matrix3f, builder, -size, length, 0, minU, maxV, packedLightIn); + drawVertex(matrix4f, matrix3f, builder, size, length, 0, maxU, maxV, packedLightIn); + drawVertex(matrix4f, matrix3f, builder, size, offset, 0, maxU, minV, packedLightIn); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/screens/ChargingStationScreen.java b/src/main/java/com/atsuishio/superbwarfare/client/screens/ChargingStationScreen.java new file mode 100644 index 000000000..b10d5b2ee --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/screens/ChargingStationScreen.java @@ -0,0 +1,116 @@ +package com.atsuishio.superbwarfare.client.screens; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.block.entity.ChargingStationBlockEntity; +import com.atsuishio.superbwarfare.menu.ChargingStationMenu; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractButton; +import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@OnlyIn(Dist.CLIENT) +public class ChargingStationScreen extends AbstractContainerScreen { + + private static final ResourceLocation TEXTURE = ModUtils.loc("textures/gui/charging_station.png"); + + public ChargingStationScreen(ChargingStationMenu pMenu, Inventory pPlayerInventory, Component pTitle) { + super(pMenu, pPlayerInventory, pTitle); + imageWidth = 176; + imageHeight = 166; + } + + @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); + + long fuelTick = ChargingStationScreen.this.menu.getFuelTick(); + long maxFuelTick = ChargingStationScreen.this.menu.getMaxFuelTick(); + long energy = ChargingStationScreen.this.menu.getEnergy(); + + if (maxFuelTick == 0) { + maxFuelTick = ChargingStationBlockEntity.DEFAULT_FUEL_TIME; + } + + // Fuel + float fuelRate = (float) fuelTick / (float) maxFuelTick; + pGuiGraphics.blit(TEXTURE, i + 45, j + 51 - (int) (13 * fuelRate), 177, 14 - (int) (13 * fuelRate), 13, (int) (13 * fuelRate)); + + // Energy + float energyRate = (float) energy / (float) ChargingStationBlockEntity.MAX_ENERGY; + pGuiGraphics.blit(TEXTURE, i + 80, j + 70 - (int) (54 * energyRate), + 177, 17, 16, (int) (54 * energyRate)); + } + + @Override + public void render(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + this.renderBackground(pGuiGraphics, pMouseX, pMouseY, pPartialTick); + super.render(pGuiGraphics, pMouseX, pMouseY, pPartialTick); + this.renderTooltip(pGuiGraphics, pMouseX, pMouseY); + } + + @Override + protected void renderTooltip(GuiGraphics pGuiGraphics, int pX, int pY) { + super.renderTooltip(pGuiGraphics, pX, pY); + + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + + List tooltip = new ArrayList<>(); + tooltip.add(Component.translatable("des.superbwarfare.charging_station.energy", ChargingStationScreen.this.menu.getEnergy(), + ChargingStationBlockEntity.MAX_ENERGY)); + + if ((pX - i) >= 80 && (pX - i) <= 96 && (pY - j) >= 16 && (pY - j) <= 70) { + pGuiGraphics.renderTooltip(this.font, tooltip, Optional.empty(), pX, pY); + } + } + + @OnlyIn(Dist.CLIENT) + class ShowRangeButton extends AbstractButton { + + @Override + protected void renderWidget(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + this.setMessage(ChargingStationScreen.this.menu.showRange() ? Component.translatable("container.superbwarfare.charging_station.hide_range") : Component.translatable("container.superbwarfare.charging_station.show_range")); + super.renderWidget(pGuiGraphics, pMouseX, pMouseY, pPartialTick); + } + + public ShowRangeButton(int pX, int pY) { + super(pX + 7, pY + 55, 33, 14, Component.translatable("container.superbwarfare.charging_station.show_range")); + } + + @Override + public void onPress() { + // TODO show range message +// ModUtils.PACKET_HANDLER.sendToServer(new ShowChargingRangeMessage(!ChargingStationScreen.this.menu.showRange())); + } + + @Override + protected void updateWidgetNarration(NarrationElementOutput pNarrationElementOutput) { + + } + } + + @Override + protected void init() { + super.init(); + this.titleLabelX = 8; + this.titleLabelY = 5; + this.inventoryLabelX = 8; + this.inventoryLabelY = 74; + + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + this.addRenderableWidget(new ShowRangeButton(i, j)); + } + +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/screens/FuMO25Screen.java b/src/main/java/com/atsuishio/superbwarfare/client/screens/FuMO25Screen.java new file mode 100644 index 000000000..0cd5e2c94 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/screens/FuMO25Screen.java @@ -0,0 +1,337 @@ +package com.atsuishio.superbwarfare.client.screens; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.block.entity.FuMO25BlockEntity; +import com.atsuishio.superbwarfare.menu.FuMO25Menu; +import com.atsuishio.superbwarfare.tools.FormatTool; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.math.Axis; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractButton; +import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Inventory; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@OnlyIn(Dist.CLIENT) +public class FuMO25Screen extends AbstractContainerScreen { + + private static final ResourceLocation TEXTURE = ModUtils.loc("textures/gui/radar.png"); + private static final ResourceLocation SCAN = ModUtils.loc("textures/gui/radar_scan.png"); + + private BlockPos currentPos = null; + private Entity currentTarget = null; + + public FuMO25Screen(FuMO25Menu pMenu, Inventory pPlayerInventory, Component pTitle) { + super(pMenu, pPlayerInventory, pTitle); + imageWidth = 340; + imageHeight = 166; + } + + @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, 358, 328); + + // 目标位置 + renderTargets(pGuiGraphics); + + // 扫描盘 + renderScan(pGuiGraphics); + + // 网格线 + renderXLine(pGuiGraphics, i, j); + + // FE + long energy = FuMO25Screen.this.menu.getEnergy(); + float energyRate = (float) energy / (float) FuMO25BlockEntity.MAX_ENERGY; + pGuiGraphics.blit(TEXTURE, i + 278, j + 39, 178, 167, (int) (54 * energyRate), 16, 358, 328); + + // 信息显示 + renderInfo(pGuiGraphics); + + RenderSystem.depthMask(true); + RenderSystem.defaultBlendFunc(); + RenderSystem.enableDepthTest(); + RenderSystem.disableBlend(); + RenderSystem.setShaderColor(1, 1, 1, 1); + } + + private void renderXLine(GuiGraphics guiGraphics, int i, int j) { + var poseStack = guiGraphics.pose(); + poseStack.pushPose(); + + RenderSystem.disableDepthTest(); + RenderSystem.depthMask(false); + RenderSystem.enableBlend(); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE); + + guiGraphics.blit(TEXTURE, i + 8, j + 11, 0, 167, 147, 147, 358, 328); + + RenderSystem.disableDepthTest(); + RenderSystem.depthMask(false); + RenderSystem.enableBlend(); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + + poseStack.popPose(); + } + + private void renderTargets(GuiGraphics guiGraphics) { + var entities = FuMO25ScreenHelper.entities; + if (entities == null || entities.isEmpty()) return; + var pos = FuMO25ScreenHelper.pos; + if (pos == null) return; + if (!FuMO25Screen.this.menu.isPowered()) return; + + int type = (int) FuMO25Screen.this.menu.getFuncType(); + int range = type == 1 ? FuMO25BlockEntity.MAX_RANGE : FuMO25BlockEntity.DEFAULT_RANGE; + + var poseStack = guiGraphics.pose(); + poseStack.pushPose(); + + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + + int centerX = i + 81; + int centerY = j + 84; + + for (var entity : entities) { + double moveX = (entity.getX() - pos.getX()) / range * 74; + double moveZ = (entity.getZ() - pos.getZ()) / range * 74; + + // TODO preciseBlit +// RenderHelper.preciseBlit(guiGraphics, TEXTURE, (float) (centerX + moveX), (float) (centerY + moveZ), +// 233, 167, 4, 4, 358, 328); + } + + poseStack.popPose(); + } + + private void renderScan(GuiGraphics guiGraphics) { + if (FuMO25Screen.this.menu.getEnergy() <= 0) return; + if (!FuMO25Screen.this.menu.isPowered()) return; + + var poseStack = guiGraphics.pose(); + poseStack.pushPose(); + + RenderSystem.disableDepthTest(); + RenderSystem.depthMask(false); + RenderSystem.enableBlend(); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + + poseStack.rotateAround(Axis.ZP.rotationDegrees(System.currentTimeMillis() % 36000000 / 30f), i + 9 + 145 / 2f, j + 12 + 145 / 2f, 0); + + guiGraphics.blit(SCAN, i + 9, j + 12, 0, 0, 145, 145, 145, 145); + + poseStack.popPose(); + } + + private void renderInfo(GuiGraphics guiGraphics) { + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + + if (this.currentPos != null) { + guiGraphics.drawString(this.font, Component.translatable("des.superbwarfare.fumo_25.current_pos", + "[" + currentPos.getX() + ", " + currentPos.getY() + ", " + currentPos.getZ() + "]"), i + 173, j + 13, 0xffffff); + } + + if (this.currentTarget != null) { + StringBuilder sb = new StringBuilder(); + sb.append(currentTarget.getDisplayName().getString()); + if (currentTarget instanceof LivingEntity living) { + sb.append(" (HP: ").append(FormatTool.format1D(living.getHealth())) + .append("/").append(FormatTool.format1D(living.getMaxHealth())).append(")"); + } + // TODO vehicle +// else if (currentTarget instanceof VehicleEntity vehicle) { +// sb.append(" (HP: ").append(FormatTool.format1D(vehicle.getHealth())) +// .append("/").append(FormatTool.format1D(vehicle.getMaxHealth())).append(")"); +// } + + guiGraphics.drawString(this.font, Component.translatable("des.superbwarfare.fumo_25.current_target", sb), + i + 173, j + 24, 0xffffff); + } + + int type = (int) FuMO25Screen.this.menu.getFuncType(); + var component = switch (type) { + case 1 -> Component.translatable("des.superbwarfare.fumo_25.type_1"); + case 2 -> Component.translatable("des.superbwarfare.fumo_25.type_2"); + case 3 -> Component.translatable("des.superbwarfare.fumo_25.type_3"); + default -> Component.translatable("des.superbwarfare.fumo_25.type_0"); + }; + if (type != 0) { + component = component.append(Component.literal(" " + FuMO25Screen.this.menu.getTime() / 20 + "s")); + } + guiGraphics.drawString(this.font, component, i + 173, j + 43, 0xffffff); + } + + @Override + public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { + var entities = FuMO25ScreenHelper.entities; + if (entities == null || entities.isEmpty()) return super.mouseClicked(pMouseX, pMouseY, pButton); + var pos = FuMO25ScreenHelper.pos; + if (pos == null) return super.mouseClicked(pMouseX, pMouseY, pButton); + if (pButton != 0) return super.mouseClicked(pMouseX, pMouseY, pButton); + if (!FuMO25Screen.this.menu.isPowered()) return super.mouseClicked(pMouseX, pMouseY, pButton); + + int type = (int) FuMO25Screen.this.menu.getFuncType(); + int range = type == 1 ? FuMO25BlockEntity.MAX_RANGE : FuMO25BlockEntity.DEFAULT_RANGE; + + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + + int centerX = i + 81; + int centerY = j + 84; + + for (var entity : entities) { + double moveX = (entity.getX() - pos.getX()) / range * 74; + double moveZ = (entity.getZ() - pos.getZ()) / range * 74; + + if (pMouseX >= centerX + moveX && pMouseX <= centerX + moveX + 4 && pMouseY >= centerY + moveZ && pMouseY <= centerY + moveZ + 4) { + // TODO network + // ModUtils.PACKET_HANDLER.sendToServer(new RadarSetPosMessage(entity.getOnPos())); + this.currentPos = entity.getOnPos(); + this.currentTarget = entity; + return true; + } + } + + return super.mouseClicked(pMouseX, pMouseY, pButton); + } + + @Override + public void render(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + this.renderBackground(pGuiGraphics, pMouseX, pMouseY, pPartialTick); + pGuiGraphics.pose().pushPose(); + super.render(pGuiGraphics, pMouseX, pMouseY, pPartialTick); + pGuiGraphics.pose().popPose(); + this.renderTooltip(pGuiGraphics, pMouseX, pMouseY); + } + + @Override + protected void renderTooltip(GuiGraphics pGuiGraphics, int pX, int pY) { + super.renderTooltip(pGuiGraphics, pX, pY); + + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + + List tooltip = new ArrayList<>(); + tooltip.add(Component.translatable("des.superbwarfare.charging_station.energy", FuMO25Screen.this.menu.getEnergy(), + FuMO25BlockEntity.MAX_ENERGY)); + + if ((pX - i) >= 278 && (pX - i) <= 332 && (pY - j) >= 39 && (pY - j) <= 55) { + pGuiGraphics.renderTooltip(this.font, tooltip, Optional.empty(), pX, pY); + } + } + + // 本方法留空 + @Override + protected void renderLabels(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY) { + } + + @Override + protected void init() { + super.init(); + this.titleLabelX = 33; + this.titleLabelY = 5; + this.inventoryLabelX = 105; + this.inventoryLabelY = 128; + + this.currentPos = null; + this.currentTarget = null; + + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + + LockButton lockButton = new LockButton(i + 304, j + 61); + this.addRenderableWidget(lockButton); + + ModeButton widerButton = new ModeButton(i + 171, j + 61, 1); + this.addRenderableWidget(widerButton); + + ModeButton glowButton = new ModeButton(i + 201, j + 61, 2); + this.addRenderableWidget(glowButton); + + ModeButton guideButton = new ModeButton(i + 231, j + 61, 3); + this.addRenderableWidget(guideButton); + } + + @OnlyIn(Dist.CLIENT) + class LockButton extends AbstractButton { + + public LockButton(int pX, int pY) { + super(pX, pY, 29, 15, Component.literal("")); + } + + @Override + public void onPress() { + if (FuMO25Screen.this.menu.getFuncType() == 3 && FuMO25Screen.this.menu.getSlot(0).getItem().isEmpty()) { + if (FuMO25Screen.this.currentTarget == null) return; + // TODO network +// ModUtils.PACKET_HANDLER.sendToServer(new RadarSetTargetMessage(FuMO25Screen.this.currentTarget.getUUID())); + } else { +// ModUtils.PACKET_HANDLER.sendToServer(new RadarSetParametersMessage((byte) 0)); + } + } + + @Override + protected void renderWidget(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + if (FuMO25Screen.this.menu.getFuncType() == 3 && FuMO25Screen.this.menu.getSlot(0).getItem().isEmpty()) { + pGuiGraphics.blit(TEXTURE, this.getX(), this.getY(), 148, this.isHovered() ? 311 : 295, 29, 15, 358, 328); + } else { + pGuiGraphics.blit(TEXTURE, this.getX(), this.getY(), 148, this.isHovered() ? 183 : 167, 29, 15, 358, 328); + } + } + + @Override + protected void updateWidgetNarration(NarrationElementOutput pNarrationElementOutput) { + } + } + + @OnlyIn(Dist.CLIENT) + static class ModeButton extends AbstractButton { + + private final int mode; + + public ModeButton(int pX, int pY, int mode) { + super(pX, pY, 29, 15, Component.literal("")); + this.mode = mode; + } + + @Override + public void onPress() { + // TODO network +// ModUtils.PACKET_HANDLER.sendToServer(new RadarChangeModeMessage((byte) this.mode)); + } + + @Override + protected void renderWidget(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + pGuiGraphics.blit(TEXTURE, this.getX(), this.getY(), 148, this.isHovered() ? 183 + this.mode * 32 : 167 + this.mode * 32, + 29, 15, 358, 328); + } + + @Override + protected void updateWidgetNarration(@NotNull NarrationElementOutput pNarrationElementOutput) { + } + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/screens/FuMO25ScreenHelper.java b/src/main/java/com/atsuishio/superbwarfare/client/screens/FuMO25ScreenHelper.java new file mode 100644 index 000000000..66b67bf22 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/screens/FuMO25ScreenHelper.java @@ -0,0 +1,58 @@ +package com.atsuishio.superbwarfare.client.screens; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.block.entity.FuMO25BlockEntity; +import com.atsuishio.superbwarfare.menu.FuMO25Menu; +import com.atsuishio.superbwarfare.tools.SeekTool; +import net.minecraft.client.Camera; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.ClientTickEvent; + +import java.util.List; + +@EventBusSubscriber(modid = ModUtils.MODID, bus = EventBusSubscriber.Bus.GAME, value = Dist.CLIENT) +public class FuMO25ScreenHelper { + + public static BlockPos pos = null; + public static List entities = null; + + public static final int TOLERANCE_DISTANCE = 16; + + @SubscribeEvent + public static void onClientTick(ClientTickEvent.Post event) { + Minecraft mc = Minecraft.getInstance(); + LocalPlayer player = mc.player; + Camera camera = mc.gameRenderer.getMainCamera(); + Vec3 cameraPos = camera.getPosition(); + + if (player == null) return; + var menu = player.containerMenu; + if (!(menu instanceof FuMO25Menu fuMO25Menu)) return; + if (pos == null) return; + + if (pos.distToCenterSqr(cameraPos) > TOLERANCE_DISTANCE * TOLERANCE_DISTANCE) { + pos = BlockPos.containing(cameraPos); + } + + if (fuMO25Menu.getEnergy() <= 0) { + resetEntities(); + return; + } + + var funcType = fuMO25Menu.getFuncType(); + entities = SeekTool.getEntitiesWithinRange(pos, player.level(), funcType == 1 ? FuMO25BlockEntity.MAX_RANGE : FuMO25BlockEntity.DEFAULT_RANGE); + } + + public static void resetEntities() { + if (entities != null) { + entities = null; + } + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/screens/ReforgingTableScreen.java b/src/main/java/com/atsuishio/superbwarfare/client/screens/ReforgingTableScreen.java new file mode 100644 index 000000000..7b72e07fa --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/screens/ReforgingTableScreen.java @@ -0,0 +1,218 @@ +package com.atsuishio.superbwarfare.client.screens; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.menu.ReforgingTableMenu; +import com.atsuishio.superbwarfare.perk.Perk; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractButton; +import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +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; + +@OnlyIn(Dist.CLIENT) +public class ReforgingTableScreen extends AbstractContainerScreen { + + private static final ResourceLocation TEXTURE = ModUtils.loc("textures/gui/reforging_table.png"); + + public ReforgingTableScreen(ReforgingTableMenu pMenu, Inventory pPlayerInventory, Component pTitle) { + super(pMenu, pPlayerInventory, pTitle); + imageWidth = 176; + imageHeight = 177; + } + + @Override + protected void renderBg(GuiGraphics guiGraphics, float partialTicks, int gx, int gy) { + RenderSystem.setShaderColor(1, 1, 1, 1); + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + guiGraphics.blit(TEXTURE, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight, 200, 200); + RenderSystem.disableBlend(); + } + + @Override + public void render(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + this.renderBackground(pGuiGraphics, pMouseX, pMouseY, pPartialTick); + super.render(pGuiGraphics, pMouseX, pMouseY, pPartialTick); + + var ammoPerkLevel = ReforgingTableScreen.this.menu.ammoPerkLevel.get(); + var funcPerkLevel = ReforgingTableScreen.this.menu.funcPerkLevel.get(); + var damagePerkLevel = ReforgingTableScreen.this.menu.damagePerkLevel.get(); + + if (ammoPerkLevel > 0) { + renderNumber(pGuiGraphics, this.leftPos + 136, this.topPos + 31, 1, 178, ammoPerkLevel); + } + + if (funcPerkLevel > 0) { + renderNumber(pGuiGraphics, this.leftPos + 146, this.topPos + 31, 1, 184, funcPerkLevel); + } + + if (damagePerkLevel > 0) { + renderNumber(pGuiGraphics, this.leftPos + 156, this.topPos + 31, 1, 190, damagePerkLevel); + } + + var upgradePoint = ReforgingTableScreen.this.menu.upgradePoint.get(); + renderNumber(pGuiGraphics, this.leftPos + 43, this.topPos + 20, 51, 178, upgradePoint); + + this.renderTooltip(pGuiGraphics, pMouseX, pMouseY); + } + + private void renderNumber(GuiGraphics guiGraphics, int x, int y, int u, int v, int number) { + int g = number / 10; + int s = number % 10; + guiGraphics.blit(TEXTURE, x, y, u + 5 * g, v, 5, 5, 200, 200); + guiGraphics.blit(TEXTURE, x + 4, y, u + 5 * s, v, 5, 5, 200, 200); + } + + @Override + protected void init() { + super.init(); + this.titleLabelX = 8; + this.titleLabelY = 2; + this.inventoryLabelX = 8; + this.inventoryLabelY = 85; + + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + + ReforgeButton button = new ReforgeButton(i + 124, j + 70); + UpgradeButton ammoUpgrade = new UpgradeButton(i + 98, j + 21, Perk.Type.AMMO); + DowngradeButton ammoDowngrade = new DowngradeButton(i + 69, j + 21, Perk.Type.AMMO); + UpgradeButton funcUpgrade = new UpgradeButton(i + 98, j + 41, Perk.Type.FUNCTIONAL); + DowngradeButton funcDowngrade = new DowngradeButton(i + 69, j + 41, Perk.Type.FUNCTIONAL); + UpgradeButton damageUpgrade = new UpgradeButton(i + 98, j + 61, Perk.Type.DAMAGE); + DowngradeButton damageDowngrade = new DowngradeButton(i + 69, j + 61, Perk.Type.DAMAGE); + + this.addRenderableWidget(button); + this.addRenderableWidget(ammoUpgrade); + this.addRenderableWidget(ammoDowngrade); + this.addRenderableWidget(funcUpgrade); + this.addRenderableWidget(funcDowngrade); + this.addRenderableWidget(damageUpgrade); + this.addRenderableWidget(damageDowngrade); + } + + @OnlyIn(Dist.CLIENT) + static class ReforgeButton extends AbstractButton { + + @Override + protected void renderWidget(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + pGuiGraphics.blit(TEXTURE, this.getX(), this.getY(), this.isHovered() ? 81 : 51, 184, 29, 15, 200, 200); + } + + public ReforgeButton(int pX, int pY) { + super(pX, pY, 40, 16, Component.literal("")); + } + + + @Override + public void onPress() { + // TODO network +// ModUtils.PACKET_HANDLER.sendToServer(new GunReforgeMessage(0)); + } + + @Override + protected void updateWidgetNarration(NarrationElementOutput pNarrationElementOutput) { + + } + } + + @OnlyIn(Dist.CLIENT) + class UpgradeButton extends AbstractButton { + public Perk.Type type; + + public UpgradeButton(int pX, int pY, Perk.Type type) { + super(pX, pY, 9, 9, Component.literal("")); + this.type = type; + } + + @Override + protected void renderWidget(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + pGuiGraphics.blit(TEXTURE, this.getX(), this.getY(), 187, this.isHovered() ? 10 : 0, 9, 9, 200, 200); + } + + @Override + public void onPress() { + if (ReforgingTableScreen.this.menu.getPerkItemBySlot(type) == ItemStack.EMPTY) { + return; + } + switch (type) { + case AMMO -> { + if (ReforgingTableScreen.this.menu.ammoPerkLevel.get() >= ReforgingTableMenu.MAX_PERK_LEVEL) { + return; + } + } + case FUNCTIONAL -> { + if (ReforgingTableScreen.this.menu.funcPerkLevel.get() >= ReforgingTableMenu.MAX_PERK_LEVEL) { + return; + } + } + case DAMAGE -> { + if (ReforgingTableScreen.this.menu.damagePerkLevel.get() >= ReforgingTableMenu.MAX_PERK_LEVEL) { + return; + } + } + } + + // TODO network +// ModUtils.PACKET_HANDLER.sendToServer(new SetPerkLevelMessage(type.ordinal(), true)); + } + + @Override + protected void updateWidgetNarration(NarrationElementOutput pNarrationElementOutput) { + + } + } + + @OnlyIn(Dist.CLIENT) + class DowngradeButton extends AbstractButton { + public Perk.Type type; + + @Override + protected void renderWidget(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + pGuiGraphics.blit(TEXTURE, this.getX(), this.getY(), 177, this.isHovered() ? 10 : 0, 9, 9, 200, 200); + } + + public DowngradeButton(int pX, int pY, Perk.Type type) { + super(pX, pY, 12, 12, Component.literal("")); + this.type = type; + } + + @Override + public void onPress() { + if (ReforgingTableScreen.this.menu.getPerkItemBySlot(type) == ItemStack.EMPTY) { + return; + } + switch (type) { + case AMMO -> { + if (ReforgingTableScreen.this.menu.ammoPerkLevel.get() <= 1) { + return; + } + } + case FUNCTIONAL -> { + if (ReforgingTableScreen.this.menu.funcPerkLevel.get() <= 1) { + return; + } + } + case DAMAGE -> { + if (ReforgingTableScreen.this.menu.damagePerkLevel.get() <= 1) { + return; + } + } + } + + // TODO network +// ModUtils.PACKET_HANDLER.sendToServer(new SetPerkLevelMessage(type.ordinal(), false)); + } + + @Override + protected void updateWidgetNarration(NarrationElementOutput pNarrationElementOutput) { + + } + } +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/client/screens/VehicleScreen.java b/src/main/java/com/atsuishio/superbwarfare/client/screens/VehicleScreen.java new file mode 100644 index 000000000..2d344f5c2 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/screens/VehicleScreen.java @@ -0,0 +1,47 @@ +package com.atsuishio.superbwarfare.client.screens; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.menu.VehicleMenu; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import org.jetbrains.annotations.NotNull; + +@OnlyIn(Dist.CLIENT) +public class VehicleScreen extends AbstractContainerScreen { + + private static final ResourceLocation TEXTURE = ModUtils.loc("textures/gui/vehicle.png"); + + public VehicleScreen(VehicleMenu pMenu, Inventory pPlayerInventory, Component pTitle) { + super(pMenu, pPlayerInventory, pTitle); + imageWidth = 345; + imageHeight = 222; + } + + @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, 358, 328); + } + + @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.renderTooltip(pGuiGraphics, pMouseX, pMouseY); + } + + @Override + protected void init() { + super.init(); + this.titleLabelX = 33; + this.titleLabelY = 5; + this.inventoryLabelX = 105; + this.inventoryLabelY = 128; + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/screens/modsell/ModSellWarningScreen.java b/src/main/java/com/atsuishio/superbwarfare/client/screens/modsell/ModSellWarningScreen.java new file mode 100644 index 000000000..51689d3a6 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/screens/modsell/ModSellWarningScreen.java @@ -0,0 +1,116 @@ +package com.atsuishio.superbwarfare.client.screens.modsell; + +import com.atsuishio.superbwarfare.config.client.EnvironmentChecksumConfig; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.AbstractButton; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.layouts.Layout; +import net.minecraft.client.gui.layouts.LinearLayout; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen; +import net.minecraft.client.gui.screens.multiplayer.WarningScreen; +import net.minecraft.network.chat.CommonComponents; +import net.minecraft.network.chat.Component; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import net.neoforged.bus.api.EventPriority; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.ScreenEvent; +import org.jetbrains.annotations.NotNull; + +import java.net.InetAddress; +import java.security.MessageDigest; +import java.util.HexFormat; +import java.util.List; + +@OnlyIn(Dist.CLIENT) +@EventBusSubscriber(value = Dist.CLIENT) +public class ModSellWarningScreen extends WarningScreen { + + private static final String ENVIRONMENT_CHECKSUM = generateEnvironmentHash(); + + private static String getHostName() { + try { + return InetAddress.getLocalHost().getHostName(); + } catch (Exception e) { + System.err.println(e.getMessage()); + return "error"; + } + } + + private static String generateEnvironmentHash() { + var environmentInfo = List.of( + System.getProperty("os.name"), // 操作系统名称 + System.getProperty("os.arch"), // 操作系统架构 + System.getProperty("java.vm.version"), // JVM详细版本号 + System.getProperty("java.home"), // JVM路径 + System.getProperty("user.name"), // 系统用户名称 + getHostName(), // 主机名称 + "stupidNoPayWarningChecksum" // 神秘的盐 + ); + + return sha256(String.join("|", environmentInfo)); + } + + private static String sha256(String input) { + try { + var digest = MessageDigest.getInstance("SHA-256"); + var hash = digest.digest(input.getBytes()); + return HexFormat.of().formatHex(hash); + } catch (Exception e) { + System.err.println(e.getMessage()); + return ""; + } + } + + private final Screen lastScreen; + + public ModSellWarningScreen(Screen lastScreen) { + super( + Component.literal(TranslationRecord.get(TranslationRecord.TITLE)).withStyle(ChatFormatting.BOLD), + Component.literal(TranslationRecord.get(TranslationRecord.CONTENT)), + Component.literal(TranslationRecord.get(TranslationRecord.CHECK)), + Component.literal(TranslationRecord.get(TranslationRecord.TITLE)).withStyle(ChatFormatting.BOLD).append("\n").append(Component.literal(TranslationRecord.get(TranslationRecord.CONTENT))) + ); + this.lastScreen = lastScreen; + } + + private AbstractButton createProceedButton(int pYOffset) { + return Button.builder(CommonComponents.GUI_PROCEED, button -> { + if (this.stopShowing != null && this.stopShowing.selected()) { + EnvironmentChecksumConfig.ENVIRONMENT_CHECKSUM.set(ENVIRONMENT_CHECKSUM); + EnvironmentChecksumConfig.ENVIRONMENT_CHECKSUM.save(); + } + Minecraft.getInstance().setScreen(new JoinMultiplayerScreen(this.lastScreen)); + }).bounds(this.width / 2 - 155, 100 + pYOffset, 150, 20).build(); + } + + @SubscribeEvent(priority = EventPriority.HIGH) + public static void onGuiOpen(ScreenEvent.Opening event) { + if (!(event.getNewScreen() instanceof JoinMultiplayerScreen && !(event.getCurrentScreen() instanceof ModSellWarningScreen))) + return; + + if (EnvironmentChecksumConfig.ENVIRONMENT_CHECKSUM.get().equals(ENVIRONMENT_CHECKSUM)) return; + + // 拦截多人游戏界面加载 + event.setCanceled(true); + Minecraft.getInstance().setScreen(new ModSellWarningScreen(event.getCurrentScreen())); + } + + @Override + protected @NotNull Layout addFooterButtons() { + LinearLayout linearlayout = LinearLayout.horizontal().spacing(8); + linearlayout.addChild(Button.builder(CommonComponents.GUI_PROCEED, p_280872_ -> { + if (this.stopShowing != null && this.stopShowing.selected()) { + EnvironmentChecksumConfig.ENVIRONMENT_CHECKSUM.set(ENVIRONMENT_CHECKSUM); + EnvironmentChecksumConfig.ENVIRONMENT_CHECKSUM.save(); + } + + Minecraft.getInstance().setScreen(new JoinMultiplayerScreen(this.lastScreen)); + }).build()); + linearlayout.addChild(Button.builder(CommonComponents.GUI_BACK, p_329731_ -> this.onClose()).build()); + return linearlayout; + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/screens/modsell/TranslationRecord.java b/src/main/java/com/atsuishio/superbwarfare/client/screens/modsell/TranslationRecord.java new file mode 100644 index 000000000..75d4fecf2 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/screens/modsell/TranslationRecord.java @@ -0,0 +1,46 @@ +package com.atsuishio.superbwarfare.client.screens.modsell; + +import net.minecraft.client.Minecraft; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.util.HexFormat; +import java.util.Map; + +public class TranslationRecord { + + private static final String KEY = "26342ea7c1f2d105678e702dd95f3285c5e1e4ff18814f5f74946e4f02cfdc78"; + public static final Map CONTENT = Map.ofEntries( + Map.entry("zh_cn", "f07591350fc89b0ff0f7ddc537fefec2f62cbc5e80ea77467b09899754cd54067dea26eef69388d0eef680add46073380891915bbb53ac6902c8566d1ea6679652849a70b6e003e2d4c97efd714b4919bee266a8813aca3d9741dbbc0186a41d420aa3f5d0960ab3c01767f0d79eb06b58d019a3e6cdb94f07f5106c16da8ea19c4327448ac68b446ffeaae9dbd8be844d5858792b7ef2c2686205bde67726df54d05ba4d08481cd997e4d7bf001b2034f4748b5c05637d400bbd1797df3d7c13c45763868bc0261309d701fbd4d8dabe0fd5336d13cbc727bd2ba27fe958df77c9e0deb19f870561a27bce013645b1a825d05f2530680ace33b020cd3f3e7772a70758bfdd2fbdf88351c3e9db6a1dd9a4679ad402dea8bdd0566c4d9fe0a11"), + Map.entry("en_us", "bdff19c5a3d29d85fecfe240f801c08ff6f9259aca7a8700ef6a03801a48b21b83420177692c88cc280378a755d3d44dc21ac1a757f96a5a4bc281a3c75e9fcb64f64196d59e81f04815e3b4ff83e3ac0c8dfbbb28c6731f9c468018e5e3e9460ad7e5bd1fd2edfbaa12ea22e53d1ea41733c933af7a5af79a670d5927eb4e9a37c0a9302b998aecbd9988209ce63882f4f4f0834d1e9abcc67ca99735261ef810df421d3b87b7a361b36c7771c15e64d17c7ca748061f283723b0f13230f6c3e1f6542507f4808350c2a36ff2822449d06f42bf6a8cbd29629e3e4b026a70fc") + ); + public static final Map TITLE = Map.ofEntries( + Map.entry("zh_cn", "f47aedcdf60b4ca63eed627b93e3d8d873638f82479c7ca3846b3f1939ad7e2f"), + Map.entry("en_us", "5630e4b7145bd2c4b748077389bb1bf041b0a2c6b5147af89917f50af2ac3041") + ); + + public static final Map CHECK = Map.ofEntries( + Map.entry("zh_cn", "f1eb77633be9e73e04e6f3452d3869fa2b849438b1e0bf738d61452c182c5e26c9d86d259e20a88505ad262d9daf8c1d"), + Map.entry("en_us", "543f8d6c4c8ba78365cf0fde9f4fe52f18800ac0ad501e743372134884e3bc9f9f6b451d0376b3997d5c2159e6831d3a83d6b3ce6b4d5749cba96b894d2a4d275a882e9ef1e9f912c35ee3288814f9af") + ); + + public static String get(Map map) { + try { + var selectedLanguage = Minecraft.getInstance().getLanguageManager().getSelected(); + + var encryptedContent = map.get(selectedLanguage); + if (encryptedContent == null) { + encryptedContent = map.get("en_us"); + } + + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(HexFormat.of().parseHex(KEY), "AES")); + byte[] encrypted = cipher.doFinal(HexFormat.of().parseHex(encryptedContent)); + return new String(encrypted, StandardCharsets.UTF_8); + } catch (Exception e) { + System.err.println(e.getMessage()); + throw new IllegalStateException("SuperbWarfare warning screen translation broken, exiting"); + } + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModAttributes.java b/src/main/java/com/atsuishio/superbwarfare/init/ModAttributes.java new file mode 100644 index 000000000..b43bf340e --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModAttributes.java @@ -0,0 +1,37 @@ +package com.atsuishio.superbwarfare.init; + +import com.atsuishio.superbwarfare.ModUtils; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.RangedAttribute; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.fml.event.lifecycle.FMLConstructModEvent; +import net.neoforged.neoforge.event.entity.EntityAttributeModificationEvent; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; + +@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD) +public class ModAttributes { + public static final DeferredRegister ATTRIBUTES = DeferredRegister.create(BuiltInRegistries.ATTRIBUTE, ModUtils.MODID); + + public static final DeferredHolder BULLET_RESISTANCE = ATTRIBUTES.register("bullet_resistance", () -> (new RangedAttribute("attribute." + ModUtils.MODID + ".bullet_resistance", 0, 0, 1)).setSyncable(true)); + + @SubscribeEvent + public static void register(FMLConstructModEvent event) { + // TODO register +// event.enqueueWork(() -> ATTRIBUTES.register(FMLJavaModLoadingContext.get().getModEventBus())); + } + + @SubscribeEvent + public static void addAttributes(EntityAttributeModificationEvent event) { +// List> entityTypes = event.getTypes(); +// entityTypes.forEach((e) -> { +// Class baseClass = e.getBaseClass(); +// if (baseClass.isAssignableFrom(LivingEntity.class)) { +// event.add(e, BULLET_RESISTANCE); +// } +// }); + + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModEntityRenderers.java b/src/main/java/com/atsuishio/superbwarfare/init/ModEntityRenderers.java new file mode 100644 index 000000000..8aa6a3b52 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModEntityRenderers.java @@ -0,0 +1,48 @@ +package com.atsuishio.superbwarfare.init; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.client.renderer.entity.LaserEntityRenderer; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.EntityRenderersEvent; + +@EventBusSubscriber(modid = ModUtils.MODID, bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +public class ModEntityRenderers { + + @SubscribeEvent + public static void registerEntityRenderers(EntityRenderersEvent.RegisterRenderers event) { +// event.registerEntityRenderer(ModEntities.MORTAR.get(), MortarRenderer::new); +// event.registerEntityRenderer(ModEntities.SENPAI.get(), SenpaiRenderer::new); +// event.registerEntityRenderer(ModEntities.CLAYMORE.get(), ClaymoreRenderer::new); +// event.registerEntityRenderer(ModEntities.C_4.get(), C4Renderer::new); +// event.registerEntityRenderer(ModEntities.TASER_BULLET.get(), TaserBulletProjectileRenderer::new); +// event.registerEntityRenderer(ModEntities.GUN_GRENADE.get(), GunGrenadeRenderer::new); +// event.registerEntityRenderer(ModEntities.TARGET.get(), TargetRenderer::new); +// event.registerEntityRenderer(ModEntities.RPG_ROCKET.get(), RpgRocketRenderer::new); +// event.registerEntityRenderer(ModEntities.HELI_ROCKET.get(), HeliRocketRenderer::new); +// event.registerEntityRenderer(ModEntities.MORTAR_SHELL.get(), MortarShellRenderer::new); +// event.registerEntityRenderer(ModEntities.CANNON_SHELL.get(), CannonShellRenderer::new); +// event.registerEntityRenderer(ModEntities.PROJECTILE.get(), ProjectileEntityRenderer::new); +// event.registerEntityRenderer(ModEntities.MK_42.get(), Mk42Renderer::new); +// event.registerEntityRenderer(ModEntities.DRONE.get(), DroneRenderer::new); +// event.registerEntityRenderer(ModEntities.HAND_GRENADE.get(), HandGrenadeRenderer::new); +// event.registerEntityRenderer(ModEntities.RGO_GRENADE.get(), RgoGrenadeRenderer::new); +// event.registerEntityRenderer(ModEntities.MLE_1934.get(), Mle1934Renderer::new); +// event.registerEntityRenderer(ModEntities.JAVELIN_MISSILE.get(), JavelinMissileRenderer::new); + event.registerEntityRenderer(ModEntities.LASER.get(), LaserEntityRenderer::new); +// event.registerEntityRenderer(ModEntities.ANNIHILATOR.get(), AnnihilatorRenderer::new); +// event.registerEntityRenderer(ModEntities.SPEEDBOAT.get(), SpeedboatRenderer::new); +// event.registerEntityRenderer(ModEntities.WHEEL_CHAIR.get(), WheelChairRenderer::new); +// event.registerEntityRenderer(ModEntities.AH_6.get(), Ah6Renderer::new); +// event.registerEntityRenderer(ModEntities.FLARE_DECOY.get(), FlareDecoyEntityRenderer::new); +// event.registerEntityRenderer(ModEntities.LAV_150.get(), Lav150Renderer::new); +// event.registerEntityRenderer(ModEntities.SMALL_CANNON_SHELL.get(), SmallCannonShellRenderer::new); +// event.registerEntityRenderer(ModEntities.TOM_6.get(), Tom6Renderer::new); +// event.registerEntityRenderer(ModEntities.MELON_BOMB.get(), MelonBombEntityRenderer::new); +// event.registerEntityRenderer(ModEntities.BMP_2.get(), Bmp2Renderer::new); +// event.registerEntityRenderer(ModEntities.WG_MISSILE.get(), WgMissileRenderer::new); +// event.registerEntityRenderer(ModEntities.LASER_TOWER.get(), LaserTowerRenderer::new); +// event.registerEntityRenderer(ModEntities.YX_100.get(), Yx100Renderer::new); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java b/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java index 561ab1f35..144c3fa49 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java @@ -84,7 +84,7 @@ public class ModItems { public static final DeferredHolder MORTAR_SHELL = AMMO.register("mortar_shell", MortarShell::new); public static final DeferredHolder POTION_MORTAR_SHELL = AMMO.register("potion_mortar_shell", PotionMortarShell::new); public static final DeferredHolder ROCKET = AMMO.register("rocket", Rocket::new); -// public static final DeferredHolder LUNGE_MINE = AMMO.register("lunge_mine", LungeMine::new); + // public static final DeferredHolder LUNGE_MINE = AMMO.register("lunge_mine", LungeMine::new); public static final DeferredHolder HE_5_INCHES = AMMO.register("he_5_inches", () -> new CannonShellItem(new Item.Properties().rarity(Rarity.RARE))); public static final DeferredHolder AP_5_INCHES = AMMO.register("ap_5_inches", () -> new CannonShellItem(new Item.Properties().rarity(Rarity.RARE))); // public static final DeferredHolder HAND_GRENADE = AMMO.register("hand_grenade", HandGrenade::new); @@ -244,9 +244,8 @@ public class ModItems { public static final DeferredHolder BARBED_WIRE = block(ModBlocks.BARBED_WIRE); public static final DeferredHolder DRAGON_TEETH = block(ModBlocks.DRAGON_TEETH); public static final DeferredHolder REFORGING_TABLE = block(ModBlocks.REFORGING_TABLE); - // public static final DeferredHolder CHARGING_STATION = block(ModBlocks.CHARGING_STATION); -// public static final DeferredHolder CREATIVE_CHARGING_STATION = BLOCKS.register("creative_charging_station", -// () -> new CreativeChargingStationBlockItem(ModBlocks.CREATIVE_CHARGING_STATION.get(), new Item.Properties().rarity(Rarity.EPIC))); + public static final DeferredHolder CHARGING_STATION = block(ModBlocks.CHARGING_STATION); + public static final DeferredHolder CREATIVE_CHARGING_STATION = BLOCKS.register("creative_charging_station", CreativeChargingStationBlockItem::new); public static final DeferredHolder LEAD_BLOCK = block(ModBlocks.LEAD_BLOCK); public static final DeferredHolder STEEL_BLOCK = block(ModBlocks.STEEL_BLOCK); public static final DeferredHolder TUNGSTEN_BLOCK = block(ModBlocks.TUNGSTEN_BLOCK); diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModKeyMappings.java b/src/main/java/com/atsuishio/superbwarfare/init/ModKeyMappings.java new file mode 100644 index 000000000..f20a918b5 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModKeyMappings.java @@ -0,0 +1,94 @@ +package com.atsuishio.superbwarfare.init; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.network.message.BreathMessage; +import com.mojang.blaze3d.platform.InputConstants; +import net.minecraft.client.KeyMapping; +import net.minecraft.client.Minecraft; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.ClientTickEvent; +import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent; +import net.neoforged.neoforge.client.settings.KeyConflictContext; +import net.neoforged.neoforge.client.settings.KeyModifier; +import net.neoforged.neoforge.network.PacketDistributor; +import org.lwjgl.glfw.GLFW; + +@EventBusSubscriber(modid = ModUtils.MODID, bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +public class ModKeyMappings { + + public static final KeyMapping RELOAD = new KeyMapping("key.superbwarfare.reload", GLFW.GLFW_KEY_R, "key.categories.superbwarfare"); + public static final KeyMapping FIRE_MODE = new KeyMapping("key.superbwarfare.fire_mode", GLFW.GLFW_KEY_N, "key.categories.superbwarfare"); + public static final KeyMapping SENSITIVITY_INCREASE = new KeyMapping("key.superbwarfare.sensitivity_increase", GLFW.GLFW_KEY_PAGE_UP, "key.categories.superbwarfare"); + public static final KeyMapping SENSITIVITY_REDUCE = new KeyMapping("key.superbwarfare.sensitivity_reduce", GLFW.GLFW_KEY_PAGE_DOWN, "key.categories.superbwarfare"); + public static final KeyMapping INTERACT = new KeyMapping("key.superbwarfare.interact", GLFW.GLFW_KEY_X, "key.categories.superbwarfare"); + public static final KeyMapping DISMOUNT = new KeyMapping("key.superbwarfare.dismount", GLFW.GLFW_KEY_LEFT_ALT, "key.categories.superbwarfare"); + + public static final KeyMapping BREATH = new KeyMapping("key.superbwarfare.breath", GLFW.GLFW_KEY_LEFT_CONTROL, "key.categories.superbwarfare") { + private boolean isDownOld = false; + + @Override + public void setDown(boolean isDown) { + super.setDown(isDown); + if (isDownOld != isDown && isDown) { + PacketDistributor.sendToServer(new BreathMessage(true)); + } else if (isDownOld != isDown) { + PacketDistributor.sendToServer(new BreathMessage(false)); + } + isDownOld = isDown; + } + }; + + public static final KeyMapping CONFIG = new KeyMapping("key.superbwarfare.config", KeyConflictContext.IN_GAME, + KeyModifier.ALT, InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_O, "key.categories.superbwarfare"); + + public static final KeyMapping EDIT_MODE = new KeyMapping("key.superbwarfare.edit_mode", GLFW.GLFW_KEY_H, "key.categories.superbwarfare"); + public static final KeyMapping EDIT_SCOPE = new KeyMapping("key.superbwarfare.edit_scope", GLFW.GLFW_KEY_UP, "key.categories.superbwarfare"); + public static final KeyMapping EDIT_BARREL = new KeyMapping("key.superbwarfare.edit_barrel", GLFW.GLFW_KEY_LEFT, "key.categories.superbwarfare"); + public static final KeyMapping EDIT_MAGAZINE = new KeyMapping("key.superbwarfare.edit_magazine", GLFW.GLFW_KEY_DOWN, "key.categories.superbwarfare"); + public static final KeyMapping EDIT_STOCK = new KeyMapping("key.superbwarfare.edit_stock", GLFW.GLFW_KEY_RIGHT, "key.categories.superbwarfare"); + public static final KeyMapping EDIT_GRIP = new KeyMapping("key.superbwarfare.edit_grip", KeyConflictContext.IN_GAME, + KeyModifier.SHIFT, InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_DOWN, "key.categories.superbwarfare"); + + public static final KeyMapping FIRE = new KeyMapping("key.superbwarfare.fire", InputConstants.Type.MOUSE, GLFW.GLFW_MOUSE_BUTTON_LEFT, "key.categories.superbwarfare"); + public static final KeyMapping HOLD_ZOOM = new KeyMapping("key.superbwarfare.hold_zoom", InputConstants.Type.MOUSE, GLFW.GLFW_MOUSE_BUTTON_RIGHT, "key.categories.superbwarfare"); + public static final KeyMapping SWITCH_ZOOM = new KeyMapping("key.superbwarfare.switch_zoom", GLFW.GLFW_KEY_UNKNOWN, "key.categories.superbwarfare"); + public static final KeyMapping RELEASE_DECOY = new KeyMapping("key.superbwarfare.release_decoy", GLFW.GLFW_KEY_X, "key.categories.superbwarfare"); + public static final KeyMapping FREE_CAMERA = new KeyMapping("key.superbwarfare.free_camera", GLFW.GLFW_KEY_C, "key.categories.superbwarfare"); + public static final KeyMapping MELEE = new KeyMapping("key.superbwarfare.melee", GLFW.GLFW_KEY_V, "key.categories.superbwarfare"); + + @SubscribeEvent + public static void registerKeyMappings(RegisterKeyMappingsEvent event) { + event.register(RELOAD); + event.register(FIRE_MODE); + event.register(SENSITIVITY_INCREASE); + event.register(SENSITIVITY_REDUCE); + event.register(INTERACT); + event.register(DISMOUNT); + event.register(BREATH); + event.register(CONFIG); + event.register(EDIT_MODE); + event.register(EDIT_SCOPE); + event.register(EDIT_BARREL); + event.register(EDIT_MAGAZINE); + event.register(EDIT_STOCK); + event.register(EDIT_GRIP); + event.register(FIRE); + event.register(HOLD_ZOOM); + event.register(SWITCH_ZOOM); + event.register(RELEASE_DECOY); + event.register(MELEE); + event.register(FREE_CAMERA); + } + + @EventBusSubscriber(value = Dist.CLIENT) + public static class KeyEventListener { + @SubscribeEvent + public static void onClientTick(ClientTickEvent.Pre event) { + if (Minecraft.getInstance().screen == null) { + BREATH.consumeClick(); + } + } + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModScreens.java b/src/main/java/com/atsuishio/superbwarfare/init/ModScreens.java new file mode 100644 index 000000000..84746d4c5 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModScreens.java @@ -0,0 +1,20 @@ +package com.atsuishio.superbwarfare.init; + +import com.atsuishio.superbwarfare.ModUtils; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent; + +@EventBusSubscriber(modid = ModUtils.MODID, bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +public class ModScreens { + + @SubscribeEvent + public static void clientLoad(RegisterMenuScreensEvent event) { + // TODO 正确注册menu +// event.register(ModMenuTypes.REFORGING_TABLE_MENU.get(), ReforgingTableScreen::new); +// 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); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/CreativeChargingStationBlockItem.java b/src/main/java/com/atsuishio/superbwarfare/item/CreativeChargingStationBlockItem.java new file mode 100644 index 000000000..510225555 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/CreativeChargingStationBlockItem.java @@ -0,0 +1,23 @@ +package com.atsuishio.superbwarfare.item; + +import com.atsuishio.superbwarfare.init.ModBlocks; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Rarity; + +public class CreativeChargingStationBlockItem extends BlockItem { + + public CreativeChargingStationBlockItem() { + super(ModBlocks.CREATIVE_CHARGING_STATION.get(), new Properties().rarity(Rarity.EPIC).stacksTo(1)); + } + + // TODO capability +// @Override +// public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag tag) { +// return new ICapabilityProvider() { +// @Override +// public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { +// return ForgeCapabilities.ENERGY.orEmpty(cap, LazyOptional.of(InfinityEnergyStorage::new)); +// } +// }; +// } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java b/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java index cf76e6731..30bdef64e 100644 --- a/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java +++ b/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java @@ -1,5 +1,6 @@ package com.atsuishio.superbwarfare.network; +import com.atsuishio.superbwarfare.network.message.BreathMessage; import com.atsuishio.superbwarfare.network.message.LaserShootMessage; import com.atsuishio.superbwarfare.network.message.PlayerVariablesSyncMessage; import com.atsuishio.superbwarfare.network.message.ShakeClientMessage; @@ -28,5 +29,11 @@ public class NetworkRegistry { LaserShootMessage::handler ); + registrar.playToServer( + BreathMessage.TYPE, + BreathMessage.STREAM_CODEC, + BreathMessage::handler + ); + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/network/message/BreathMessage.java b/src/main/java/com/atsuishio/superbwarfare/network/message/BreathMessage.java new file mode 100644 index 000000000..5f286c926 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/network/message/BreathMessage.java @@ -0,0 +1,29 @@ +package com.atsuishio.superbwarfare.network.message; + +import com.atsuishio.superbwarfare.ModUtils; +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.neoforged.neoforge.network.handling.IPayloadContext; +import org.jetbrains.annotations.NotNull; + +public record BreathMessage(boolean messageType) implements CustomPacketPayload { + public static final Type TYPE = new Type<>(ModUtils.loc("breath")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.BOOL, + BreathMessage::messageType, + BreathMessage::new + ); + + + public static void handler(final BreathMessage message, final IPayloadContext context) { + // TODO handler + } + + @Override + public @NotNull Type type() { + return TYPE; + } +} \ No newline at end of file