Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
8cbaa69
Adding book background asset
jonoomph Aug 17, 2025
35cd0d1
Adding initial book prototype - still breaks on old minecraft versions
jonoomph Aug 17, 2025
2c4217e
Fixing build issues on book screen for all versions of Minecraft - st…
jonoomph Aug 17, 2025
27cd2b2
New Book Item
jonoomph Aug 18, 2025
edce13c
Updating book item png
jonoomph Aug 18, 2025
96ba569
New packet types for sending / receiving all entity data (by UUID - p…
jonoomph Aug 19, 2025
d2eb891
Fixing click detection on 1.20 to 1.21.7.
jonoomph Aug 20, 2025
04000e0
Moving book textures to book sub-folder, and removing next/prev from …
jonoomph Aug 20, 2025
3eea805
Placeholder button hover assets for book
jonoomph Aug 20, 2025
ff91355
Dynamic Next/Previous buttons with hover
jonoomph Aug 20, 2025
5098111
Fixing datagen to support ALL versions of minecraft
jonoomph Aug 20, 2025
6c3656f
Summary pages are displayed first, then Detail pages with more info
jonoomph Aug 20, 2025
a72120e
Improvements to page contents, layout, pagination - and page turn sounds
jonoomph Aug 20, 2025
e9355b3
Integrating entity_type into chat data, and incorporating death into …
jonoomph Aug 20, 2025
6159359
Fixing more out-of-bounds text wrapping
jonoomph Aug 20, 2025
a656a69
Making entity type load from a helper - and not require the UUID of t…
jonoomph Aug 21, 2025
ccdf57c
Merge branch 'develop' into book
jonoomph Aug 21, 2025
5fc147d
Adding entityName into chat data, for dead mobs and refactoring entit…
jonoomph Aug 21, 2025
4e8084e
Fixing pagination and wrapping of BookScreen, and Remember book scree…
jonoomph Aug 23, 2025
0422b82
Adding top level images and hovers
jonoomph Aug 24, 2025
fe690bd
Fix sorting book index
jonoomph Aug 24, 2025
8c4c423
Adding top buttons + hover states - integrated hover assets and new a…
jonoomph Aug 24, 2025
1a91cd3
Fix last message date, adding field to EntityChatData - for better so…
jonoomph Aug 24, 2025
c4f19c2
Adding deterministic random stickers to pages (based on UUID and page…
jonoomph Aug 25, 2025
833e6a5
Merge branch 'develop' into book
jonoomph Aug 25, 2025
cbcfe90
Fixing build error for datagen providers - after merging develop
jonoomph Aug 25, 2025
66034ba
Clean messages (remove behaviors), and better support death timestamps
jonoomph Aug 25, 2025
c695bc8
Merge branch 'develop' into book
jonoomph Aug 25, 2025
d93c4c6
Merge branch 'develop' into book
jonoomph Aug 25, 2025
9c83a41
Merge branch 'develop' into book
jonoomph Aug 27, 2025
031aa35
Merge branch 'develop' into book
jonoomph Aug 28, 2025
78039be
Merging Creature Book into existing translations
jonoomph Aug 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ All notable changes to **CreatureChat™** are documented in this file. The form
## Unreleased

### Added
- New Book Item
- Load client entity chat data and display friends and enemies by most recent
- Using Fabric DataGen to create book item
- New packet types for sending / receiving all entity data (by UUID - per page)
- Dynamic Next/Previous buttons with hover (hidden when no page to turn)
- Summary pages are displayed first, then Detail pages with more info
- Improvements to page contents, layout, pagination - and page turn sounds
- Integrating entityType into chat data, and incorporating death into broadcast, login, and book pages
- Adding entityName into chat data, for dead mobs
- Remember book screen state when exiting (so book resumes exactly where you left it)
- Adding top buttons + hover states - integrated hover assets and new arrow buttons
- Adding deterministic random stickers to pages (based on UUID and page #)
- Clean recent messages (remove behaviors)
- Document SPDX header and changelog requirements in AGENTS.md for contributors

### Changed
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ loom {
runs {
datagen {
server()
client()
vmArg "-Dfabric-api.datagen"
vmArg "-Dfabric-api.datagen.output-dir=${file('src/main/generated').absolutePath}"
vmArg "-Dfabric-api.datagen.modid=creaturechat"
Expand Down
16 changes: 16 additions & 0 deletions src/client/java/com/owlmaddie/ClientInit.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,20 @@
import com.owlmaddie.ui.InventoryKeyHandler;
import com.owlmaddie.ui.PlayerMessageManager;
import com.owlmaddie.utils.TickDelta;
import com.owlmaddie.utils.UseItemCallbackHelper;
import com.owlmaddie.inventory.ModMenus;
import com.owlmaddie.inventory.MobInventoryScreen;
import com.owlmaddie.items.ModItems;
import com.owlmaddie.ui.BookScreen;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.fabricmc.fabric.api.event.player.UseItemCallback;
import net.minecraft.client.gui.screens.MenuScreens;
import net.minecraft.client.Minecraft;
import net.minecraft.world.InteractionResultHolder;

/**
* The {@code ClientInit} class initializes this mod in the client and defines all hooks into the
Expand Down Expand Up @@ -56,6 +62,16 @@ public void onInitializeClient() {
ClientPackets.register();
MenuScreens.register(ModMenus.MOB_INVENTORY, MobInventoryScreen::new);

UseItemCallback.EVENT.register((player, world, hand) -> {
if (player.getItemInHand(hand).is(ModItems.BOOK)) {
if (world.isClientSide) {
Minecraft.getInstance().setScreen(new BookScreen());
}
return InteractionResultHolder.success(player.getItemInHand(hand));
}
return UseItemCallbackHelper.handleUseItemAction(player, world, hand);
});

// Register an event callback to render text bubbles
WorldRenderEvents.BEFORE_DEBUG_RENDER.register(ctx -> {
float delta = TickDelta.get(ctx);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: 2025 owlmaddie LLC
// SPDX-License-Identifier: GPL-3.0-or-later
// Assets CC-BY-NC-SA-4.0; CreatureChat™ trademark © owlmaddie LLC - unauthorized use prohibited
package com.owlmaddie.datagen;

import com.owlmaddie.items.ModItems;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricModelProvider;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.minecraft.data.models.BlockModelGenerators;
import net.minecraft.data.models.ItemModelGenerators;
import net.minecraft.data.models.model.ModelTemplates;

/**
* Generates item model JSON files using Minecraft's model data generators
* instead of manually constructing JSON.
*/
public class CreatureChatModelProvider extends FabricModelProvider {
public CreatureChatModelProvider(FabricDataOutput output) {
super(output);
}

@Override
public void generateBlockStateModels(BlockModelGenerators blockStateModelGenerators) {
// No block models are generated for this mod.
}

@Override
public void generateItemModels(ItemModelGenerators itemModelGenerators) {
// Generates the "minecraft:item/generated" style model for the book item.
itemModelGenerators.generateFlatItem(ModItems.BOOK, ModelTemplates.FLAT_ITEM);
}
}

44 changes: 44 additions & 0 deletions src/client/java/com/owlmaddie/network/ClientPackets.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ public static void sendChat(Entity entity, String message) {
ClientPacketHelper.send(ServerPackets.PACKET_C2S_SEND_CHAT, buf);
}

public static void requestEntityData(UUID entityId) {
FriendlyByteBuf buf = ClientBufferHelper.create();
buf.writeUtf(entityId.toString());
ClientPacketHelper.send(ServerPackets.PACKET_C2S_REQUEST_ENTITY_DATA, buf);
}

// Reading a Map<String, PlayerData> from the buffer
public static Map<String, PlayerData> readPlayerDataMap(FriendlyByteBuf buffer) {
int size = buffer.readInt(); // Read the size of the map
Expand All @@ -119,6 +125,8 @@ public static void register() {
String sender_name = buffer.readUtf(32767);
ChatDataManager.ChatSender sender = ChatDataManager.ChatSender.valueOf(sender_name);
Map<String, PlayerData> players = readPlayerDataMap(buffer);
long lastTs = buffer.readLong();
long deathTs = buffer.readLong();

// Update the chat data manager on the client-side
client.execute(() -> { // Make sure to run on the client thread
Expand All @@ -140,6 +148,8 @@ public static void register() {
chatData.status = status;
chatData.sender = sender;
chatData.players = players;
chatData.lastMessage = lastTs;
chatData.death = deathTs != 0L ? deathTs : null;

// Play sound with volume based on distance (from player or entity)
Mob entity = ClientEntityFinder.getEntityByUUID(client.level, entityId);
Expand Down Expand Up @@ -207,6 +217,40 @@ public static void register() {
});
});

ClientPacketHelper.registerReceiver(ServerPackets.PACKET_S2C_ENTITY_DATA, (client, handler, buffer, responseSender) -> {
String entityId = buffer.readUtf();
byte[] compressed = buffer.readByteArray();
client.execute(() -> {
String json = Decompression.decompressString(compressed);
if (json == null || json.isEmpty()) {
return;
}
Gson gson = new Gson();
EntityChatData data = gson.fromJson(json, EntityChatData.class);
data.postDeserializeInitialization();
LOGGER.info("Client received full data for entity {}", entityId);
ChatDataManager mgr = ChatDataManager.getClientInstance();
EntityChatData existing = mgr.entityChatDataMap.get(entityId);
if (existing != null) {
existing.currentMessage = data.currentMessage;
existing.currentLineNumber = data.currentLineNumber;
existing.status = data.status;
existing.sender = data.sender;
existing.players = data.players;
existing.characterSheet = data.characterSheet;
existing.auto_generated = data.auto_generated;
existing.previousMessages = data.previousMessages;
existing.born = data.born;
existing.death = data.death;
existing.lastMessage = data.lastMessage;
existing.entityType = data.entityType;
existing.entityName = data.entityName;
} else {
mgr.entityChatDataMap.put(entityId, data);
}
});
});

// Client-side packet handler, receive entire whitelist / blacklist, and update BubbleRenderer
ClientPacketHelper.registerReceiver(ServerPackets.PACKET_S2C_WHITELIST, (client, handler, buffer, responseSender) -> {
// Read the whitelist data from the buffer
Expand Down
29 changes: 29 additions & 0 deletions src/client/java/com/owlmaddie/render/PoseHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-FileCopyrightText: 2025 owlmaddie LLC
// SPDX-License-Identifier: GPL-3.0-or-later
// Assets CC-BY-NC-SA-4.0; CreatureChat™ trademark © owlmaddie LLC - unauthorized use prohibited
package com.owlmaddie.render;

import com.mojang.blaze3d.vertex.PoseStack;

/**
* Cross-version wrapper for simple pose transformations.
*/
public final class PoseHelper {
private PoseHelper() {}

public static void push(PoseStack stack) {
stack.pushPose();
}

public static void pop(PoseStack stack) {
stack.popPose();
}

public static void translate(PoseStack stack, float x, float y) {
stack.translate(x, y, 0);
}

public static void scale(PoseStack stack, float sx, float sy) {
stack.scale(sx, sy, 1.0f);
}
}
25 changes: 25 additions & 0 deletions src/client/java/com/owlmaddie/render/RenderPipelineHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-FileCopyrightText: 2025 owlmaddie LLC
// SPDX-License-Identifier: GPL-3.0-or-later
// Assets CC-BY-NC-SA-4.0; CreatureChat™ trademark © owlmaddie LLC - unauthorized use prohibited
package com.owlmaddie.render;

import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.resources.ResourceLocation;

/**
* Helper to blit GUI textures across Minecraft versions.
*/
public final class RenderPipelineHelper {
private RenderPipelineHelper() {}

public static void blitGuiTexture(
GuiGraphics ctx,
ResourceLocation tex,
int x, int y,
int u, int v,
int width, int height,
int texWidth, int texHeight
) {
ctx.blit(tex, x, y, u, v, width, height, texWidth, texHeight);
}
}
Loading