updated weed joint, plane crash and atomic bomb explosion

This commit is contained in:
2026-03-11 09:36:32 +01:00
parent 485b15082e
commit 20a755064b
16 changed files with 638 additions and 63 deletions

View File

@@ -21,6 +21,7 @@ import net.minecraft.client.gui.screen.ingame.HandledScreens;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.OtherClientPlayerEntity;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.render.entity.EmptyEntityRenderer;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.FlyingItemEntityRenderer;
import net.minecraft.client.render.entity.PlayerEntityRenderer;
@@ -61,7 +62,9 @@ import static dev.tggamesyt.szar.client.ClientCosmetics.loadTextureFromURL;
import static dev.tggamesyt.szar.client.UraniumUtils.updateUranium;
public class SzarClient implements ClientModInitializer {
private static boolean addedFeature = false;
// add this field to your client init class
private float drogOverlayProgress = 0.0F;
private long lastTime = 0;
private static final Map<KeyBinding, KeyBinding> activeScramble = new HashMap<>();
public static final EntityModelLayer PLANE =
new EntityModelLayer(
@@ -88,6 +91,7 @@ public class SzarClient implements ClientModInitializer {
int loopStart = startOffset + startLength;
@Override
public void onInitializeClient() {
EntityRendererRegistry.register(Szar.RADIATION_AREA, EmptyEntityRenderer::new);
ClientPlayNetworking.registerGlobalReceiver(Szar.PLAY_VIDEO,
(client, handler, buf, responseSender) -> {
String player = buf.readString();
@@ -358,53 +362,59 @@ public class SzarClient implements ClientModInitializer {
);
HudRenderCallback.EVENT.register((drawContext, tickDelta) -> {
MinecraftClient client = MinecraftClient.getInstance();
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(); // 0 = level I
if (amplifier > 2) {amplifier = 2;}
boolean hasEffect = client.player.hasStatusEffect(Szar.DROG_EFFECT);
// ease in/out — 0.02F controls speed, lower = slower transition
if (hasEffect) {
drogOverlayProgress = Math.min(1.0F, drogOverlayProgress + tickDelta * 0.02F);
} else {
drogOverlayProgress = Math.max(0.0F, drogOverlayProgress - tickDelta * 0.02F);
}
if (drogOverlayProgress <= 0.0F) return;
// S-curve easing so it accelerates then decelerates
float eased = drogOverlayProgress * drogOverlayProgress * (3.0F - 2.0F * drogOverlayProgress);
var effect = hasEffect ? client.player.getStatusEffect(Szar.DROG_EFFECT) : null;
int amplifier = effect != null ? Math.min(effect.getAmplifier(), 2) : 0;
float level = amplifier + 1f;
float time = client.player.age + tickDelta;
/* ───── Color speed (gentle ramp) ───── */
float speed = 0.015f + amplifier * 0.012f;
float hue = (time * speed) % 1.0f;
int rgb = MathHelper.hsvToRgb(hue, 0.95f, 1f);
/* ───── Alpha (mostly stable) ───── */
float pulse =
(MathHelper.sin(time * (0.04f + amplifier * 0.015f)) + 1f) * 0.5f;
// multiply alpha by eased so it fades in/out smoothly
float alpha = MathHelper.clamp(
0.20f + amplifier * 0.10f + pulse * 0.10f,
0.20f,
(0.20f + amplifier * 0.10f + pulse * 0.10f) * eased,
0.0f,
0.70f
);
/* ───── Very subtle jitter ───── */
float jitter = 0.15f * amplifier;
// jitter also scales with eased so it doesn't pop in suddenly
float jitter = 0.15f * amplifier * eased;
float jitterX = (client.world.random.nextFloat() - 0.5f) * jitter;
float jitterY = (client.world.random.nextFloat() - 0.5f) * jitter;
int width = client.getWindow().getScaledWidth();
int height = client.getWindow().getScaledHeight();
int color =
((int)(alpha * 255) << 24)
| (rgb & 0x00FFFFFF);
int color = ((int)(alpha * 255) << 24) | (rgb & 0x00FFFFFF);
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
drawContext.getMatrices().push();
drawContext.getMatrices().translate(jitterX, jitterY, 0);
drawContext.fill(0, 0, width, height, color);
drawContext.getMatrices().pop();
RenderSystem.disableBlend();

View File

@@ -0,0 +1,54 @@
package dev.tggamesyt.szar.client.mixin;
import dev.tggamesyt.szar.Joint;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.entity.model.BipedEntityModel;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Arm;
import net.minecraft.util.Hand;
import net.minecraft.util.math.MathHelper;
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(BipedEntityModel.class)
public abstract class BipedEntityModelMixin<T extends LivingEntity> {
@Shadow public ModelPart rightArm;
@Shadow public ModelPart leftArm;
@Shadow public ModelPart head;
@Inject(
method = "setAngles",
at = @At(
value = "INVOKE",
// hat.copyTransform(head) is the absolute last call in setAngles
target = "Lnet/minecraft/client/model/ModelPart;copyTransform(Lnet/minecraft/client/model/ModelPart;)V",
shift = At.Shift.AFTER
)
)
private void injectJointPose(T entity, float f, float g, float h, float i, float j, CallbackInfo ci) {
if (!entity.isUsingItem()) return;
if (!(entity.getActiveItem().getItem() instanceof Joint)) return;
boolean mainHand = entity.getActiveHand() == Hand.MAIN_HAND;
boolean rightHanded = entity.getMainArm() == Arm.RIGHT;
boolean useRight = (mainHand && rightHanded) || (!mainHand && !rightHanded);
if (useRight) {
this.rightArm.pitch = MathHelper.clamp(
this.head.pitch - 1.7F - (entity.isInSneakingPose() ? 0.2617994F : 0.0F),
-2.4F, 3.3F
);
this.rightArm.yaw = this.head.yaw - 0.4F;
} else {
this.leftArm.pitch = MathHelper.clamp(
this.head.pitch - 1.7F - (entity.isInSneakingPose() ? 0.2617994F : 0.0F),
-2.4F, 3.3F
);
this.leftArm.yaw = this.head.yaw + 0.4F;
}
}
}

View File

@@ -0,0 +1,46 @@
package dev.tggamesyt.szar.client.mixin;
import dev.tggamesyt.szar.Joint;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.GameRenderer;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(GameRenderer.class)
public abstract class GameRendererMixin {
@Shadow @Final private MinecraftClient client;
// smooth value between 0.0 (no zoom) and 1.0 (full zoom)
@Unique private float szar$jointZoomProgress = 0.0F;
@Inject(method = "getFov", at = @At("RETURN"), cancellable = true)
private void injectJointFov(Camera camera, float tickDelta, boolean changingFov, CallbackInfoReturnable<Double> cir) {
if (this.client.player == null) return;
boolean isUsing = this.client.player.isUsingItem()
&& this.client.player.getActiveItem().getItem() instanceof Joint;
// ease in when using, ease out when not
if (isUsing) {
szar$jointZoomProgress = Math.min(1.0F, szar$jointZoomProgress + tickDelta * 0.1F);
} else {
szar$jointZoomProgress = Math.max(0.0F, szar$jointZoomProgress - tickDelta * 0.1F);
}
if (szar$jointZoomProgress <= 0.0F) return;
// smooth S-curve easing
float eased = szar$jointZoomProgress * szar$jointZoomProgress * (3.0F - 2.0F * szar$jointZoomProgress);
double currentFov = cir.getReturnValue();
// lerp toward 90% of normal FOV (10% zoom)
cir.setReturnValue(currentFov * (1.0 - 0.1 * eased));
}
}

View File

@@ -0,0 +1,68 @@
package dev.tggamesyt.szar.client.mixin;
import dev.tggamesyt.szar.Joint;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.item.HeldItemRenderer;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Arm;
import net.minecraft.util.Hand;
import net.minecraft.util.math.RotationAxis;
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(HeldItemRenderer.class)
public abstract class HeldItemRendererMixin {
@Inject(method = "renderFirstPersonItem", at = @At("HEAD"), cancellable = true)
private void injectJointFirstPerson(
AbstractClientPlayerEntity player,
float tickDelta,
float pitch,
Hand hand,
float swingProgress,
ItemStack item,
float equipProgress,
MatrixStack matrices,
VertexConsumerProvider vertexConsumers,
int light,
CallbackInfo ci
) {
if (!(item.getItem() instanceof Joint)) return;
// only override position while actively using, otherwise let normal rendering handle equip/unequip
if (!player.isUsingItem() || player.getActiveHand() != hand || player.getItemUseTimeLeft() <= 0) return;
boolean isMainHand = hand == Hand.MAIN_HAND;
Arm arm = isMainHand ? player.getMainArm() : player.getMainArm().getOpposite();
boolean isRight = arm == Arm.RIGHT;
matrices.push();
// rotate 80 degrees toward player (around Y axis, so it faces them)
matrices.translate(
0.0F,
-0.15F, // was -0.35F, more negative = higher up
-0.5F
);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(80.0F));
matrices.translate(0.0F, equipProgress * -0.6F, 0.0F);
HeldItemRenderer self = (HeldItemRenderer)(Object)this;
self.renderItem(
player,
item,
isRight ? ModelTransformationMode.FIRST_PERSON_RIGHT_HAND : ModelTransformationMode.FIRST_PERSON_LEFT_HAND,
!isRight,
matrices,
vertexConsumers,
light
);
matrices.pop();
ci.cancel();
}
}

View File

@@ -1,12 +1,18 @@
package dev.tggamesyt.szar.client.mixin;
import dev.tggamesyt.szar.Joint;
import dev.tggamesyt.szar.client.VideoHeadFeature;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.PlayerEntityRenderer;
import net.minecraft.client.render.entity.model.BipedEntityModel;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
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;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(PlayerEntityRenderer.class)
public abstract class PlayerEntityRendererMixin {
@@ -18,4 +24,20 @@ public abstract class PlayerEntityRendererMixin {
renderer.addFeature(new VideoHeadFeature(renderer));
}
@Inject(method = "getArmPose", at = @At("RETURN"), cancellable = true)
private static void injectJointArmPose(
AbstractClientPlayerEntity player,
Hand hand,
CallbackInfoReturnable<BipedEntityModel.ArmPose> cir
) {
ItemStack stack = player.getStackInHand(hand);
if (!stack.isEmpty()
&& player.getActiveHand() == hand
&& player.getItemUseTimeLeft() > 0
&& stack.getItem() instanceof Joint) {
// SPYGLASS pose raises the arm, then BipedEntityModelMixin overrides the exact angles
cir.setReturnValue(BipedEntityModel.ArmPose.SPYGLASS);
}
}
}

View File

@@ -0,0 +1,72 @@
package dev.tggamesyt.szar.client.mixin;
import dev.tggamesyt.szar.Joint;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.feature.PlayerHeldItemFeatureRenderer;
import net.minecraft.client.render.entity.model.ModelWithHead;
import net.minecraft.client.render.item.HeldItemRenderer;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Arm;
import net.minecraft.util.math.MathHelper;
import org.spongepowered.asm.mixin.Final;
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(PlayerHeldItemFeatureRenderer.class)
public abstract class PlayerHeldItemFeatureRendererMixin<T extends net.minecraft.entity.player.PlayerEntity, M extends net.minecraft.client.render.entity.model.EntityModel<T> & net.minecraft.client.render.entity.model.ModelWithArms & ModelWithHead> extends net.minecraft.client.render.entity.feature.HeldItemFeatureRenderer<T, M> {
@Shadow @Final private HeldItemRenderer playerHeldItemRenderer;
public PlayerHeldItemFeatureRendererMixin(net.minecraft.client.render.entity.feature.FeatureRendererContext<T, M> context, HeldItemRenderer heldItemRenderer) {
super(context, heldItemRenderer);
}
@Inject(method = "renderItem", at = @At("HEAD"), cancellable = true)
private void injectJointRender(
LivingEntity entity,
ItemStack stack,
ModelTransformationMode transformationMode,
Arm arm,
MatrixStack matrices,
VertexConsumerProvider vertexConsumers,
int light,
CallbackInfo ci
) {
if (stack.getItem() instanceof Joint
&& entity.getActiveItem() == stack
&& entity.handSwingTicks == 0) {
matrices.push();
ModelPart head = ((ModelWithHead) this.getContextModel()).getHead();
float savedPitch = head.pitch;
// clamp head pitch so the joint doesn't clip into the head when looking up/down
head.pitch = MathHelper.clamp(head.pitch, -(float)(Math.PI / 6F), (float)(Math.PI / 2F));
head.rotate(matrices);
head.pitch = savedPitch;
net.minecraft.client.render.entity.feature.HeadFeatureRenderer.translate(matrices, false);
boolean isLeft = arm == Arm.LEFT;
matrices.translate(
0F,
-0.3F,
0.1F
);
this.playerHeldItemRenderer.renderItem(entity, stack, ModelTransformationMode.HEAD, false, matrices, vertexConsumers, light);
matrices.pop();
ci.cancel();
}
}
}

View File

@@ -4,9 +4,13 @@
"package": "dev.tggamesyt.szar.client.mixin",
"compatibilityLevel": "JAVA_17",
"client": [
"BipedEntityModelMixin",
"GameRendererMixin",
"HeldItemRendererMixin",
"ItemRendererMixin",
"MouseMixin",
"PlayerEntityRendererMixin",
"PlayerHeldItemFeatureRendererMixin",
"PlayerModelMixin",
"RadiatedItemRendererMixin",
"RadiationHeartMixin",