Public Access
1 parent
88af167f62
commit
08caa98c0b
10 files changed
+163
-4
No files matched your search
@@ -355,6 +355,11 @@ Age's selected terrain profile. End biome columns generate from End stone;
|
||||
Nether biome columns use Minecraft's Nether surface rules for netherrack,
|
||||
soul sand, basalt, and nylium instead of inheriting Overworld blocks.
|
||||
|
||||
Version 0.2.26.0 applies each Age's persisted celestial angle to the client
|
||||
sky. The sun, moon, and stars follow a plane rotated by the saved Legacy-style
|
||||
angle in normal gameplay and Immersive Portals previews, while vanilla
|
||||
dimensions retain their standard celestial path.
|
||||
|
||||
Version 0.2.14.0 restores the legacy Linking and Descriptive Book artwork for
|
||||
inventory items and gives each book its matching open-book texture when placed
|
||||
on a Book Stand. Return Linking Books created inside another Age also retain and
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ mod_name=Rivencraft
|
||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||
mod_license=LGPL-3.0-or-later
|
||||
# The mod version. Rivencraft uses the x.y.z.b policy documented in README.md.
|
||||
mod_version=0.2.25.1
|
||||
mod_version=0.2.26.0
|
||||
immersive_portals_version=6.0.7
|
||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||
# This should match the base package used for the mod sources.
|
||||
|
||||
@@ -9,6 +9,7 @@ import net.dnorberg.rivencraft.registry.ModBlocks;
|
||||
import net.dnorberg.rivencraft.registry.ModBlockEntities;
|
||||
import net.dnorberg.rivencraft.registry.ModBiomeSources;
|
||||
import net.dnorberg.rivencraft.event.BookStandConversionHandler;
|
||||
import net.dnorberg.rivencraft.event.AgeCelestialAngleSync;
|
||||
import net.dnorberg.rivencraft.network.ModNetworking;
|
||||
import net.dnorberg.rivencraft.config.RivencraftConfig;
|
||||
import net.dnorberg.rivencraft.config.RivencraftClientConfig;
|
||||
@@ -40,6 +41,8 @@ public final class Rivencraft {
|
||||
ModCreativeTabs.register(modEventBus);
|
||||
NeoForge.EVENT_BUS.addListener(BookStandConversionHandler::onRightClickBlock);
|
||||
NeoForge.EVENT_BUS.addListener(AgeWeatherService::onLevelTickPost);
|
||||
NeoForge.EVENT_BUS.addListener(AgeCelestialAngleSync::onPlayerLoggedIn);
|
||||
NeoForge.EVENT_BUS.addListener(AgeCelestialAngleSync::onPlayerChangedDimension);
|
||||
LOGGER.info("Initializing Rivencraft");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package net.dnorberg.rivencraft.client;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import net.dnorberg.rivencraft.network.AgeCelestialAnglePayload;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.neoforged.neoforge.network.handling.IPayloadContext;
|
||||
|
||||
/** Client cache used by both the active world and remote preview renderers. */
|
||||
public final class ClientAgeCelestialAngles {
|
||||
private static final Map<ResourceKey<Level>, Float> ANGLES = new ConcurrentHashMap<>();
|
||||
|
||||
private ClientAgeCelestialAngles() {
|
||||
}
|
||||
|
||||
public static void handle(AgeCelestialAnglePayload payload, IPayloadContext context) {
|
||||
ANGLES.put(payload.dimension(), payload.angle());
|
||||
}
|
||||
|
||||
public static float get(ResourceKey<Level> dimension) {
|
||||
return ANGLES.getOrDefault(dimension, 0.0F);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package net.dnorberg.rivencraft.event;
|
||||
|
||||
import net.dnorberg.rivencraft.book.AgeDefinition;
|
||||
import net.dnorberg.rivencraft.book.AgeDimensionService;
|
||||
import net.dnorberg.rivencraft.book.AgeRegistrySavedData;
|
||||
import net.dnorberg.rivencraft.network.AgeCelestialAnglePayload;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
|
||||
import net.neoforged.neoforge.network.PacketDistributor;
|
||||
import net.neoforged.neoforge.network.registration.NetworkRegistry;
|
||||
|
||||
/** Sends saved celestial angles when a client joins or enters an Age. */
|
||||
public final class AgeCelestialAngleSync {
|
||||
private AgeCelestialAngleSync() {
|
||||
}
|
||||
|
||||
public static void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) {
|
||||
if (!(event.getEntity() instanceof ServerPlayer player)) {
|
||||
return;
|
||||
}
|
||||
for (AgeDefinition age : AgeRegistrySavedData.get(player.serverLevel()).definitions()) {
|
||||
send(player, age);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onPlayerChangedDimension(PlayerEvent.PlayerChangedDimensionEvent event) {
|
||||
if (!(event.getEntity() instanceof ServerPlayer player)) {
|
||||
return;
|
||||
}
|
||||
AgeRegistrySavedData.get(player.serverLevel()).definitions().stream()
|
||||
.filter(age -> AgeDimensionService.dimensionKey(age).equals(event.getTo()))
|
||||
.findFirst()
|
||||
.ifPresent(age -> send(player, age));
|
||||
}
|
||||
|
||||
public static void send(ServerPlayer player, AgeDefinition age) {
|
||||
if (!NetworkRegistry.hasChannel(player.connection, AgeCelestialAnglePayload.TYPE.id())) {
|
||||
return;
|
||||
}
|
||||
PacketDistributor.sendToPlayer(player, new AgeCelestialAnglePayload(
|
||||
AgeDimensionService.dimensionKey(age), age.traits().celestialAngle()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package net.dnorberg.rivencraft.mixin.client;
|
||||
|
||||
import com.mojang.math.Axis;
|
||||
import net.dnorberg.rivencraft.client.ClientAgeCelestialAngles;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import org.joml.Quaternionf;
|
||||
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.Redirect;
|
||||
|
||||
/** Tilts the vanilla sun, moon, and star plane by each Age's saved angle. */
|
||||
@Mixin(LevelRenderer.class)
|
||||
public abstract class LevelRendererMixin {
|
||||
@Shadow
|
||||
private ClientLevel level;
|
||||
|
||||
@Redirect(
|
||||
method = "renderSky",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lcom/mojang/math/Axis;rotationDegrees(F)Lorg/joml/Quaternionf;",
|
||||
ordinal = 3
|
||||
)
|
||||
)
|
||||
private Quaternionf rivencraft$rotateCelestialPlane(Axis axis, float degrees) {
|
||||
float angle = ClientAgeCelestialAngles.get(level.dimension());
|
||||
return new Quaternionf(Axis.ZP.rotationDegrees(angle)).mul(axis.rotationDegrees(degrees));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package net.dnorberg.rivencraft.network;
|
||||
|
||||
import net.dnorberg.rivencraft.Rivencraft;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
/** Synchronizes an Age's saved celestial-plane rotation to clients. */
|
||||
public record AgeCelestialAnglePayload(ResourceKey<Level> dimension, float angle)
|
||||
implements CustomPacketPayload {
|
||||
public static final Type<AgeCelestialAnglePayload> TYPE = new Type<>(
|
||||
ResourceLocation.fromNamespaceAndPath(Rivencraft.MOD_ID, "age_celestial_angle")
|
||||
);
|
||||
public static final StreamCodec<RegistryFriendlyByteBuf, AgeCelestialAnglePayload> STREAM_CODEC =
|
||||
StreamCodec.of(
|
||||
(buffer, payload) -> {
|
||||
buffer.writeResourceKey(payload.dimension());
|
||||
buffer.writeFloat(payload.angle());
|
||||
},
|
||||
buffer -> new AgeCelestialAnglePayload(
|
||||
buffer.readResourceKey(Registries.DIMENSION), buffer.readFloat())
|
||||
);
|
||||
|
||||
@Override
|
||||
public Type<? extends CustomPacketPayload> type() {
|
||||
return TYPE;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import net.dnorberg.rivencraft.book.AgeDimensionService;
|
||||
import net.dnorberg.rivencraft.block.entity.BookStandBlockEntity;
|
||||
import net.dnorberg.rivencraft.client.ClientLinkPreviewHandler;
|
||||
import net.dnorberg.rivencraft.client.ClientBookInteractionHandler;
|
||||
import net.dnorberg.rivencraft.client.ClientAgeCelestialAngles;
|
||||
import net.dnorberg.rivencraft.event.AgeCelestialAngleSync;
|
||||
import net.dnorberg.rivencraft.item.DescriptiveBookItem;
|
||||
import net.dnorberg.rivencraft.item.LinkingBookItem;
|
||||
import net.dnorberg.rivencraft.registry.ModDataComponents;
|
||||
@@ -46,7 +48,7 @@ public final class ModNetworking {
|
||||
}
|
||||
|
||||
public static void register(RegisterPayloadHandlersEvent event) {
|
||||
PayloadRegistrar registrar = event.registrar("8");
|
||||
PayloadRegistrar registrar = event.registrar("9");
|
||||
registrar.playToServer(RequestDescriptiveBookScreenPayload.TYPE, RequestDescriptiveBookScreenPayload.STREAM_CODEC,
|
||||
ModNetworking::requestDescriptiveBookScreen);
|
||||
registrar.playToClient(OpenDescriptiveBookScreenPayload.TYPE, OpenDescriptiveBookScreenPayload.STREAM_CODEC,
|
||||
@@ -64,6 +66,8 @@ public final class ModNetworking {
|
||||
(payload, context) -> releaseLinkPreview(context));
|
||||
registrar.playToClient(LinkPreviewPayload.TYPE, LinkPreviewPayload.STREAM_CODEC,
|
||||
ClientLinkPreviewHandler::handle);
|
||||
registrar.playToClient(AgeCelestialAnglePayload.TYPE, AgeCelestialAnglePayload.STREAM_CODEC,
|
||||
ClientAgeCelestialAngles::handle);
|
||||
}
|
||||
|
||||
private static void requestDescriptiveBookScreen(RequestDescriptiveBookScreenPayload payload, IPayloadContext context) {
|
||||
@@ -222,6 +226,11 @@ public final class ModNetworking {
|
||||
return;
|
||||
}
|
||||
|
||||
AgeRegistrySavedData.get(player.serverLevel()).definitions().stream()
|
||||
.filter(age -> AgeDimensionService.dimensionKey(age).equals(target.location().dimension()))
|
||||
.findFirst()
|
||||
.ifPresent(age -> AgeCelestialAngleSync.send(player, age));
|
||||
|
||||
ServerLevel level = player.getServer().getLevel(target.location().dimension());
|
||||
if (level == null) {
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8",
|
||||
"package": "net.dnorberg.rivencraft.mixin",
|
||||
"compatibilityLevel": "JAVA_21",
|
||||
"client": [
|
||||
"client.LevelRendererMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
@@ -50,8 +50,8 @@ A spiritual successor and modern port of Mystcraft for Minecraft 1.21.1 on NeoFo
|
||||
'''
|
||||
|
||||
# The [[mixins]] block allows you to declare your mixin config to FML so that it gets loaded.
|
||||
#[[mixins]]
|
||||
#config="${mod_id}.mixins.json"
|
||||
[[mixins]]
|
||||
config="${mod_id}.mixins.json"
|
||||
|
||||
# The [[accessTransformers]] block allows you to declare where your AT file is.
|
||||
# If this block is omitted, a fallback attempt will be made to load an AT from META-INF/accesstransformer.cfg
|
||||
|
||||
Reference in new issue
Block a user