Public Access
This commit is contained in:
1 parent
3ad518232a
commit
73051c5ba6
7 files changed
+133
-22
No files matched your search
@@ -329,6 +329,12 @@ Age-seeded biomes in the legacy diagonal-checkerboard layout. Each square is
|
||||
uses Minecraft's serializable checkerboard biome source so the layout remains
|
||||
stable across server reloads.
|
||||
|
||||
Version 0.2.22.1 includes the server-owned Age traits in the validated
|
||||
Descriptive Book screen response and displays the terrain, biome distribution,
|
||||
lighting, weather, day length, celestial angle, and celestial phase on the
|
||||
book's right-hand description page. This works for held books and Book Stands
|
||||
without copying mutable Age-generation data onto the item.
|
||||
|
||||
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.22.0
|
||||
mod_version=0.2.22.1
|
||||
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.
|
||||
|
||||
@@ -92,8 +92,8 @@ public final class ClientBookInteractionHandler {
|
||||
return;
|
||||
}
|
||||
minecraft.setScreen(payload.fromStand()
|
||||
? new DescriptiveBookScreen(payload.source().pos(), payload.book())
|
||||
: new DescriptiveBookScreen(hand, payload.book()));
|
||||
? new DescriptiveBookScreen(payload.source().pos(), payload.book(), payload.traits())
|
||||
: new DescriptiveBookScreen(hand, payload.book(), payload.traits()));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.dnorberg.rivencraft.client.screen;
|
||||
|
||||
import net.dnorberg.rivencraft.book.AgeReference;
|
||||
import net.dnorberg.rivencraft.book.AgeTraits;
|
||||
import net.dnorberg.rivencraft.client.ClientBookExploreOverlay;
|
||||
import net.dnorberg.rivencraft.network.UseDescriptiveBookPayload;
|
||||
import net.dnorberg.rivencraft.network.BindDescriptiveBookPayload;
|
||||
@@ -22,6 +23,9 @@ import net.minecraft.util.FormattedCharSequence;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.neoforged.neoforge.network.PacketDistributor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public final class DescriptiveBookScreen extends Screen implements ExplorableBookScreen {
|
||||
private static final int BOOK_TEXT_COLOR = 0xFF3B281B;
|
||||
@@ -40,6 +44,7 @@ public final class DescriptiveBookScreen extends Screen implements ExplorableBoo
|
||||
|
||||
private final AgeReference age;
|
||||
private final ResourceLocation generationProfile;
|
||||
private final AgeTraits traits;
|
||||
private final InteractionHand hand;
|
||||
private final BlockPos bookStandPos;
|
||||
private DestinationPreviewRenderer preview;
|
||||
@@ -47,18 +52,20 @@ public final class DescriptiveBookScreen extends Screen implements ExplorableBoo
|
||||
private Button exploreButton;
|
||||
private boolean movingToExploreOverlay;
|
||||
|
||||
public DescriptiveBookScreen(InteractionHand hand, ItemStack book) {
|
||||
public DescriptiveBookScreen(InteractionHand hand, ItemStack book, @Nullable AgeTraits traits) {
|
||||
super(book.getHoverName());
|
||||
age = book.get(ModDataComponents.AGE_REFERENCE.get());
|
||||
generationProfile = book.get(ModDataComponents.AGE_GENERATION_PROFILE.get());
|
||||
this.traits = traits;
|
||||
this.hand = hand;
|
||||
bookStandPos = null;
|
||||
}
|
||||
|
||||
public DescriptiveBookScreen(BlockPos bookStandPos, ItemStack book) {
|
||||
public DescriptiveBookScreen(BlockPos bookStandPos, ItemStack book, @Nullable AgeTraits traits) {
|
||||
super(book.getHoverName());
|
||||
age = book.get(ModDataComponents.AGE_REFERENCE.get());
|
||||
generationProfile = book.get(ModDataComponents.AGE_GENERATION_PROFILE.get());
|
||||
this.traits = traits;
|
||||
hand = InteractionHand.MAIN_HAND;
|
||||
this.bookStandPos = bookStandPos.immutable();
|
||||
}
|
||||
@@ -138,14 +145,34 @@ public final class DescriptiveBookScreen extends Screen implements ExplorableBoo
|
||||
left + 177, top + 45, 124);
|
||||
} else {
|
||||
preview.render(graphics, left + LINK_PANEL_X, top + LINK_PANEL_Y, LINK_PANEL_WIDTH, LINK_PANEL_HEIGHT, partialTick);
|
||||
drawWrappedWithoutShadow(graphics, Component.literal(age.name()), left + 177, top + 43, 124);
|
||||
int detailsY = drawWrappedWithoutShadow(
|
||||
graphics, Component.literal(age.name()), left + 177, top + 43, 124) + 3;
|
||||
detailsY = Math.max(detailsY, top + 72);
|
||||
if (generationProfile != null) {
|
||||
Component profileName = generationProfile.getNamespace().equals("rivencraft")
|
||||
? Component.translatable("generator.rivencraft." + generationProfile.getPath())
|
||||
: Component.literal(generationProfile.toString());
|
||||
drawWrappedWithoutShadow(graphics,
|
||||
detailsY = drawWrappedWithoutShadow(graphics,
|
||||
Component.translatable("screen.rivencraft.age.generator", profileName),
|
||||
left + 177, top + 72, 124);
|
||||
left + 177, detailsY, 124) + 2;
|
||||
}
|
||||
if (traits != null) {
|
||||
detailsY = drawTrait(graphics, "biomes", traitName("biome_distribution", traits.biomeDistribution()),
|
||||
left + 177, detailsY);
|
||||
detailsY = drawTrait(graphics, "lighting", traitName("lighting", traits.lighting()),
|
||||
left + 177, detailsY);
|
||||
detailsY = drawTrait(graphics, "weather", traitName("weather", traits.weather()),
|
||||
left + 177, detailsY);
|
||||
Component dayLength = traits.hasStoppedCelestialCycle()
|
||||
? Component.translatable("trait.rivencraft.day_length.stopped")
|
||||
: Component.literal(String.format(Locale.ROOT, "%.2fx", traits.celestialPeriod()));
|
||||
detailsY = drawTrait(graphics, "day_length", dayLength, left + 177, detailsY);
|
||||
detailsY = drawTrait(graphics, "celestial_angle",
|
||||
Component.literal(String.format(Locale.ROOT, "%.0f°", traits.celestialAngle())),
|
||||
left + 177, detailsY);
|
||||
drawTrait(graphics, "celestial_phase",
|
||||
Component.literal(String.format(Locale.ROOT, "%.0f%%", traits.celestialPhase() * 100.0F)),
|
||||
left + 177, detailsY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,11 +315,22 @@ public final class DescriptiveBookScreen extends Screen implements ExplorableBoo
|
||||
onClose();
|
||||
}
|
||||
|
||||
private void drawWrappedWithoutShadow(GuiGraphics graphics, Component text, int x, int y, int maxWidth) {
|
||||
private int drawTrait(GuiGraphics graphics, String key, Component value, int x, int y) {
|
||||
return drawWrappedWithoutShadow(graphics,
|
||||
Component.translatable("screen.rivencraft.age.trait." + key, value), x, y, 124) + 2;
|
||||
}
|
||||
|
||||
private static Component traitName(String group, Enum<?> value) {
|
||||
return Component.translatable("trait.rivencraft." + group + "."
|
||||
+ value.name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
private int drawWrappedWithoutShadow(GuiGraphics graphics, Component text, int x, int y, int maxWidth) {
|
||||
for (FormattedCharSequence line : font.split(text, maxWidth)) {
|
||||
graphics.drawString(font, line, x, y, BOOK_TEXT_COLOR, false);
|
||||
y += font.lineHeight;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -75,18 +75,20 @@ public final class ModNetworking {
|
||||
return;
|
||||
}
|
||||
AgeReference reference = access.stack().get(ModDataComponents.AGE_REFERENCE.get());
|
||||
if (reference != null && !access.stack().has(ModDataComponents.AGE_GENERATION_PROFILE.get())) {
|
||||
AgeRegistrySavedData.get(player.serverLevel()).find(reference.id()).ifPresent(definition -> {
|
||||
var definition = reference == null
|
||||
? null
|
||||
: AgeRegistrySavedData.get(player.serverLevel()).find(reference.id()).orElse(null);
|
||||
if (definition != null && !access.stack().has(ModDataComponents.AGE_GENERATION_PROFILE.get())) {
|
||||
access.stack().set(ModDataComponents.AGE_GENERATION_PROFILE.get(), definition.generationProfile());
|
||||
access.sync().run();
|
||||
});
|
||||
}
|
||||
// Requests run on the same server thread as Age creation. A request queued
|
||||
// during generation can only open the finished book, never a stale client copy.
|
||||
player.inventoryMenu.broadcastChanges();
|
||||
PacketDistributor.sendToPlayer(player, new OpenDescriptiveBookScreenPayload(
|
||||
payload.fromStand(), payload.offhand(),
|
||||
GlobalPos.of(player.level().dimension(), payload.standPos()), access.stack().copy()));
|
||||
GlobalPos.of(player.level().dimension(), payload.standPos()), access.stack().copy(),
|
||||
definition == null ? null : definition.traits()));
|
||||
}
|
||||
|
||||
private static void bindDescriptiveBook(BindDescriptiveBookPayload payload, IPayloadContext context) {
|
||||
|
||||
+46
-9
@@ -1,27 +1,64 @@
|
||||
package net.dnorberg.rivencraft.network;
|
||||
|
||||
import net.dnorberg.rivencraft.Rivencraft;
|
||||
import net.dnorberg.rivencraft.book.AgeTraits;
|
||||
import net.minecraft.core.GlobalPos;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
import net.minecraft.network.codec.ByteBufCodecs;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/** Server-approved book contents, sent only when the book is available to open. */
|
||||
public record OpenDescriptiveBookScreenPayload(boolean fromStand, boolean offhand, GlobalPos source, ItemStack book)
|
||||
public record OpenDescriptiveBookScreenPayload(
|
||||
boolean fromStand,
|
||||
boolean offhand,
|
||||
GlobalPos source,
|
||||
ItemStack book,
|
||||
@Nullable AgeTraits traits
|
||||
)
|
||||
implements CustomPacketPayload {
|
||||
public static final Type<OpenDescriptiveBookScreenPayload> TYPE = new Type<>(
|
||||
ResourceLocation.fromNamespaceAndPath(Rivencraft.MOD_ID, "open_descriptive_book_screen")
|
||||
);
|
||||
public static final StreamCodec<RegistryFriendlyByteBuf, OpenDescriptiveBookScreenPayload> STREAM_CODEC = StreamCodec.composite(
|
||||
ByteBufCodecs.BOOL, OpenDescriptiveBookScreenPayload::fromStand,
|
||||
ByteBufCodecs.BOOL, OpenDescriptiveBookScreenPayload::offhand,
|
||||
GlobalPos.STREAM_CODEC, OpenDescriptiveBookScreenPayload::source,
|
||||
ItemStack.STREAM_CODEC, OpenDescriptiveBookScreenPayload::book,
|
||||
OpenDescriptiveBookScreenPayload::new
|
||||
);
|
||||
public static final StreamCodec<RegistryFriendlyByteBuf, OpenDescriptiveBookScreenPayload> STREAM_CODEC =
|
||||
StreamCodec.of(OpenDescriptiveBookScreenPayload::encode, OpenDescriptiveBookScreenPayload::decode);
|
||||
|
||||
private static void encode(RegistryFriendlyByteBuf buffer, OpenDescriptiveBookScreenPayload payload) {
|
||||
buffer.writeBoolean(payload.fromStand());
|
||||
buffer.writeBoolean(payload.offhand());
|
||||
GlobalPos.STREAM_CODEC.encode(buffer, payload.source());
|
||||
ItemStack.STREAM_CODEC.encode(buffer, payload.book());
|
||||
buffer.writeBoolean(payload.traits() != null);
|
||||
if (payload.traits() != null) {
|
||||
AgeTraits traits = payload.traits();
|
||||
buffer.writeEnum(traits.biomeDistribution());
|
||||
buffer.writeEnum(traits.lighting());
|
||||
buffer.writeEnum(traits.weather());
|
||||
buffer.writeDouble(traits.celestialPeriod());
|
||||
buffer.writeFloat(traits.celestialAngle());
|
||||
buffer.writeFloat(traits.celestialPhase());
|
||||
}
|
||||
}
|
||||
|
||||
private static OpenDescriptiveBookScreenPayload decode(RegistryFriendlyByteBuf buffer) {
|
||||
boolean fromStand = buffer.readBoolean();
|
||||
boolean offhand = buffer.readBoolean();
|
||||
GlobalPos source = GlobalPos.STREAM_CODEC.decode(buffer);
|
||||
ItemStack book = ItemStack.STREAM_CODEC.decode(buffer);
|
||||
AgeTraits traits = buffer.readBoolean()
|
||||
? new AgeTraits(
|
||||
buffer.readEnum(AgeTraits.BiomeDistribution.class),
|
||||
buffer.readEnum(AgeTraits.Lighting.class),
|
||||
buffer.readEnum(AgeTraits.Weather.class),
|
||||
buffer.readDouble(),
|
||||
buffer.readFloat(),
|
||||
buffer.readFloat()
|
||||
)
|
||||
: null;
|
||||
return new OpenDescriptiveBookScreenPayload(fromStand, offhand, source, book, traits);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type<? extends CustomPacketPayload> type() {
|
||||
|
||||
@@ -29,6 +29,34 @@
|
||||
"screen.rivencraft.age.name_prompt": "Name this Age before writing the Descriptive Book",
|
||||
"screen.rivencraft.age.create": "Create",
|
||||
"screen.rivencraft.age.generator": "Terrain: %s",
|
||||
"screen.rivencraft.age.trait.biomes": "Biomes: %s",
|
||||
"screen.rivencraft.age.trait.lighting": "Lighting: %s",
|
||||
"screen.rivencraft.age.trait.weather": "Weather: %s",
|
||||
"screen.rivencraft.age.trait.day_length": "Day length: %s",
|
||||
"screen.rivencraft.age.trait.celestial_angle": "Angle: %s",
|
||||
"screen.rivencraft.age.trait.celestial_phase": "Phase: %s",
|
||||
"trait.rivencraft.biome_distribution.native": "Native",
|
||||
"trait.rivencraft.biome_distribution.single": "Single",
|
||||
"trait.rivencraft.biome_distribution.tiled": "Tiled",
|
||||
"trait.rivencraft.biome_distribution.grid": "Grid",
|
||||
"trait.rivencraft.biome_distribution.tiny": "Tiny",
|
||||
"trait.rivencraft.biome_distribution.small": "Small",
|
||||
"trait.rivencraft.biome_distribution.medium": "Medium",
|
||||
"trait.rivencraft.biome_distribution.large": "Large",
|
||||
"trait.rivencraft.biome_distribution.huge": "Huge",
|
||||
"trait.rivencraft.lighting.normal": "Normal",
|
||||
"trait.rivencraft.lighting.dark": "Dark",
|
||||
"trait.rivencraft.lighting.bright": "Bright",
|
||||
"trait.rivencraft.weather.normal": "Normal",
|
||||
"trait.rivencraft.weather.fast": "Fast",
|
||||
"trait.rivencraft.weather.slow": "Slow",
|
||||
"trait.rivencraft.weather.off": "Off",
|
||||
"trait.rivencraft.weather.always": "Always",
|
||||
"trait.rivencraft.weather.cloudy": "Cloudy",
|
||||
"trait.rivencraft.weather.rain": "Rain",
|
||||
"trait.rivencraft.weather.snow": "Snow",
|
||||
"trait.rivencraft.weather.storm": "Storm",
|
||||
"trait.rivencraft.day_length.stopped": "Stopped",
|
||||
"generator.rivencraft.standard": "Standard",
|
||||
"generator.rivencraft.amplified": "Amplified",
|
||||
"generator.rivencraft.island": "Island",
|
||||
|
||||
Reference in new issue
Block a user