diff --git a/src/client/java/dev/tggamesyt/szar/client/mixin/RadiatedItemRendererMixin.java b/src/client/java/dev/tggamesyt/szar/client/mixin/RadiatedItemRendererMixin.java new file mode 100644 index 0000000..30ec1f8 --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/mixin/RadiatedItemRendererMixin.java @@ -0,0 +1,58 @@ +package dev.tggamesyt.szar.client.mixin; + +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.item.ItemRenderer; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.json.ModelTransformationMode; +import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import org.joml.Matrix4f; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ItemRenderer.class) +public abstract class RadiatedItemRendererMixin { + + @Inject( + method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;)V", + at = @At("TAIL") + ) + private void renderRadiationPixel(ItemStack stack, + ModelTransformationMode mode, + boolean leftHanded, + MatrixStack matrices, + VertexConsumerProvider vertexConsumers, + int light, + int overlay, + BakedModel model, + CallbackInfo ci) { + + if (!stack.hasNbt() || !stack.getNbt().getBoolean("Radiated")) return; + + int x = Math.min(stack.getNbt().getInt("RadPixelX"), 15) / 2; + int y = Math.min(stack.getNbt().getInt("RadPixelY"), 15) / 2; + + matrices.push(); + Matrix4f matrix = matrices.peek().getPositionMatrix(); + + VertexConsumer vc = vertexConsumers.getBuffer(RenderLayer.getSolid()); // no atlas + + float px = x / 16f; + float py = y / 16f; + float size = 1f / 16f; + float z = 0.01f; + + // draw 1px green quad on top of item + vc.vertex(matrix, px, py, z).color(0f,1f,0f,1f).texture(0f,0f).overlay(overlay).light(light).normal(0f,0f,1f).next(); + vc.vertex(matrix, px + size, py, z).color(0f,1f,0f,1f).texture(0f,0f).overlay(overlay).light(light).normal(0f,0f,1f).next(); + vc.vertex(matrix, px + size, py + size, z).color(0f,1f,0f,1f).texture(0f,0f).overlay(overlay).light(light).normal(0f,0f,1f).next(); + vc.vertex(matrix, px, py + size, z).color(0f,1f,0f,1f).texture(0f,0f).overlay(overlay).light(light).normal(0f,0f,1f).next(); + + matrices.pop(); + } +} diff --git a/src/client/resources/szar.client.mixins.json b/src/client/resources/szar.client.mixins.json index 294c188..7b2bfbc 100644 --- a/src/client/resources/szar.client.mixins.json +++ b/src/client/resources/szar.client.mixins.json @@ -5,7 +5,8 @@ "compatibilityLevel": "JAVA_17", "client": [ "MouseMixin", - "RadiationHeartMixin" + "RadiationHeartMixin", + "RadiatedItemRendererMixin" ], "injectors": { "defaultRequire": 1 diff --git a/src/main/java/dev/tggamesyt/szar/Szar.java b/src/main/java/dev/tggamesyt/szar/Szar.java index c4f1438..d5d5f18 100644 --- a/src/main/java/dev/tggamesyt/szar/Szar.java +++ b/src/main/java/dev/tggamesyt/szar/Szar.java @@ -82,7 +82,6 @@ import java.util.concurrent.CompletableFuture; import java.util.regex.Pattern; public class Szar implements ModInitializer { - public static final String MOD_ID = "szar"; public static final Logger LOGGER = LogManager.getLogger(MOD_ID); public static MinecraftServer SERVER; @@ -292,7 +291,6 @@ public class Szar implements ModInitializer { ServerLifecycleEvents.SERVER_STOPPED.register(server -> { SERVER = null; }); - // register block Registry.register( Registries.BLOCK, diff --git a/src/main/java/dev/tggamesyt/szar/mixin/CraftingScreenHandlerMixin.java b/src/main/java/dev/tggamesyt/szar/mixin/CraftingScreenHandlerMixin.java new file mode 100644 index 0000000..7fe463b --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/mixin/CraftingScreenHandlerMixin.java @@ -0,0 +1,75 @@ +package dev.tggamesyt.szar.mixin; + +import dev.tggamesyt.szar.RadiatedItem; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.CraftingInventory; +import net.minecraft.inventory.CraftingResultInventory; +import net.minecraft.inventory.RecipeInputInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket; +import net.minecraft.screen.CraftingScreenHandler; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(CraftingScreenHandler.class) +public class CraftingScreenHandlerMixin { + + @Inject( + method = "updateResult", + at = @At("HEAD"), + cancellable = true + ) + private static void onUpdateResult(ScreenHandler handler, + World world, + PlayerEntity player, + RecipeInputInventory craftingInventory, + CraftingResultInventory resultInventory, + CallbackInfo ci) { + + if (world.isClient) return; + + ItemStack resultStack = ItemStack.EMPTY; + + boolean hasRadiated = false; + ItemStack foodStack = ItemStack.EMPTY; + + // Check the crafting grid + for (int i = 0; i < craftingInventory.size(); i++) { + ItemStack stack = craftingInventory.getStack(i); + if (stack.isEmpty()) continue; + + if (stack.getItem() instanceof RadiatedItem) { + hasRadiated = true; + } else if (stack.isFood()) { + foodStack = stack; + } + } + + // If we found a food + radiated item, make a new edible copy + if (hasRadiated && !foodStack.isEmpty()) { + resultStack = new ItemStack(foodStack.getItem()); // preserves the original Item and its FoodComponent + resultStack.setCount(1); // optional: set to 1 + resultStack.setNbt(foodStack.getNbt() != null ? foodStack.getNbt().copy() : null); + + // Add our custom NBT to mark radiation + resultStack.getOrCreateNbt().putBoolean("Radiated", true); + resultStack.getOrCreateNbt().putInt("RadPixelX", player.getRandom().nextInt(16)); + resultStack.getOrCreateNbt().putInt("RadPixelY", player.getRandom().nextInt(16)); + } + + // Set the crafting output + resultInventory.setStack(0, resultStack); + handler.setPreviousTrackedSlot(0, resultStack); + ((ServerPlayerEntity) player).networkHandler.sendPacket( + new ScreenHandlerSlotUpdateS2CPacket(handler.syncId, handler.nextRevision(), 0, resultStack) + ); + + ci.cancel(); // prevent vanilla recipe overwrite + } +} diff --git a/src/main/java/dev/tggamesyt/szar/mixin/RadiatedItemMixin.java b/src/main/java/dev/tggamesyt/szar/mixin/RadiatedItemMixin.java new file mode 100644 index 0000000..76521f6 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/mixin/RadiatedItemMixin.java @@ -0,0 +1,37 @@ +package dev.tggamesyt.szar.mixin; + +import dev.tggamesyt.szar.Szar; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.damage.DamageType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.util.Hand; +import net.minecraft.util.TypedActionResult; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import static dev.tggamesyt.szar.Szar.RADIATION_DAMAGE; +import static dev.tggamesyt.szar.Szar.SERVER; + +@Mixin(Item.class) +public abstract class RadiatedItemMixin { + @Inject(method = "use", at = @At("RETURN")) + private void onUse(World world, PlayerEntity user, Hand hand, CallbackInfoReturnable> cir) { + ItemStack stack = cir.getReturnValue().getValue(); + if (!world.isClient && stack.hasNbt() && stack.getNbt().getBoolean("Radiated")) { + RegistryEntry radiationEntry = Szar.SERVER.getRegistryManager() + .get(RegistryKeys.DAMAGE_TYPE) + .getEntry(Szar.RADIATION_DAMAGE) + .orElseThrow(); + DamageSource radiation = new DamageSource(radiationEntry); + user.damage(radiation, Float.MAX_VALUE); + } + } +} diff --git a/src/main/resources/szar.mixins.json b/src/main/resources/szar.mixins.json index 7dac352..2b31406 100644 --- a/src/main/resources/szar.mixins.json +++ b/src/main/resources/szar.mixins.json @@ -4,7 +4,9 @@ "package": "dev.tggamesyt.szar.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "PlayerEntityMixin" + "PlayerEntityMixin", + "CraftingScreenHandlerMixin", + "RadiatedItemMixin" ], "injectors": { "defaultRequire": 1