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
|
uses Minecraft's serializable checkerboard biome source so the layout remains
|
||||||
stable across server reloads.
|
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
|
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
|
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
|
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.
|
# 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
|
mod_license=LGPL-3.0-or-later
|
||||||
# The mod version. Rivencraft uses the x.y.z.b policy documented in README.md.
|
# 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
|
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.
|
# 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.
|
# This should match the base package used for the mod sources.
|
||||||
|
|||||||
@@ -92,8 +92,8 @@ public final class ClientBookInteractionHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
minecraft.setScreen(payload.fromStand()
|
minecraft.setScreen(payload.fromStand()
|
||||||
? new DescriptiveBookScreen(payload.source().pos(), payload.book())
|
? new DescriptiveBookScreen(payload.source().pos(), payload.book(), payload.traits())
|
||||||
: new DescriptiveBookScreen(hand, payload.book()));
|
: new DescriptiveBookScreen(hand, payload.book(), payload.traits()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.dnorberg.rivencraft.client.screen;
|
package net.dnorberg.rivencraft.client.screen;
|
||||||
|
|
||||||
import net.dnorberg.rivencraft.book.AgeReference;
|
import net.dnorberg.rivencraft.book.AgeReference;
|
||||||
|
import net.dnorberg.rivencraft.book.AgeTraits;
|
||||||
import net.dnorberg.rivencraft.client.ClientBookExploreOverlay;
|
import net.dnorberg.rivencraft.client.ClientBookExploreOverlay;
|
||||||
import net.dnorberg.rivencraft.network.UseDescriptiveBookPayload;
|
import net.dnorberg.rivencraft.network.UseDescriptiveBookPayload;
|
||||||
import net.dnorberg.rivencraft.network.BindDescriptiveBookPayload;
|
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.item.ItemStack;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.neoforged.neoforge.network.PacketDistributor;
|
import net.neoforged.neoforge.network.PacketDistributor;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public final class DescriptiveBookScreen extends Screen implements ExplorableBookScreen {
|
public final class DescriptiveBookScreen extends Screen implements ExplorableBookScreen {
|
||||||
private static final int BOOK_TEXT_COLOR = 0xFF3B281B;
|
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 AgeReference age;
|
||||||
private final ResourceLocation generationProfile;
|
private final ResourceLocation generationProfile;
|
||||||
|
private final AgeTraits traits;
|
||||||
private final InteractionHand hand;
|
private final InteractionHand hand;
|
||||||
private final BlockPos bookStandPos;
|
private final BlockPos bookStandPos;
|
||||||
private DestinationPreviewRenderer preview;
|
private DestinationPreviewRenderer preview;
|
||||||
@@ -47,18 +52,20 @@ public final class DescriptiveBookScreen extends Screen implements ExplorableBoo
|
|||||||
private Button exploreButton;
|
private Button exploreButton;
|
||||||
private boolean movingToExploreOverlay;
|
private boolean movingToExploreOverlay;
|
||||||
|
|
||||||
public DescriptiveBookScreen(InteractionHand hand, ItemStack book) {
|
public DescriptiveBookScreen(InteractionHand hand, ItemStack book, @Nullable AgeTraits traits) {
|
||||||
super(book.getHoverName());
|
super(book.getHoverName());
|
||||||
age = book.get(ModDataComponents.AGE_REFERENCE.get());
|
age = book.get(ModDataComponents.AGE_REFERENCE.get());
|
||||||
generationProfile = book.get(ModDataComponents.AGE_GENERATION_PROFILE.get());
|
generationProfile = book.get(ModDataComponents.AGE_GENERATION_PROFILE.get());
|
||||||
|
this.traits = traits;
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
bookStandPos = null;
|
bookStandPos = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DescriptiveBookScreen(BlockPos bookStandPos, ItemStack book) {
|
public DescriptiveBookScreen(BlockPos bookStandPos, ItemStack book, @Nullable AgeTraits traits) {
|
||||||
super(book.getHoverName());
|
super(book.getHoverName());
|
||||||
age = book.get(ModDataComponents.AGE_REFERENCE.get());
|
age = book.get(ModDataComponents.AGE_REFERENCE.get());
|
||||||
generationProfile = book.get(ModDataComponents.AGE_GENERATION_PROFILE.get());
|
generationProfile = book.get(ModDataComponents.AGE_GENERATION_PROFILE.get());
|
||||||
|
this.traits = traits;
|
||||||
hand = InteractionHand.MAIN_HAND;
|
hand = InteractionHand.MAIN_HAND;
|
||||||
this.bookStandPos = bookStandPos.immutable();
|
this.bookStandPos = bookStandPos.immutable();
|
||||||
}
|
}
|
||||||
@@ -138,14 +145,34 @@ public final class DescriptiveBookScreen extends Screen implements ExplorableBoo
|
|||||||
left + 177, top + 45, 124);
|
left + 177, top + 45, 124);
|
||||||
} else {
|
} else {
|
||||||
preview.render(graphics, left + LINK_PANEL_X, top + LINK_PANEL_Y, LINK_PANEL_WIDTH, LINK_PANEL_HEIGHT, partialTick);
|
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) {
|
if (generationProfile != null) {
|
||||||
Component profileName = generationProfile.getNamespace().equals("rivencraft")
|
Component profileName = generationProfile.getNamespace().equals("rivencraft")
|
||||||
? Component.translatable("generator.rivencraft." + generationProfile.getPath())
|
? Component.translatable("generator.rivencraft." + generationProfile.getPath())
|
||||||
: Component.literal(generationProfile.toString());
|
: Component.literal(generationProfile.toString());
|
||||||
drawWrappedWithoutShadow(graphics,
|
detailsY = drawWrappedWithoutShadow(graphics,
|
||||||
Component.translatable("screen.rivencraft.age.generator", profileName),
|
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();
|
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)) {
|
for (FormattedCharSequence line : font.split(text, maxWidth)) {
|
||||||
graphics.drawString(font, line, x, y, BOOK_TEXT_COLOR, false);
|
graphics.drawString(font, line, x, y, BOOK_TEXT_COLOR, false);
|
||||||
y += font.lineHeight;
|
y += font.lineHeight;
|
||||||
}
|
}
|
||||||
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -75,18 +75,20 @@ public final class ModNetworking {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AgeReference reference = access.stack().get(ModDataComponents.AGE_REFERENCE.get());
|
AgeReference reference = access.stack().get(ModDataComponents.AGE_REFERENCE.get());
|
||||||
if (reference != null && !access.stack().has(ModDataComponents.AGE_GENERATION_PROFILE.get())) {
|
var definition = reference == null
|
||||||
AgeRegistrySavedData.get(player.serverLevel()).find(reference.id()).ifPresent(definition -> {
|
? 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.stack().set(ModDataComponents.AGE_GENERATION_PROFILE.get(), definition.generationProfile());
|
||||||
access.sync().run();
|
access.sync().run();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
// Requests run on the same server thread as Age creation. A request queued
|
// 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.
|
// during generation can only open the finished book, never a stale client copy.
|
||||||
player.inventoryMenu.broadcastChanges();
|
player.inventoryMenu.broadcastChanges();
|
||||||
PacketDistributor.sendToPlayer(player, new OpenDescriptiveBookScreenPayload(
|
PacketDistributor.sendToPlayer(player, new OpenDescriptiveBookScreenPayload(
|
||||||
payload.fromStand(), payload.offhand(),
|
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) {
|
private static void bindDescriptiveBook(BindDescriptiveBookPayload payload, IPayloadContext context) {
|
||||||
|
|||||||
+46
-9
@@ -1,27 +1,64 @@
|
|||||||
package net.dnorberg.rivencraft.network;
|
package net.dnorberg.rivencraft.network;
|
||||||
|
|
||||||
import net.dnorberg.rivencraft.Rivencraft;
|
import net.dnorberg.rivencraft.Rivencraft;
|
||||||
|
import net.dnorberg.rivencraft.book.AgeTraits;
|
||||||
import net.minecraft.core.GlobalPos;
|
import net.minecraft.core.GlobalPos;
|
||||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||||
import net.minecraft.network.codec.ByteBufCodecs;
|
|
||||||
import net.minecraft.network.codec.StreamCodec;
|
import net.minecraft.network.codec.StreamCodec;
|
||||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/** Server-approved book contents, sent only when the book is available to open. */
|
/** 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 {
|
implements CustomPacketPayload {
|
||||||
public static final Type<OpenDescriptiveBookScreenPayload> TYPE = new Type<>(
|
public static final Type<OpenDescriptiveBookScreenPayload> TYPE = new Type<>(
|
||||||
ResourceLocation.fromNamespaceAndPath(Rivencraft.MOD_ID, "open_descriptive_book_screen")
|
ResourceLocation.fromNamespaceAndPath(Rivencraft.MOD_ID, "open_descriptive_book_screen")
|
||||||
);
|
);
|
||||||
public static final StreamCodec<RegistryFriendlyByteBuf, OpenDescriptiveBookScreenPayload> STREAM_CODEC = StreamCodec.composite(
|
public static final StreamCodec<RegistryFriendlyByteBuf, OpenDescriptiveBookScreenPayload> STREAM_CODEC =
|
||||||
ByteBufCodecs.BOOL, OpenDescriptiveBookScreenPayload::fromStand,
|
StreamCodec.of(OpenDescriptiveBookScreenPayload::encode, OpenDescriptiveBookScreenPayload::decode);
|
||||||
ByteBufCodecs.BOOL, OpenDescriptiveBookScreenPayload::offhand,
|
|
||||||
GlobalPos.STREAM_CODEC, OpenDescriptiveBookScreenPayload::source,
|
private static void encode(RegistryFriendlyByteBuf buffer, OpenDescriptiveBookScreenPayload payload) {
|
||||||
ItemStack.STREAM_CODEC, OpenDescriptiveBookScreenPayload::book,
|
buffer.writeBoolean(payload.fromStand());
|
||||||
OpenDescriptiveBookScreenPayload::new
|
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
|
@Override
|
||||||
public Type<? extends CustomPacketPayload> type() {
|
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.name_prompt": "Name this Age before writing the Descriptive Book",
|
||||||
"screen.rivencraft.age.create": "Create",
|
"screen.rivencraft.age.create": "Create",
|
||||||
"screen.rivencraft.age.generator": "Terrain: %s",
|
"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.standard": "Standard",
|
||||||
"generator.rivencraft.amplified": "Amplified",
|
"generator.rivencraft.amplified": "Amplified",
|
||||||
"generator.rivencraft.island": "Island",
|
"generator.rivencraft.island": "Island",
|
||||||
|
|||||||
Reference in new issue
Block a user