diff --git a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java index ab09e503..e7e15b4e 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java +++ b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java @@ -45,6 +45,7 @@ import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.client.color.world.BiomeColors; import net.minecraft.client.color.world.FoliageColors; +import net.minecraft.client.item.ClampedModelPredicateProvider; import net.minecraft.client.item.ModelPredicateProviderRegistry; import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.SpriteProvider; @@ -55,6 +56,8 @@ import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.model.json.ModelTransformationMode; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; import net.minecraft.fluid.Fluids; import net.minecraft.item.*; import net.minecraft.particle.ParticleEffect; @@ -116,7 +119,32 @@ public interface URenderers { PolearmRenderer.register(UItems.WOODEN_POLEARM, UItems.STONE_POLEARM, UItems.IRON_POLEARM, UItems.GOLDEN_POLEARM, UItems.DIAMOND_POLEARM, UItems.NETHERITE_POLEARM); ModelPredicateProviderRegistry.register(UItems.GEMSTONE, new Identifier("affinity"), (stack, world, entity, seed) -> EnchantableItem.isEnchanted(stack) ? EnchantableItem.getSpellKey(stack).getAffinity().getAlignment() : 0); ModelPredicateProviderRegistry.register(UItems.ROCK_CANDY, new Identifier("count"), (stack, world, entity, seed) -> stack.getCount() / (float)stack.getMaxCount()); - ModelPredicateProviderRegistry.register(Unicopia.id("zap_cycle"), (stack, world, entity, seed) -> UnicopiaClient.getInstance().getZapStageDelta()); + ModelPredicateProviderRegistry.register(Unicopia.id("zap_cycle"), new ClampedModelPredicateProvider() { + private double targetAngle; + private double lastAngle; + private long lastTick; + + @Override + public float unclampedCall(ItemStack stack, ClientWorld world, LivingEntity e, int var4) { + Entity entity = e != null ? e : stack.getHolder(); + if (entity == null) { + return 0; + } + if (world == null && entity.getWorld() instanceof ClientWorld) { + world = (ClientWorld)entity.getWorld(); + } + + if (world == null) { + return 0; + } + if (world.getTime() != lastTick) { + targetAngle = world.getDimension().natural() ? UnicopiaClient.getInstance().getZapAppleStage().getCycleProgress(world) : Math.random(); + lastAngle = lastAngle + (targetAngle - lastAngle) * 0.1; + } + + return (float)lastAngle; + } + }); ColorProviderRegistry.BLOCK.register(URenderers::getTintedBlockColor, TintedBlock.REGISTRY.stream().toArray(Block[]::new)); ColorProviderRegistry.ITEM.register((stack, i) -> getTintedBlockColor(Block.getBlockFromItem(stack.getItem()).getDefaultState(), null, null, i), TintedBlock.REGISTRY.stream().map(Block::asItem).filter(i -> i != Items.AIR).toArray(Item[]::new)); diff --git a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java index 9ea6a700..e7face1d 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java +++ b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java @@ -55,7 +55,6 @@ public class UnicopiaClient implements ClientModInitializer { public final Lerp skyAngle = new Lerp(0, true); private ZapAppleStageStore.Stage zapAppleStage = ZapAppleStageStore.Stage.HIBERNATING; - private long zapStageTime; public static Optional getCamera() { PlayerEntity player = MinecraftClient.getInstance().player; @@ -88,13 +87,12 @@ public class UnicopiaClient implements ClientModInitializer { instance = this; } - public void setZapAppleStage(ZapAppleStageStore.Stage stage, long delta) { + public void setZapAppleStage(ZapAppleStageStore.Stage stage) { zapAppleStage = stage; - zapStageTime = delta; } - public float getZapStageDelta() { - return zapAppleStage.getCycleProgress(zapStageTime); + public ZapAppleStageStore.Stage getZapAppleStage() { + return zapAppleStage; } public float getSkyAngleDelta(float tickDelta) { @@ -148,8 +146,6 @@ public class UnicopiaClient implements ClientModInitializer { world.setRainGradient(gradient); world.setThunderGradient(gradient); } - - zapStageTime++; } private Float getTargetRainGradient(ClientWorld world, BlockPos pos, float tickDelta) { diff --git a/src/main/java/com/minelittlepony/unicopia/network/Channel.java b/src/main/java/com/minelittlepony/unicopia/network/Channel.java index 67f56df1..d1a6bc19 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/Channel.java +++ b/src/main/java/com/minelittlepony/unicopia/network/Channel.java @@ -55,7 +55,7 @@ public interface Channel { sender.sendPacket(SERVER_RESOURCES.id(), new MsgServerResources().toBuffer()); sender.sendPacket(SERVER_SKY_ANGLE.id(), new MsgSkyAngle(UnicopiaWorldProperties.forWorld(handler.getPlayer().getServerWorld()).getTangentalSkyAngle()).toBuffer()); ZapAppleStageStore store = ZapAppleStageStore.get(handler.player.getServerWorld()); - sender.sendPacket(SERVER_ZAP_STAGE.id(), new MsgZapAppleStage(store.getStage(), store.getStageDelta()).toBuffer()); + sender.sendPacket(SERVER_ZAP_STAGE.id(), new MsgZapAppleStage(store.getStage()).toBuffer()); }); } } diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgZapAppleStage.java b/src/main/java/com/minelittlepony/unicopia/network/MsgZapAppleStage.java index 10bad6c1..f90728b3 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/MsgZapAppleStage.java +++ b/src/main/java/com/minelittlepony/unicopia/network/MsgZapAppleStage.java @@ -7,17 +7,15 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.PacketByteBuf; public record MsgZapAppleStage ( - ZapAppleStageStore.Stage stage, - long delta + ZapAppleStageStore.Stage stage ) implements Packet { public MsgZapAppleStage(PacketByteBuf buffer) { - this(buffer.readEnumConstant(ZapAppleStageStore.Stage.class), buffer.readLong()); + this(buffer.readEnumConstant(ZapAppleStageStore.Stage.class)); } @Override public void toBuffer(PacketByteBuf buffer) { buffer.writeEnumConstant(stage); - buffer.writeLong(delta); } } diff --git a/src/main/java/com/minelittlepony/unicopia/network/handler/ClientNetworkHandlerImpl.java b/src/main/java/com/minelittlepony/unicopia/network/handler/ClientNetworkHandlerImpl.java index 6082dca9..d9b9e07f 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/handler/ClientNetworkHandlerImpl.java +++ b/src/main/java/com/minelittlepony/unicopia/network/handler/ClientNetworkHandlerImpl.java @@ -95,7 +95,7 @@ public class ClientNetworkHandlerImpl { } private void handleZapStage(PlayerEntity sender, MsgZapAppleStage packet) { - UnicopiaClient.getInstance().setZapAppleStage(packet.stage(), packet.delta()); + UnicopiaClient.getInstance().setZapAppleStage(packet.stage()); } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/ZapAppleStageStore.java b/src/main/java/com/minelittlepony/unicopia/server/world/ZapAppleStageStore.java index cb27244f..a30fc4c6 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/ZapAppleStageStore.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/ZapAppleStageStore.java @@ -3,12 +3,15 @@ package com.minelittlepony.unicopia.server.world; import java.util.Locale; import java.util.stream.StreamSupport; +import org.jetbrains.annotations.Nullable; + import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.network.Channel; import com.minelittlepony.unicopia.network.MsgZapAppleStage; import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect; import com.minelittlepony.unicopia.particle.ParticleUtils; +import com.minelittlepony.unicopia.util.MeteorlogicalUtil; import com.minelittlepony.unicopia.util.Tickable; import net.minecraft.entity.EntityType; @@ -37,17 +40,15 @@ public class ZapAppleStageStore extends PersistentState implements Tickable { private final World world; private Stage lastStage = Stage.HIBERNATING; - private long stageDelta; - private long lastTime; private boolean stageChanged; private boolean playedMoonEffect; private int nextLightningEvent = 1200; + private float prevSkyAngle; ZapAppleStageStore(World world, NbtCompound compound) { this(world); lastStage = Stage.VALUES[Math.max(0, compound.getInt("stage")) % Stage.VALUES.length]; - stageDelta = compound.getLong("stageDelta"); stageChanged = compound.getBoolean("stageChanged"); playedMoonEffect = compound.getBoolean("playedMoonEffect"); nextLightningEvent = compound.getInt("nextLightningEvent"); @@ -59,41 +60,36 @@ public class ZapAppleStageStore extends PersistentState implements Tickable { @Override public void tick() { - if (!world.isDay()) { + float skyAngle = MeteorlogicalUtil.getSkyAngle(world); + + if (skyAngle > MeteorlogicalUtil.SUNSET) { if (nextLightningEvent > 0) { nextLightningEvent--; + markDirty(); } - if (!stageChanged && (lastStage != Stage.HIBERNATING || (world.getMoonPhase() == 0))) { + if (!stageChanged && MathHelper.approximatelyEquals(skyAngle, MeteorlogicalUtil.MIDNIGHT) || ( + MeteorlogicalUtil.isBetween(skyAngle, MeteorlogicalUtil.MIDNIGHT, MeteorlogicalUtil.MOONSET) + && MeteorlogicalUtil.isBetween(prevSkyAngle, MeteorlogicalUtil.SUNSET, MeteorlogicalUtil.MIDNIGHT) + )) { stageChanged = true; - lastStage = lastStage.getNext(); - stageDelta = 0; - playedMoonEffect = false; - sendUpdate(); + if (lastStage != Stage.HIBERNATING || world.getMoonPhase() == 0) { + lastStage = lastStage.getNext(); + playedMoonEffect = false; + markDirty(); + sendUpdate(); + } } } else if (stageChanged) { stageChanged = false; + markDirty(); } - long timeOfDay = world.getTimeOfDay(); - if (stageDelta != 0 && (timeOfDay < lastTime || timeOfDay > lastTime + 10)) { - long timeDifference = timeOfDay - lastTime; - Unicopia.LOGGER.info("Times a changing {}!", timeDifference); - while (timeDifference < 0) { - timeDifference += DAY_LENGTH; - } - stageDelta += timeDifference; - sendUpdate(); - } - lastTime = timeOfDay; - - - stageDelta++; - markDirty(); + prevSkyAngle = skyAngle; } protected void sendUpdate() { - Channel.SERVER_ZAP_STAGE.sendToAllPlayers(new MsgZapAppleStage(getStage(), stageDelta), world); + Channel.SERVER_ZAP_STAGE.sendToAllPlayers(new MsgZapAppleStage(getStage()), world); } public void playMoonEffect(BlockPos pos) { @@ -137,22 +133,9 @@ public class ZapAppleStageStore extends PersistentState implements Tickable { return lastStage; } - public long getStageDelta() { - return stageDelta; - } - - public float getStageProgress() { - return getStage().getStageProgress(getStageDelta()); - } - - public float getCycleProgress() { - return getStage().getCycleProgress(getStageDelta()); - } - @Override public NbtCompound writeNbt(NbtCompound compound) { compound.putInt("stage", lastStage.ordinal()); - compound.putLong("stageDelta", stageDelta); compound.putBoolean("stageChanged", stageChanged); compound.putBoolean("playedMoonEffect", playedMoonEffect); compound.putInt("nextLightningEvent", nextLightningEvent); @@ -160,19 +143,16 @@ public class ZapAppleStageStore extends PersistentState implements Tickable { } public enum Stage implements StringIdentifiable { - HIBERNATING(MOON_PHASES * DAY_LENGTH), - GREENING(DAY_LENGTH), - FLOWERING(DAY_LENGTH), - FRUITING(DAY_LENGTH), - RIPE(DAY_LENGTH); + HIBERNATING, + GREENING, + FLOWERING, + FRUITING, + RIPE; static final Stage[] VALUES = values(); + static final float MAX = VALUES.length; - private final long duration; - - Stage(long duration) { - this.duration = duration; - } + private final float ordinal = ordinal(); public Stage getNext() { return byId((ordinal() + 1) % VALUES.length); @@ -182,13 +162,21 @@ public class ZapAppleStageStore extends PersistentState implements Tickable { return byId(((ordinal() - 1) + VALUES.length) % VALUES.length); } - public float getStageProgress(long time) { - return (time % duration) / (float)duration; + public float getStageProgress(@Nullable World world) { + if (world == null) { + return 0; + } + float skyAngle = MeteorlogicalUtil.getSkyAngle(world); + float dayProgress = ((skyAngle + 1.5F) % 3F) / 3F; + if (this == HIBERNATING) { + return (world.getMoonPhase() + dayProgress) / MOON_PHASES; + } + + return dayProgress; } - public float getCycleProgress(long time) { - float ordinal = ordinal(); - return MathHelper.lerp(getStageProgress(time), ordinal, ordinal + 1) / 5F; + public float getCycleProgress(@Nullable World world) { + return MathHelper.lerp(getStageProgress(world), ordinal, ordinal + 1) / MAX; } public static Stage byId(int id) { diff --git a/src/main/java/com/minelittlepony/unicopia/util/MeteorlogicalUtil.java b/src/main/java/com/minelittlepony/unicopia/util/MeteorlogicalUtil.java index f4010e20..ad424cd9 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/MeteorlogicalUtil.java +++ b/src/main/java/com/minelittlepony/unicopia/util/MeteorlogicalUtil.java @@ -12,6 +12,15 @@ import net.minecraft.world.LightType; import net.minecraft.world.World; public interface MeteorlogicalUtil { + float SUNRISE = 0; + float NOON = 0.5F; + float SUNSET = 1; + float MIDNIGHT = 1.5F; + float MOONSET = 2; + + static boolean isBetween(float skyAngle, float start, float end) { + return skyAngle >= start && skyAngle <= end; + } static boolean isLookingIntoSun(World world, Entity entity) { @@ -52,7 +61,7 @@ public interface MeteorlogicalUtil { static float getSunIntensity(World world) { float skyAngle = getSkyAngle(world); - if (skyAngle > 1) { + if (skyAngle > SUNSET) { return 0; } @@ -69,7 +78,21 @@ public interface MeteorlogicalUtil { return intensity; } - // we translate sun angle to a scale of 0-1 (0=sunrise, 1=sunset, >1 nighttime) + /** + * Gets the sun angle on a scale of 0-2 where 0=sunrise, 1=sunset, and >1 is night + * + * 0 = sunrisde + * 0-0.5 = morning + * 0.5 = noon + * 0.5-1 = evening + * 1 = sunset + * 1-1.5 = night + * 1.5 = midnight + * 1.5-0 = night + * + * @param world + * @return The sun angle + */ static float getSkyAngle(World world) { return ((world.getSkyAngle(1) + 0.25F) % 1F) * 2; }