diff --git a/gradle.properties b/gradle.properties index 61d027f..6f94019 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=26.3.30 +mod_version=26.4.1 maven_group=dev.tggamesyt archives_base_name=szar # Dependencies diff --git a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java index 8ad0723..c614530 100644 --- a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java +++ b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java @@ -58,7 +58,34 @@ public class SzarClient implements ClientModInitializer { // add this field to your client init class public static final int april = Szar.april; public static final int fools = Szar.fools; + public static boolean hasBeaten = false; + + // Transition state + public static long transitionStartTime = -1L; + public static boolean transitioningToNormal = false; // true = flipped->normal, false = normal->flipped + public static boolean wasFlipped = false; + + public static final long TRANSITION_DURATION_MS = 2000L; + private float drogOverlayProgress = 0.0F; + public static float getCurrentFlipAngle() { + if (transitionStartTime != -1L) { + long elapsed = System.currentTimeMillis() - transitionStartTime; + if (elapsed >= TRANSITION_DURATION_MS) { + transitionStartTime = -1L; + wasFlipped = false; + return hasBeaten ? 0f : 180f; + } + float t = (float) elapsed / (float) TRANSITION_DURATION_MS; + t = t * t * (3f - 2f * t); + if (transitioningToNormal) { + return 180f * (1f - t); // 180 -> 0 + } else { + return 180f * t; // 0 -> 180 + } + } + return hasBeaten ? 0f : 180f; + } private long lastTime = 0; private static final Map activeScramble = new HashMap<>(); public static final EntityModelLayer PLANE = @@ -90,6 +117,22 @@ public class SzarClient implements ClientModInitializer { ); @Override public void onInitializeClient() { + ClientPlayNetworking.registerGlobalReceiver(Szar.APRIL_GAME_BEATEN, (client, handler, buf, responseSender) -> { + client.execute(() -> { + hasBeaten = true; + transitionStartTime = System.currentTimeMillis(); + transitioningToNormal = true; + }); + }); + + ClientPlayNetworking.registerGlobalReceiver(Szar.APRIL_GAME_BEATEN_REVOKED, (client, handler, buf, responseSender) -> { + client.execute(() -> { + hasBeaten = false; + transitionStartTime = System.currentTimeMillis(); + transitioningToNormal = false; + wasFlipped = true; + }); + }); BlockEntityRendererFactories.register(BlueprintBlocks.BLUEPRINT_STAIRS_BE_TYPE, BlueprintBlockEntityRenderer::new); BlockEntityRendererFactories.register(BlueprintBlocks.BLUEPRINT_SLAB_BE_TYPE, BlueprintBlockEntityRenderer::new); BlockEntityRendererFactories.register(BlueprintBlocks.BLUEPRINT_DOOR_BE_TYPE, BlueprintBlockEntityRenderer::new); diff --git a/src/client/java/dev/tggamesyt/szar/client/mixin/MouseFlipMixin.java b/src/client/java/dev/tggamesyt/szar/client/mixin/MouseFlipMixin.java index eaf716a..a7f0176 100644 --- a/src/client/java/dev/tggamesyt/szar/client/mixin/MouseFlipMixin.java +++ b/src/client/java/dev/tggamesyt/szar/client/mixin/MouseFlipMixin.java @@ -1,6 +1,7 @@ package dev.tggamesyt.szar.client.mixin; import dev.tggamesyt.szar.client.SzarClient; +import dev.tggamesyt.szar.client.network.AprilGameBeatenReceiver; import net.minecraft.client.Mouse; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -28,6 +29,8 @@ public class MouseFlipMixin { ) private double flipMouseY(double pitchDelta) { if (!isAprilFools()) return pitchDelta; - return -pitchDelta; + // Flip mouse when angle is past 90 degrees (i.e. screen is more flipped than not) + if (SzarClient.getCurrentFlipAngle() > 90f) return -pitchDelta; + return pitchDelta; } } \ No newline at end of file diff --git a/src/client/java/dev/tggamesyt/szar/client/mixin/ScreenFlipMixin.java b/src/client/java/dev/tggamesyt/szar/client/mixin/ScreenFlipMixin.java index 1ac554b..313f34d 100644 --- a/src/client/java/dev/tggamesyt/szar/client/mixin/ScreenFlipMixin.java +++ b/src/client/java/dev/tggamesyt/szar/client/mixin/ScreenFlipMixin.java @@ -26,20 +26,27 @@ public class ScreenFlipMixin { @ModifyReturnValue(method = "getBasicProjectionMatrix", at = @At("RETURN")) private Matrix4f flipProjection(Matrix4f original) { if (!isAprilFools()) return original; - return original.scale(1.0f, -1.0f, 1.0f); + + float angle = SzarClient.getCurrentFlipAngle(); + if (angle == 0f) return original; + if (angle == 180f) return original.scale(1.0f, -1.0f, 1.0f); + + return original.rotateZ((float) Math.toRadians(angle)); } @Inject(method = "renderWorld", at = @At("HEAD")) private void setFrontFaceCW(float tickDelta, long limitTime, MatrixStack matrices, CallbackInfo ci) { if (!isAprilFools()) return; - // Y flip reverses winding order, so tell GL that clockwise = front face - GL11.glFrontFace(GL11.GL_CW); + if (SzarClient.getCurrentFlipAngle() > 90f) { + GL11.glFrontFace(GL11.GL_CW); + } } @Inject(method = "renderWorld", at = @At("TAIL")) private void restoreFrontFaceCCW(float tickDelta, long limitTime, MatrixStack matrices, CallbackInfo ci) { if (!isAprilFools()) return; - // Restore default: counter-clockwise = front face - GL11.glFrontFace(GL11.GL_CCW); + if (SzarClient.getCurrentFlipAngle() > 90f) { + GL11.glFrontFace(GL11.GL_CCW); + } } } \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/Szar.java b/src/main/java/dev/tggamesyt/szar/Szar.java index f8a5f33..37f5a60 100644 --- a/src/main/java/dev/tggamesyt/szar/Szar.java +++ b/src/main/java/dev/tggamesyt/szar/Szar.java @@ -103,6 +103,8 @@ public class Szar implements ModInitializer { public static final Logger LOGGER = LogManager.getLogger(MOD_ID); public static int april = 4; public static int fools = 1; + public static final Identifier APRIL_GAME_BEATEN = new Identifier(MOD_ID, "april_game_beaten"); + public static final Identifier APRIL_GAME_BEATEN_REVOKED = new Identifier("szar", "april_game_beaten_revoked"); public static final Identifier DRUNK_TYPE_PACKET = new Identifier(MOD_ID, "drunk_type"); public static final Identifier OPEN_DETONATOR_SCREEN = new Identifier(MOD_ID, "open_coord_screen"); public static final Identifier DETONATOR_INPUT = new Identifier(MOD_ID, "coord_input"); diff --git a/src/main/java/dev/tggamesyt/szar/mixin/PlayerAdvancementTrackerMixin.java b/src/main/java/dev/tggamesyt/szar/mixin/PlayerAdvancementTrackerMixin.java new file mode 100644 index 0000000..ab0895a --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/mixin/PlayerAdvancementTrackerMixin.java @@ -0,0 +1,56 @@ +package dev.tggamesyt.szar.mixin; + +import dev.tggamesyt.szar.Szar; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.advancement.Advancement; +import net.minecraft.advancement.PlayerAdvancementTracker; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; +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.CallbackInfoReturnable; + +import java.time.LocalDate; + +@Mixin(PlayerAdvancementTracker.class) +public class PlayerAdvancementTrackerMixin { + + @Shadow + private ServerPlayerEntity owner; + + @Inject(method = "grantCriterion", at = @At("RETURN")) + private void onCriterionGranted(Advancement advancement, String criterionName, CallbackInfoReturnable cir) { + if (!cir.getReturnValue()) return; + if (owner == null) return; + + if (advancement.getId().equals(new Identifier("end", "kill_dragon"))) { + if (!owner.getAdvancementTracker().getProgress(advancement).isDone()) return; + + LocalDate today = LocalDate.now(); + if (today.getMonthValue() != Szar.april || today.getDayOfMonth() != Szar.fools) return; + + Szar.grantAdvancement(owner, "april_game_beaten"); + return; + } + + if (!advancement.getId().equals(new Identifier(Szar.MOD_ID, "april_game_beaten"))) return; + if (!owner.getAdvancementTracker().getProgress(advancement).isDone()) return; + + ServerPlayNetworking.send(owner, Szar.APRIL_GAME_BEATEN, PacketByteBufs.empty()); + } + + @Inject(method = "revokeCriterion", at = @At("RETURN")) + private void onCriterionRevoked(Advancement advancement, String criterionName, CallbackInfoReturnable cir) { + if (!cir.getReturnValue()) return; + if (owner == null) return; + + if (!advancement.getId().equals(new Identifier(Szar.MOD_ID, "april_game_beaten"))) return; + // If it's no longer done after revoking, send the revoke packet + if (owner.getAdvancementTracker().getProgress(advancement).isDone()) return; + + ServerPlayNetworking.send(owner, Szar.APRIL_GAME_BEATEN_REVOKED, PacketByteBufs.empty()); + } +} \ No newline at end of file diff --git a/src/main/resources/assets/szar/lang/en_us.json b/src/main/resources/assets/szar/lang/en_us.json index 8a8800e..216c646 100644 --- a/src/main/resources/assets/szar/lang/en_us.json +++ b/src/main/resources/assets/szar/lang/en_us.json @@ -206,5 +206,8 @@ "block.szar.ender_obsidian": "Ender Obsidian", "block.szar.ender_ore": "Ender Ore", "item.szar.raw_ender": "Raw Ender", - "item.szar.ender_ingot": "Ender Ingot" + "item.szar.ender_ingot": "Ender Ingot", + + "advancement.szar.april_game_beaten.title": "We are so back", + "advancement.szar.april_game_beaten.description": "Beat the game on april 1st to flip the game back." } diff --git a/src/main/resources/data/szar/advancements/april_game_beaten.json b/src/main/resources/data/szar/advancements/april_game_beaten.json new file mode 100644 index 0000000..63b50ff --- /dev/null +++ b/src/main/resources/data/szar/advancements/april_game_beaten.json @@ -0,0 +1,18 @@ +{ + "parent": "szar:april", + "display": { + "icon": { + "item": "szar:april" + }, + "title": {"translate": "advancement.szar.april_game_beaten.title"}, + "description": {"translate": "advancement.szar.april_game_beaten.description"}, + "show_toast": true, + "announce_to_chat": false, + "frame": "challenge" + }, + "criteria": { + "used_item": { + "trigger": "minecraft:impossible" + } + } +} \ No newline at end of file diff --git a/src/main/resources/szar.mixins.json b/src/main/resources/szar.mixins.json index ee685ac..2947ff0 100644 --- a/src/main/resources/szar.mixins.json +++ b/src/main/resources/szar.mixins.json @@ -16,6 +16,7 @@ "NoClipMixin", "NoiseChunkGeneratorMixin", "PlaneBlockInteractionMixin", + "PlayerAdvancementTrackerMixin", "PlayerDropMixin", "PlayerEntityMixin", "PlayerInteractionMixin",