From a5150e34fe35be6c3222fa1e7c95e2ee0176d777 Mon Sep 17 00:00:00 2001 From: TGdoesCode Date: Wed, 21 Jan 2026 09:34:51 +0100 Subject: [PATCH] update drog effect --- gradle.properties | 2 +- .../szar/client/MouseScrambleState.java | 12 +++ .../szar/client/SmokeZoomHandler.java | 2 +- .../dev/tggamesyt/szar/client/SzarClient.java | 92 ++++++++++++++++--- .../szar/client/mixin/MouseMixin.java | 85 +++++++++++++++++ src/client/resources/szar.client.mixins.json | 3 +- src/main/java/dev/tggamesyt/szar/Joint.java | 84 +++++++++++++++-- .../dev/tggamesyt/szar/NwordPassItem.java | 2 +- src/main/java/dev/tggamesyt/szar/Szar.java | 63 ++++++++++++- 9 files changed, 320 insertions(+), 25 deletions(-) create mode 100644 src/client/java/dev/tggamesyt/szar/client/MouseScrambleState.java create mode 100644 src/client/java/dev/tggamesyt/szar/client/mixin/MouseMixin.java diff --git a/gradle.properties b/gradle.properties index a363ace..5c68eba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ minecraft_version=1.20.1 yarn_mappings=1.20.1+build.10 loader_version=0.18.3 # Mod Properties -mod_version=1.0.4 +mod_version=1.0.5 maven_group=dev.tggamesyt archives_base_name=szar # Dependencies diff --git a/src/client/java/dev/tggamesyt/szar/client/MouseScrambleState.java b/src/client/java/dev/tggamesyt/szar/client/MouseScrambleState.java new file mode 100644 index 0000000..888b149 --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/MouseScrambleState.java @@ -0,0 +1,12 @@ +package dev.tggamesyt.szar.client; +import dev.tggamesyt.szar.client.SzarClient.MouseScrambleMode; + +public class MouseScrambleState { + public static MouseScrambleMode active = MouseScrambleMode.NONE; + public static boolean wasMoving = false; + + public static void reset() { + active = MouseScrambleMode.NONE; + wasMoving = false; + } +} diff --git a/src/client/java/dev/tggamesyt/szar/client/SmokeZoomHandler.java b/src/client/java/dev/tggamesyt/szar/client/SmokeZoomHandler.java index 98decee..33bbb6f 100644 --- a/src/client/java/dev/tggamesyt/szar/client/SmokeZoomHandler.java +++ b/src/client/java/dev/tggamesyt/szar/client/SmokeZoomHandler.java @@ -1,6 +1,6 @@ package dev.tggamesyt.szar.client; -import dev.tggamesyt.szar.items.Joint; +import dev.tggamesyt.szar.Joint; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.minecraft.item.ItemStack; diff --git a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java index b09d168..6de9b0b 100644 --- a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java +++ b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java @@ -1,34 +1,32 @@ package dev.tggamesyt.szar.client; import com.mojang.blaze3d.systems.RenderSystem; -import dev.tggamesyt.szar.NiggerEntity; import dev.tggamesyt.szar.Szar; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry; import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry; import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry; import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.client.gui.hud.InGameHud; -import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; import net.minecraft.client.render.*; -import net.minecraft.client.render.entity.model.BipedEntityModel; -import net.minecraft.client.render.entity.model.EntityModelLayers; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.random.Random; + +import java.util.HashMap; +import java.util.Map; public class SzarClient implements ClientModInitializer { - + private static final Map activeScramble = new HashMap<>(); @Override public void onInitializeClient() { ClientPlayNetworking.registerGlobalReceiver( - Szar.NWORDPACKET, + Szar.TOTEMPACKET, (client, handler, buf, responseSender) -> { ItemStack stack = buf.readItemStack(); @@ -60,6 +58,7 @@ public class SzarClient implements ClientModInitializer { var effect = client.player.getStatusEffect(Szar.DROG_EFFECT); int amplifier = effect.getAmplifier(); // 0 = level I + if (amplifier > 2) {amplifier = 2;} float level = amplifier + 1f; float time = client.player.age + tickDelta; @@ -104,6 +103,18 @@ public class SzarClient implements ClientModInitializer { RenderSystem.disableBlend(); }); + ClientTickEvents.END_CLIENT_TICK.register(client -> { + if (client.player == null) return; + if (!client.player.hasStatusEffect(Szar.DROG_EFFECT)) return; + + var effect = client.player.getStatusEffect(Szar.DROG_EFFECT); + int amplifier = effect.getAmplifier(); + float level = amplifier + 1f; + float chance = 0; + if (level > 6) {chance = 0.20f * (level-6);} + scrambleMovement(client, chance); + }); + HudRenderCallback.EVENT.register((drawContext, tickDelta) -> { MinecraftClient client = MinecraftClient.getInstance(); @@ -123,4 +134,63 @@ public class SzarClient implements ClientModInitializer { }); } + private static void scrambleMovement(MinecraftClient client, float chance) { + var options = client.options; + long window = client.getWindow().getHandle(); + Random random = client.player.getRandom(); + + KeyBinding[] movementKeys = { + options.forwardKey, + options.backKey, + options.leftKey, + options.rightKey + }; + + /* ───── Clear logical movement every tick ───── */ + for (KeyBinding key : movementKeys) { + KeyBinding.setKeyPressed(key.getDefaultKey(), false); + } + + /* ───── Handle each movement key ───── */ + for (KeyBinding key : movementKeys) { + InputUtil.Key bound = key.getDefaultKey(); + + if (bound.getCategory() != InputUtil.Type.KEYSYM) continue; + + boolean physicallyDown = + InputUtil.isKeyPressed(window, bound.getCode()); + + if (physicallyDown) { + /* ───── Key is held ───── */ + + // If first tick of press → decide direction + if (!activeScramble.containsKey(key)) { + KeyBinding chosen = key; + + if (random.nextFloat() < chance) { + do { + chosen = movementKeys[random.nextInt(movementKeys.length)]; + } while (chosen == key); + } + + activeScramble.put(key, chosen); + } + + // Apply stored direction + KeyBinding result = activeScramble.get(key); + KeyBinding.setKeyPressed(result.getDefaultKey(), true); + + } else { + /* ───── Key released ───── */ + activeScramble.remove(key); + } + } + } + public enum MouseScrambleMode { + NONE, + INVERT_X, + INVERT_Y, + INVERT_BOTH + } + } diff --git a/src/client/java/dev/tggamesyt/szar/client/mixin/MouseMixin.java b/src/client/java/dev/tggamesyt/szar/client/mixin/MouseMixin.java new file mode 100644 index 0000000..c1da07c --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/mixin/MouseMixin.java @@ -0,0 +1,85 @@ +package dev.tggamesyt.szar.client.mixin; + +import dev.tggamesyt.szar.Szar; +import dev.tggamesyt.szar.client.MouseScrambleState; +import dev.tggamesyt.szar.client.SzarClient; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.Mouse; +import net.minecraft.util.math.random.Random; +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.ModifyArgs; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.invoke.arg.Args; + +import static dev.tggamesyt.szar.client.SzarClient.MouseScrambleMode.*; + +@Mixin(Mouse.class) +public abstract class MouseMixin { + + @Shadow private MinecraftClient client; + + @ModifyArgs( + method = "updateMouse", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/network/ClientPlayerEntity;changeLookDirection(DD)V" + ) + ) + private void szar$scrambleMouse(Args args) { + + if (client.player == null) return; + + if (!client.player.hasStatusEffect(Szar.DROG_EFFECT)) { + MouseScrambleState.reset(); + return; + } + + double dx = args.get(0); + double dy = args.get(1); + + boolean isMoving = dx != 0 || dy != 0; + + var effect = client.player.getStatusEffect(Szar.DROG_EFFECT); + assert effect != null; + int amplifier = effect.getAmplifier(); + float level = amplifier + 1f; + float chance = 0; + if (level > 8) {chance = 0.25f * (level-8);} + Random random = client.player.getRandom(); + + /* ───── Mouse movement started ───── */ + if (isMoving && !MouseScrambleState.wasMoving) { + + MouseScrambleState.active = SzarClient.MouseScrambleMode.NONE; + + if (random.nextFloat() < chance) { + SzarClient.MouseScrambleMode[] modes = { + INVERT_X, + INVERT_Y, + INVERT_BOTH + }; + + MouseScrambleState.active = + modes[random.nextInt(modes.length)]; + } + } + + /* ───── Apply scramble ───── */ + switch (MouseScrambleState.active) { + case INVERT_X -> dx = -dx; + case INVERT_Y -> dy = -dy; + case INVERT_BOTH -> { + dx = -dx; + dy = -dy; + } + } + + MouseScrambleState.wasMoving = isMoving; + + args.set(0, dx); + args.set(1, dy); + } +} diff --git a/src/client/resources/szar.client.mixins.json b/src/client/resources/szar.client.mixins.json index a7de253..cce8fa8 100644 --- a/src/client/resources/szar.client.mixins.json +++ b/src/client/resources/szar.client.mixins.json @@ -1,9 +1,10 @@ { "required": true, "minVersion": "0.8", - "package": "dev.tggamesyt.szar.mixin.client", + "package": "dev.tggamesyt.szar.client.mixin", "compatibilityLevel": "JAVA_17", "client": [ + "MouseMixin" ], "injectors": { "defaultRequire": 1 diff --git a/src/main/java/dev/tggamesyt/szar/Joint.java b/src/main/java/dev/tggamesyt/szar/Joint.java index ca29e3f..e70dde5 100644 --- a/src/main/java/dev/tggamesyt/szar/Joint.java +++ b/src/main/java/dev/tggamesyt/szar/Joint.java @@ -1,10 +1,16 @@ -package dev.tggamesyt.szar.items; +package dev.tggamesyt.szar; import dev.tggamesyt.szar.Szar; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.effect.StatusEffects; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.SpyglassItem; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.sound.SoundEvents; import net.minecraft.stat.Stats; import net.minecraft.util.Hand; @@ -15,9 +21,9 @@ import net.minecraft.world.World; public class Joint extends SpyglassItem { public Joint(Settings settings) { - super(settings.maxDamage(64)); // max durability + super(settings.maxDamage(20)); // max durability } - + private static final int COOLDOWN_TICKS = 20 * 5; @Override public UseAction getUseAction(ItemStack stack) { return UseAction.SPYGLASS; // keeps spyglass hold animation @@ -40,28 +46,90 @@ public class Joint extends SpyglassItem { @Override public void onStoppedUsing(ItemStack stack, World world, LivingEntity user, int remainingUseTicks) { // Only do server/client side durability and effect - if (!world.isClient) return; + //if (!world.isClient) return; // Consume 1 durability stack.damage(1, user, p -> p.sendToolBreakStatus(user.getActiveHand())); - + if (user instanceof PlayerEntity player && !world.isClient) { + player.getItemCooldownManager().set(this, COOLDOWN_TICKS); + } // Increase drug effect int amplifier = 0; if (user.hasStatusEffect(Szar.DROG_EFFECT)) { amplifier = Math.min(user.getStatusEffect(Szar.DROG_EFFECT).getAmplifier() + 1, 9); // max 10 levels + user.addStatusEffect(new StatusEffectInstance( + StatusEffects.LUCK, + 1200, + amplifier, + false, // ambient + true, // show particles + true // show icon + )); + user.addStatusEffect(new StatusEffectInstance( + StatusEffects.MINING_FATIGUE, + 1200, + amplifier, + false, // ambient + true, // show particles + true // show icon + )); + user.addStatusEffect(new StatusEffectInstance( + StatusEffects.STRENGTH, + 1200, + amplifier, + false, // ambient + true, // show particles + true // show icon + )); + user.addStatusEffect(new StatusEffectInstance( + StatusEffects.HEALTH_BOOST, + 1200, + amplifier, + false, // ambient + true, // show particles + true // show icon + )); + user.addStatusEffect(new StatusEffectInstance( + StatusEffects.REGENERATION, + 1200, + amplifier, + false, // ambient + true, // show particles + true // show icon + )); + user.addStatusEffect(new StatusEffectInstance( + StatusEffects.SATURATION, + 1200, + amplifier, + false, // ambient + true, // show particles + true // show icon + )); + } + if (amplifier > 3) { + int nausealevel = amplifier - 3; + user.addStatusEffect(new StatusEffectInstance( + StatusEffects.NAUSEA, + 1200, + nausealevel, + false, // ambient + true, // show particles + true // show icon + )); } // Apply the effect (10 seconds, invisible particles) - user.addStatusEffect(new net.minecraft.entity.effect.StatusEffectInstance( + user.addStatusEffect(new StatusEffectInstance( Szar.DROG_EFFECT, - 6000, + 1200, amplifier, false, // ambient - false, // show particles + true, // show particles true // show icon )); // Optional: play inhale / stop sound user.playSound(SoundEvents.ITEM_HONEY_BOTTLE_DRINK, 1.0F, 1.0F); } + } diff --git a/src/main/java/dev/tggamesyt/szar/NwordPassItem.java b/src/main/java/dev/tggamesyt/szar/NwordPassItem.java index efbd962..f4da7ab 100644 --- a/src/main/java/dev/tggamesyt/szar/NwordPassItem.java +++ b/src/main/java/dev/tggamesyt/szar/NwordPassItem.java @@ -31,7 +31,7 @@ public class NwordPassItem extends Item { PacketByteBuf buf = PacketByteBufs.create(); buf.writeItemStack(stack); - ServerPlayNetworking.send(serverPlayer, Szar.NWORDPACKET, buf); + ServerPlayNetworking.send(serverPlayer, Szar.TOTEMPACKET, buf); } //world.sendEntityStatus(user, (byte) 35); diff --git a/src/main/java/dev/tggamesyt/szar/Szar.java b/src/main/java/dev/tggamesyt/szar/Szar.java index 81c5f59..06b6e39 100644 --- a/src/main/java/dev/tggamesyt/szar/Szar.java +++ b/src/main/java/dev/tggamesyt/szar/Szar.java @@ -1,10 +1,12 @@ package dev.tggamesyt.szar; -import dev.tggamesyt.szar.items.Joint; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.item.v1.FabricItemSettings; import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup; import net.fabricmc.fabric.api.message.v1.ServerMessageDecoratorEvent; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry; import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder; @@ -17,13 +19,19 @@ import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.EntityType; import net.minecraft.entity.SpawnGroup; import net.minecraft.entity.effect.StatusEffect; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.*; +import net.minecraft.network.PacketByteBuf; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; +import net.minecraft.world.World; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -39,7 +47,7 @@ public class Szar implements ModInitializer { new Block(AbstractBlock.Settings.copy(Blocks.NETHERITE_BLOCK)); public static final Block FASZ_BLOCK = new FaszBlock(); - public static final Identifier NWORDPACKET = + public static final Identifier TOTEMPACKET = new Identifier(MOD_ID, "nwordpacket"); public static final ItemGroup SZAR_GROUP = Registry.register( Registries.ITEM_GROUP, @@ -104,6 +112,13 @@ public class Szar implements ModInitializer { GYPSY_ENTITY_TYPE, GypsyEntity.createAttributes() ); + ServerTickEvents.END_WORLD_TICK.register(world -> { + for (var entity : world.getPlayers()) { + if (entity.getHealth() <= 0f) { + tryDrugTotem(entity); + } + } + }); } public static final StatusEffect DROG_EFFECT = Registry.register( Registries.STATUS_EFFECT, @@ -344,6 +359,50 @@ public class Szar implements ModInitializer { .getProgress(advancement) .isDone(); } + public static boolean tryDrugTotem(PlayerEntity player) { + StatusEffectInstance effect = player.getStatusEffect(Szar.DROG_EFFECT); + if (effect == null || effect.getAmplifier() < 5) return false; + // Only trigger if holding Joint + ItemStack stack = player.getMainHandStack(); + if (!(stack.getItem() instanceof Joint)) return false; + + World world = player.getWorld(); + + // Prevent death + player.setHealth(1f); + + // Clear negative effects + player.clearStatusEffects(); + + // Vanilla totem effects + player.addStatusEffect(new StatusEffectInstance(StatusEffects.REGENERATION, 900, 1)); + player.addStatusEffect(new StatusEffectInstance(StatusEffects.ABSORPTION, 100, 1)); + player.addStatusEffect(new StatusEffectInstance(StatusEffects.FIRE_RESISTANCE, 800, 0)); + + // Sound + player.playSound(SoundEvents.ITEM_TOTEM_USE, 1f, 1f); + + // Animation via packet + if (!world.isClient() && player instanceof ServerPlayerEntity serverPlayer) { + PacketByteBuf buf = PacketByteBufs.create(); + buf.writeItemStack(stack); + ServerPlayNetworking.send(serverPlayer, Szar.TOTEMPACKET, buf); + } + + // Reduce drug level safely + int duration = effect.getDuration(); + int amplifier = effect.getAmplifier(); + player.addStatusEffect(new StatusEffectInstance( + Szar.DROG_EFFECT, + duration, + Math.max(0, amplifier - 2), + false, + true, + true + )); + + return true; + } }