Properly implement changing sun and stars position with the unicorn amulet

This commit is contained in:
Sollace 2023-08-29 21:27:43 +01:00
parent fcd6701961
commit aaecdf7cbf
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
16 changed files with 207 additions and 80 deletions

View file

@ -33,7 +33,7 @@ public class TimeChangeAbility implements Ability<Hit> {
@Override
public double getCostEstimate(Pony player) {
return 400;
return 2;
}
@Override
@ -43,6 +43,10 @@ public class TimeChangeAbility implements Ability<Hit> {
@Override
public Optional<Hit> prepare(Pony player) {
if (!player.subtractEnergyCost(0)) {
return Optional.empty();
}
return Hit.INSTANCE;
}

View file

@ -4,11 +4,10 @@ import com.minelittlepony.unicopia.ability.Abilities;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.effect.*;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.server.world.UnicopiaWorldProperties;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
/**
* Internal.
@ -17,41 +16,52 @@ import net.minecraft.util.math.Vec3d;
*/
public class TimeControlAbilitySpell extends AbstractSpell {
private Vec3d prevRotation = null;
private boolean initilized;
private long timeOffset;
private float angleOffset;
public TimeControlAbilitySpell(CustomisedSpellType<?> type) {
super(type);
setHidden(true);
}
@Override
public boolean tick(Caster<?> source, Situation situation) {
if (situation != Situation.BODY) {
return false;
}
if (!(source instanceof Pony pony) || !Abilities.TIME.canUse(pony.getCompositeRace())) {
if (situation != Situation.BODY || !(source instanceof Pony pony) || !Abilities.TIME.canUse(pony.getCompositeRace())) {
return false;
}
if (source.asWorld() instanceof ServerWorld sw) {
float yaw = MathHelper.wrapDegrees(source.asEntity().getHeadYaw());
float pitch = MathHelper.wrapDegrees(source.asEntity().getPitch(1)) / 90F;
float yaw = -(source.asEntity().getHeadYaw() + 90);
float pitch = -(source.asEntity().getPitch(1) / 90F);
if (yaw > 0) {
pitch += 90;
long time = (long)(pitch * 6000);
// sunrise(0) - midday(1) - sunset(2) - midnight(3)
if (!initilized) {
initilized = true;
timeOffset = sw.getTimeOfDay() - time;
angleOffset = UnicopiaWorldProperties.forWorld(sw).getTangentalSkyAngle() - yaw;
}
Vec3d rotation = new Vec3d(pitch, 0, 1);
if (prevRotation != null) {
pitch = (float)MathHelper.lerp(0.05, pitch, rotation.x);
sw.setTimeOfDay((long)(pitch * 6000));
if (angleOffset > 90 && angleOffset < 270) {
time *= -1;
}
prevRotation = new Vec3d(pitch, 0, 1);
time += timeOffset;
if (time < 0) {
time += 24000;
}
time %= 24000;
sw.setTimeOfDay(time);
sw.getServer().sendTimeUpdatePackets();
UnicopiaWorldProperties.forWorld(sw).setTangentalSkyAngle(angleOffset + yaw);
}
return source.subtractEnergyCost(2);
@ -60,20 +70,16 @@ public class TimeControlAbilitySpell extends AbstractSpell {
@Override
public void toNBT(NbtCompound compound) {
super.toNBT(compound);
compound.putBoolean("initilized", initilized);
compound.putLong("timeOffset", timeOffset);
compound.putFloat("angleOffset", angleOffset);
}
@Override
public void fromNBT(NbtCompound compound) {
super.fromNBT(compound);
}
@Override
public boolean isHidden() {
return true;
}
@Override
public void setHidden(boolean hidden) {
initilized = compound.getBoolean("initilized");
timeOffset = compound.getLong("timeOffset");
angleOffset = compound.getFloat("angleOffset");
}
}

View file

@ -38,10 +38,19 @@ import net.minecraft.util.math.BlockPos;
public class UnicopiaClient implements ClientModInitializer {
private static UnicopiaClient instance;
public static UnicopiaClient getInstance() {
return instance;
}
@Nullable
private Float originalRainGradient;
private final Lerp rainGradient = new Lerp(0);
public final Lerp tangentalSkyAngle = new Lerp(0, true);
public final Lerp skyAngle = new Lerp(0, true);
public static Optional<PlayerCamera> getCamera() {
PlayerEntity player = MinecraftClient.getInstance().player;
@ -69,6 +78,19 @@ public class UnicopiaClient implements ClientModInitializer {
return 0.6F;
}
public UnicopiaClient() {
instance = this;
}
public float getSkyAngleDelta(float tickDelta) {
if (MinecraftClient.getInstance().world == null) {
return 0;
}
float skyAngle = MinecraftClient.getInstance().world.getSkyAngle(tickDelta);
this.skyAngle.update(skyAngle, 200);
return this.skyAngle.getValue() - skyAngle;
}
@Override
public void onInitializeClient() {
InteractionManager.INSTANCE = new ClientInteractionManager();

View file

@ -8,7 +8,7 @@ import com.minelittlepony.common.client.gui.element.*;
import com.minelittlepony.common.client.gui.style.Style;
import com.minelittlepony.unicopia.*;
import com.minelittlepony.unicopia.client.minelittlepony.MineLPDelegate;
import com.minelittlepony.unicopia.server.world.WorldTribeManager;
import com.minelittlepony.unicopia.server.world.UnicopiaWorldProperties;
import com.minelittlepony.unicopia.util.RegistryIndexer;
import net.fabricmc.loader.api.FabricLoader;
@ -81,7 +81,7 @@ public class SettingsScreen extends GameGui {
row += 20;
content.addButton(new Label(LEFT, row)).getStyle().setText("unicopia.options.world");
WorldTribeManager tribes = WorldTribeManager.forWorld((ServerWorld)server.getPlayerManager().getPlayer(MinecraftClient.getInstance().player.getUuid()).getWorld());
UnicopiaWorldProperties tribes = UnicopiaWorldProperties.forWorld((ServerWorld)server.getPlayerManager().getPlayer(MinecraftClient.getInstance().player.getUuid()).getWorld());
content.addButton(new Slider(LEFT, row += 20, 0, races.size(), races.indexOf(tribes.getDefaultRace())))
.onChange(races.createSetter(tribes::setDefaultRace))

View file

@ -1,7 +1,7 @@
package com.minelittlepony.unicopia.command;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.server.world.WorldTribeManager;
import com.minelittlepony.unicopia.server.world.UnicopiaWorldProperties;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@ -26,14 +26,14 @@ class WorldTribeCommand {
static int get(ServerCommandSource source) throws CommandSyntaxException {
source.sendFeedback(() -> {
WorldTribeManager manager = WorldTribeManager.forWorld(source.getWorld());
UnicopiaWorldProperties manager = UnicopiaWorldProperties.forWorld(source.getWorld());
return Text.translatable("commands.worldtribe.success.get", manager.getDefaultRace().getDisplayName());
}, true);
return 0;
}
static int set(ServerCommandSource source, Race race) {
WorldTribeManager manager = WorldTribeManager.forWorld(source.getWorld());
UnicopiaWorldProperties manager = UnicopiaWorldProperties.forWorld(source.getWorld());
manager.setDefaultRace(race);
source.sendFeedback(() -> Text.translatable("commands.worldtribe.success.set", race.getDisplayName()), true);

View file

@ -16,7 +16,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.minelittlepony.unicopia.entity.collision.EntityCollisions;
import com.minelittlepony.unicopia.entity.duck.RotatedView;
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
@ -72,3 +71,4 @@ abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source
recurseCount = Math.max(0, recurseCount - 1);
}
}

View file

@ -2,6 +2,8 @@ package com.minelittlepony.unicopia.mixin.client;
import java.util.SortedSet;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -12,17 +14,25 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.minelittlepony.unicopia.client.ClientBlockDestructionManager;
import com.minelittlepony.unicopia.client.UnicopiaClient;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import net.minecraft.client.render.BlockBreakingInfo;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.resource.SynchronousResourceReloader;
import net.minecraft.util.math.RotationAxis;
@Mixin(value = WorldRenderer.class, priority = 1001)
abstract class MixinWorldRenderer implements SynchronousResourceReloader, AutoCloseable, ClientBlockDestructionManager.Source {
private final ClientBlockDestructionManager destructions = new ClientBlockDestructionManager();
@Nullable
@Shadow
private ClientWorld world;
@Shadow
private @Final Long2ObjectMap<SortedSet<BlockBreakingInfo>> blockBreakingProgressions;
@ -53,4 +63,21 @@ abstract class MixinWorldRenderer implements SynchronousResourceReloader, AutoCl
private void onTick(CallbackInfo info) {
destructions.tick(blockBreakingProgressions);
}
@Inject(method = "renderSky("
+ "Lnet/minecraft/client/util/math/MatrixStack;"
+ "Lorg/joml/Matrix4f;"
+ "F"
+ "Lnet/minecraft/client/render/Camera;"
+ "Z"
+ "Ljava/lang/Runnable;"
+ ")V", at = @At(
value = "INVOKE",
target = "net/minecraft/client/world/ClientWorld.getSkyAngle(F)F",
ordinal = 1
))
private void onRenderSky(MatrixStack matrices, Matrix4f projectionMatrix, float tickDelta, Camera camera, boolean thickFog, Runnable fogCallback, CallbackInfo info) {
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(UnicopiaClient.getInstance().getSkyAngleDelta(tickDelta)));
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(UnicopiaClient.getInstance().tangentalSkyAngle.getValue()));
}
}

View file

@ -2,7 +2,7 @@ package com.minelittlepony.unicopia.network;
import com.minelittlepony.unicopia.*;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.server.world.WorldTribeManager;
import com.minelittlepony.unicopia.server.world.UnicopiaWorldProperties;
import com.sollace.fabwork.api.packets.*;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
@ -30,12 +30,13 @@ public interface Channel {
S2CPacketType<MsgOtherPlayerCapabilities> SERVER_OTHER_PLAYER_CAPABILITIES = SimpleNetworking.serverToClient(Unicopia.id("other_player_capabilities"), MsgOtherPlayerCapabilities::new);
S2CPacketType<MsgPlayerAnimationChange> SERVER_PLAYER_ANIMATION_CHANGE = SimpleNetworking.serverToClient(Unicopia.id("other_player_animation_change"), MsgPlayerAnimationChange::new);
S2CPacketType<MsgSkyAngle> SERVER_SKY_ANGLE = SimpleNetworking.serverToClient(Unicopia.id("sky_angle"), MsgSkyAngle::new);
static void bootstrap() {
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
Pony pony = Pony.of(handler.player);
if (pony.getActualSpecies() == Race.UNSET) {
Race race = WorldTribeManager.forWorld(handler.player.getServerWorld()).getDefaultRace();
Race race = UnicopiaWorldProperties.forWorld(handler.player.getServerWorld()).getDefaultRace();
if (!race.isPermitted(handler.player)) {
race = Race.UNSET;
}
@ -47,6 +48,7 @@ public interface Channel {
}
}
sender.sendPacket(SERVER_RESOURCES_SEND.id(), new MsgServerResources().toBuffer());
sender.sendPacket(SERVER_SKY_ANGLE.id(), new MsgSkyAngle(UnicopiaWorldProperties.forWorld(handler.getPlayer().getServerWorld()).getTangentalSkyAngle()).toBuffer());
});
}
}

View file

@ -3,7 +3,7 @@ package com.minelittlepony.unicopia.network;
import com.minelittlepony.unicopia.*;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.server.world.UGameRules;
import com.minelittlepony.unicopia.server.world.WorldTribeManager;
import com.minelittlepony.unicopia.server.world.UnicopiaWorldProperties;
import com.sollace.fabwork.api.packets.HandledPacket;
import net.minecraft.network.PacketByteBuf;
@ -36,7 +36,7 @@ public record MsgRequestSpeciesChange (
Pony player = Pony.of(sender);
if (force || player.getActualSpecies().isUnset()) {
player.setSpecies(newRace.isPermitted(sender) ? newRace : WorldTribeManager.forWorld((ServerWorld)player.asWorld()).getDefaultRace());
player.setSpecies(newRace.isPermitted(sender) ? newRace : UnicopiaWorldProperties.forWorld((ServerWorld)player.asWorld()).getDefaultRace());
if (force) {
if (sender.getWorld().getGameRules().getBoolean(UGameRules.ANNOUNCE_TRIBE_JOINS)) {

View file

@ -0,0 +1,20 @@
package com.minelittlepony.unicopia.network;
import com.sollace.fabwork.api.packets.Packet;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.PacketByteBuf;
public record MsgSkyAngle (
float tangentalSkyAngle
) implements Packet<PlayerEntity> {
public MsgSkyAngle(PacketByteBuf buffer) {
this(buffer.readFloat());
}
@Override
public void toBuffer(PacketByteBuf buffer) {
buffer.writeFloat(tangentalSkyAngle());
}
}

View file

@ -10,13 +10,13 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.client.ClientBlockDestructionManager;
import com.minelittlepony.unicopia.client.DiscoveryToast;
import com.minelittlepony.unicopia.client.UnicopiaClient;
import com.minelittlepony.unicopia.client.gui.TribeSelectionScreen;
import com.minelittlepony.unicopia.client.gui.spellbook.ClientChapters;
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Chapter;
import com.minelittlepony.unicopia.entity.UEntities;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.network.*;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
@ -33,6 +33,7 @@ public class ClientNetworkHandlerImpl {
Channel.CANCEL_PLAYER_ABILITY.receiver().addPersistentListener(this::handleCancelAbility);
Channel.UNLOCK_TRAITS.receiver().addPersistentListener(this::handleUnlockTraits);
Channel.SERVER_RESOURCES_SEND.receiver().addPersistentListener(this::handleServerResources);
Channel.SERVER_SKY_ANGLE.receiver().addPersistentListener(this::handleSkyAngle);
}
private void handleTribeScreen(PlayerEntity sender, MsgTribeSelect packet) {
@ -82,6 +83,10 @@ public class ClientNetworkHandlerImpl {
}
}
private void handleSkyAngle(PlayerEntity sender, MsgSkyAngle packet) {
UnicopiaClient.getInstance().tangentalSkyAngle.update(packet.tangentalSkyAngle(), 200);
}
@SuppressWarnings("unchecked")
private void handleServerResources(PlayerEntity sender, MsgServerResources packet) {
SpellTraits.load(packet.traits());

View file

@ -0,0 +1,62 @@
package com.minelittlepony.unicopia.server.world;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.network.Channel;
import com.minelittlepony.unicopia.network.MsgSkyAngle;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.PersistentState;
public class UnicopiaWorldProperties extends PersistentState {
private final ServerWorld world;
private Race defaultRace = Race.UNSET;
private float tangentalSkyAngle;
public UnicopiaWorldProperties(ServerWorld world) {
this.world = world;
}
public UnicopiaWorldProperties(ServerWorld world, NbtCompound tag) {
this(world);
defaultRace = Race.fromName(tag.getString("defaultRace"), Race.HUMAN);
tangentalSkyAngle = tag.getFloat("tangentalSkyAngle");
}
public Race getDefaultRace() {
return defaultRace;
}
public Race setDefaultRace(Race race) {
defaultRace = race;
markDirty();
return defaultRace;
}
public float getTangentalSkyAngle() {
return tangentalSkyAngle;
}
public void setTangentalSkyAngle(float angle) {
tangentalSkyAngle = MathHelper.wrapDegrees(angle);
markDirty();
Channel.SERVER_SKY_ANGLE.sendToAllPlayers(new MsgSkyAngle(tangentalSkyAngle), world);
}
@Override
public NbtCompound writeNbt(NbtCompound tag) {
tag.putString("defaultRace", Race.REGISTRY.getId(defaultRace).toString());
tag.putFloat("tangentalSkyAngle", tangentalSkyAngle);
return tag;
}
public static UnicopiaWorldProperties forWorld(ServerWorld world) {
return world.getPersistentStateManager().getOrCreate(
nbt -> new UnicopiaWorldProperties(world, nbt),
() -> new UnicopiaWorldProperties(world), "unicopia_tribes"
);
}
}

View file

@ -1,38 +0,0 @@
package com.minelittlepony.unicopia.server.world;
import com.minelittlepony.unicopia.Race;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.PersistentState;
public class WorldTribeManager extends PersistentState {
private Race defaultRace = Race.UNSET;
public WorldTribeManager() {}
public WorldTribeManager(NbtCompound nbt) {
defaultRace = Race.fromName(nbt.getString("defaultRace"), Race.HUMAN);
}
public Race getDefaultRace() {
return defaultRace;
}
public Race setDefaultRace(Race race) {
defaultRace = race;
markDirty();
return defaultRace;
}
@Override
public NbtCompound writeNbt(NbtCompound tag) {
tag.putString("defaultRace", Race.REGISTRY.getId(defaultRace).toString());
return tag;
}
public static WorldTribeManager forWorld(ServerWorld world) {
return world.getPersistentStateManager().getOrCreate(WorldTribeManager::new, WorldTribeManager::new, "unicopia_tribes");
}
}

View file

@ -11,9 +11,15 @@ public class Lerp {
private float end;
private boolean finished = true;
private final boolean angle;
public Lerp(float initial) {
this(initial, false);
}
public Lerp(float initial, boolean angle) {
end = initial;
this.angle = angle;
}
public boolean update(float newTarget, long changeDuration) {
@ -34,9 +40,16 @@ public class Lerp {
}
float delta = getDelta();
finished = delta >= 1F;
if (angle) {
return MathHelper.lerpAngleDegrees(delta, start, end);
}
return MathHelper.lerp(delta, start, end);
}
public float getTarget() {
return end;
}
public boolean isFinished() {
return finished;
}

View file

@ -1,5 +1,7 @@
package com.minelittlepony.unicopia.util;
import com.minelittlepony.unicopia.client.UnicopiaClient;
import net.minecraft.entity.Entity;
import net.minecraft.util.hit.HitResult.Type;
import net.minecraft.util.math.BlockPos;
@ -30,6 +32,7 @@ public interface MeteorlogicalUtil {
playerAngle = 1 - playerAngle;
}
playerYaw += UnicopiaClient.getInstance().tangentalSkyAngle.getValue();
playerYaw = Math.abs(playerYaw);
// check if day,

View file

@ -376,6 +376,7 @@
"ability.unicopia.toggle_flight": "Take-off/Land",
"ability.unicopia.hang": "Cling to Ceiling",
"ability.unicopia.eee": "Screech",
"ability.unicopia.time_control": "Control Sun / Moon",
"ability.unicopia.feed": "Siphon Love",
"ability.unicopia.capture_cloud": "Bust Cloud",
"ability.unicopia.disguise": "Change Form",