This commit is contained in:
lukasabbe
2024-09-20 22:53:21 +02:00
commit b229b1ed2f
30 changed files with 1091 additions and 0 deletions
@@ -0,0 +1,46 @@
package me.lukasabbe.bookshelfinspector;
import me.lukasabbe.bookshelfinspector.network.BookShelfInventoryPayload;
import me.lukasabbe.bookshelfinspector.network.BookShelfInventoryRequestPayload;
import me.lukasabbe.bookshelfinspector.network.ModCheckPayload;
import me.lukasabbe.bookshelfinspector.util.BookshelfTools;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.server.MinecraftServer;
import java.util.logging.Logger;
public class Bookshelfinspector implements ModInitializer {
public static MinecraftServer serverInstance;
public final static String MOD_ID = "bookshelfinspector";
public static Logger LOGGER = Logger.getLogger(MOD_ID);
@Override
public void onInitialize() {
PayloadTypeRegistry.playC2S().register(BookShelfInventoryRequestPayload.ID,BookShelfInventoryRequestPayload.CODEC);
PayloadTypeRegistry.playS2C().register(BookShelfInventoryPayload.ID,BookShelfInventoryPayload.CODEC);
PayloadTypeRegistry.playS2C().register(ModCheckPayload.ID, ModCheckPayload.CODEC);
ServerPlayNetworking.registerGlobalReceiver(BookShelfInventoryRequestPayload.ID,((payload, context) -> context.server().execute(() -> {
if(Bookshelfinspector.serverInstance == null) return;
ItemStack stack = BookshelfTools.getItemById(payload.pos(),payload.slotNum(),context.player());
if(stack == null){
ServerPlayNetworking.send(context.player(), new BookShelfInventoryPayload(Items.AIR.getDefaultStack(), payload.pos(), payload.slotNum()));
return;
}
ServerPlayNetworking.send(context.player(), new BookShelfInventoryPayload(stack, payload.pos(), payload.slotNum()));
})));
ServerPlayConnectionEvents.JOIN.register(((handler, sender, server) -> {
serverInstance = server;
ServerPlayNetworking.send(handler.player, new ModCheckPayload(true));
}));
}
}
@@ -0,0 +1,41 @@
package me.lukasabbe.bookshelfinspector;
import me.lukasabbe.bookshelfinspector.data.BookData;
import me.lukasabbe.bookshelfinspector.network.BookShelfInventoryPayload;
import me.lukasabbe.bookshelfinspector.network.ModCheckPayload;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.util.hit.HitResult;
@Environment(EnvType.CLIENT)
public class BookshelfinspectorClient implements ClientModInitializer {
public static BookData currentBookData = new BookData(ItemStack.EMPTY, null, -1);
public static boolean isCurrentBookDataToggled = false;
public static boolean modAvailable = false;
public static HitResult latestHit;
@Override
public void onInitializeClient() {
ClientPlayNetworking.registerGlobalReceiver(BookShelfInventoryPayload.ID,
((payload, context) ->
context.client().execute(() ->{
if(payload.itemStack().isOf(Items.AIR))
isCurrentBookDataToggled = false;
else{
BookshelfinspectorClient.isCurrentBookDataToggled = true;
currentBookData = new BookData(payload.itemStack(),payload.pos(),payload.slotNum());
}
})));
ClientPlayNetworking.registerGlobalReceiver(ModCheckPayload.ID,
(payload, context) -> context.client().execute(() ->{
Bookshelfinspector.LOGGER.info("Connected to server");
modAvailable = true;
}));
}
}
@@ -0,0 +1,16 @@
package me.lukasabbe.bookshelfinspector.data;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
public class BookData {
public ItemStack itemStack;
public BlockPos pos;
public int slotId;
public BookData(ItemStack itemStack, BlockPos pos, int slotId) {
this.itemStack = itemStack;
this.pos = pos;
this.slotId = slotId;
}
}
@@ -0,0 +1,15 @@
package me.lukasabbe.bookshelfinspector.mixin;
import net.minecraft.block.BlockState;
import net.minecraft.block.ChiseledBookshelfBlock;
import net.minecraft.util.hit.BlockHitResult;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.util.OptionalInt;
@Mixin(ChiseledBookshelfBlock.class)
public interface BookshelfInvoker {
@Invoker("getSlotForHitPos")
OptionalInt invokerGetSlotForHitPos(BlockHitResult hit, BlockState state);
}
@@ -0,0 +1,73 @@
package me.lukasabbe.bookshelfinspector.mixin;
import me.lukasabbe.bookshelfinspector.BookshelfinspectorClient;
import me.lukasabbe.bookshelfinspector.data.BookData;
import me.lukasabbe.bookshelfinspector.network.BookShelfInventoryRequestPayload;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.block.BlockState;
import net.minecraft.block.ChiseledBookshelfBlock;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.entity.ChiseledBookshelfBlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Optional;
import java.util.OptionalInt;
@Mixin(ClientPlayerEntity.class)
public class BookshelfMixin{
@Shadow @Final protected MinecraftClient client;
@Inject(method = "tick", at= @At(value = "INVOKE", target = "Ljava/util/List;iterator()Ljava/util/Iterator;"))
public void injectTick(CallbackInfo ci){
bookShelfInspect();
}
@Unique
public void bookShelfInspect(){
if(!BookshelfinspectorClient.modAvailable) return;
if(client.cameraEntity == null || client.player == null) return;
HitResult hit = client.cameraEntity.raycast(20f,0f,false);
final HitResult.Type type = hit.getType();
if(type != HitResult.Type.BLOCK) return;
final BlockHitResult blockHitResult = (BlockHitResult) hit;
BlockPos pos = blockHitResult.getBlockPos();
Optional<ChiseledBookshelfBlockEntity> optionalChiseledBookshelfBlockEntity = client.player.getWorld().getBlockEntity(pos, BlockEntityType.CHISELED_BOOKSHELF);
if(optionalChiseledBookshelfBlockEntity.isEmpty()){
BookshelfinspectorClient.isCurrentBookDataToggled = false;
return;
}
final BlockState blockState = client.player.getWorld().getBlockState(pos);
ChiseledBookshelfBlock bookshelfBlock = (ChiseledBookshelfBlock) blockState.getBlock();
OptionalInt optionalInt = ((BookshelfInvoker)bookshelfBlock).invokerGetSlotForHitPos(blockHitResult,blockState);
if(optionalInt.isEmpty()) {
BookshelfinspectorClient.isCurrentBookDataToggled = false;
return;
}
BookshelfinspectorClient.latestHit = hit;
final BookData currentBookData = BookshelfinspectorClient.currentBookData;
if(currentBookData.itemStack == ItemStack.EMPTY || currentBookData.slotId!=optionalInt.getAsInt() || currentBookData.pos != pos){
ClientPlayNetworking.send(new BookShelfInventoryRequestPayload(pos, optionalInt.getAsInt()));
}
}
}
@@ -0,0 +1,63 @@
package me.lukasabbe.bookshelfinspector.mixin;
import me.lukasabbe.bookshelfinspector.Bookshelfinspector;
import me.lukasabbe.bookshelfinspector.BookshelfinspectorClient;
import me.lukasabbe.bookshelfinspector.data.BookData;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.hud.InGameHud;
import net.minecraft.client.render.RenderTickCounter;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Final;
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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(InGameHud.class)
public class InGameHudMixin {
@Shadow @Final private MinecraftClient client;
@Inject(method = "render",at=@At("RETURN"))
public void render(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci){
if(!BookshelfinspectorClient.modAvailable) return;
if(client.options.hudHidden) return;
if(BookshelfinspectorClient.isCurrentBookDataToggled){
final BookData currentBookData = BookshelfinspectorClient.currentBookData;
int screenWidth = client.getWindow().getScaledWidth();
int screenHeight = client.getWindow().getScaledHeight();
int x = screenWidth / 2;
int y = screenHeight / 2;
final ItemStack itemStack = currentBookData.itemStack;
int color = 0xFFFFFFFF;
if(itemStack.getRarity().getFormatting().getColorValue() != null){
color = itemStack.getRarity().getFormatting().getColorValue();
}
context.drawCenteredTextWithShadow(client.textRenderer, itemStack.getName(), x,y+10, color);
var storedComponets = itemStack.getComponents().get(DataComponentTypes.STORED_ENCHANTMENTS);
if(storedComponets != null){
int i = 20;
for(RegistryEntry<Enchantment> enchantment : storedComponets.getEnchantments()){
context.drawCenteredTextWithShadow(client.textRenderer, enchantment.value().description(), x,y+i, 0xFFFFFFFF);
i+=10;
}
}
var writtenBookContentComponent = itemStack.getComponents().get(DataComponentTypes.WRITTEN_BOOK_CONTENT);
if(writtenBookContentComponent != null){
context.drawCenteredTextWithShadow(client.textRenderer, Text.translatableWithFallback("bookshelfinspector.text.book","By ").append(writtenBookContentComponent.author()), x,y+20, 0xFFFFFFFF);
}
}
}
}
@@ -0,0 +1,10 @@
package me.lukasabbe.bookshelfinspector.network;
import me.lukasabbe.bookshelfinspector.Bookshelfinspector;
import net.minecraft.util.Identifier;
public class BookShelfInspectorNetworkConstants {
public static final Identifier BOOK_SHELF_INVENTORY_REQUEST_PACKET_ID = Identifier.of(Bookshelfinspector.MOD_ID,"book_shelf_inventory_request");
public static final Identifier BOOK_SHELF_INVENTORY_PACKET_ID = Identifier.of(Bookshelfinspector.MOD_ID,"book_shelf_inventory");
public static final Identifier MOD_CHECK_PACKET_ID = Identifier.of(Bookshelfinspector.MOD_ID,"mod_check");
}
@@ -0,0 +1,22 @@
package me.lukasabbe.bookshelfinspector.network;
import net.minecraft.item.ItemStack;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.network.packet.CustomPayload;
import net.minecraft.util.math.BlockPos;
public record BookShelfInventoryPayload(ItemStack itemStack, BlockPos pos, int slotNum) implements CustomPayload{
public static final CustomPayload.Id<BookShelfInventoryPayload> ID = new CustomPayload.Id<>(BookShelfInspectorNetworkConstants.BOOK_SHELF_INVENTORY_PACKET_ID);
public static final PacketCodec<RegistryByteBuf, BookShelfInventoryPayload> CODEC = PacketCodec.tuple(
ItemStack.OPTIONAL_PACKET_CODEC, BookShelfInventoryPayload::itemStack,
BlockPos.PACKET_CODEC, BookShelfInventoryPayload::pos,
PacketCodecs.INTEGER, BookShelfInventoryPayload::slotNum,
BookShelfInventoryPayload::new);
@Override
public CustomPayload.Id<? extends CustomPayload> getId() {
return ID;
}
}
@@ -0,0 +1,22 @@
package me.lukasabbe.bookshelfinspector.network;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.network.packet.CustomPayload;
import net.minecraft.util.math.BlockPos;
public record BookShelfInventoryRequestPayload(BlockPos pos, int slotNum) implements CustomPayload {
public static final CustomPayload.Id<BookShelfInventoryRequestPayload> ID = new CustomPayload.Id<>(BookShelfInspectorNetworkConstants.BOOK_SHELF_INVENTORY_REQUEST_PACKET_ID);
public static final PacketCodec<RegistryByteBuf, BookShelfInventoryRequestPayload> CODEC = PacketCodec.tuple(
BlockPos.PACKET_CODEC,BookShelfInventoryRequestPayload::pos,
PacketCodecs.INTEGER, BookShelfInventoryRequestPayload::slotNum,
BookShelfInventoryRequestPayload::new);
@Override
public Id<? extends CustomPayload> getId() {
return ID;
}
}
@@ -0,0 +1,21 @@
package me.lukasabbe.bookshelfinspector.network;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.network.packet.CustomPayload;
public record ModCheckPayload(boolean modActivated) implements CustomPayload {
public static final CustomPayload.Id<ModCheckPayload> ID = new CustomPayload.Id<>(BookShelfInspectorNetworkConstants.MOD_CHECK_PACKET_ID);
public static final PacketCodec<RegistryByteBuf, ModCheckPayload> CODEC = PacketCodec.tuple(
PacketCodecs.BOOL, ModCheckPayload::modActivated,
ModCheckPayload::new
);
@Override
public Id<? extends CustomPayload> getId() {
return ID;
}
}
@@ -0,0 +1,28 @@
package me.lukasabbe.bookshelfinspector.util;
import me.lukasabbe.bookshelfinspector.Bookshelfinspector;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.entity.ChiseledBookshelfBlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.Optional;
public class BookshelfTools {
public static ItemStack getItemById(BlockPos pos, int slotNum, PlayerEntity player){
final World world = Bookshelfinspector.serverInstance.getPlayerManager().getPlayer(player.getUuid()).getWorld();
if(world == null) return null;
Optional<ChiseledBookshelfBlockEntity> blockEntityOptional = world.getBlockEntity(pos,BlockEntityType.CHISELED_BOOKSHELF);
if(blockEntityOptional.isEmpty()) return null;
ChiseledBookshelfBlockEntity blockEntity = blockEntityOptional.get();
final ItemStack stack = blockEntity.getStack(slotNum);
if(stack.isEmpty()) return null;
return stack;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

@@ -0,0 +1,3 @@
{
"bookshelfinspector.text.book" : "By "
}
@@ -0,0 +1,3 @@
{
"bookshelfinspector.text.book" : "Av "
}
@@ -0,0 +1,16 @@
{
"required": true,
"minVersion": "0.8",
"package": "me.lukasabbe.bookshelfinspector.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": [
],
"client": [
"InGameHudMixin",
"BookshelfInvoker",
"BookshelfMixin"
],
"injectors": {
"defaultRequire": 1
}
}
+30
View File
@@ -0,0 +1,30 @@
{
"schemaVersion": 1,
"id": "bookshelfinspector",
"version": "${version}",
"name": "Bookshelfinspector",
"description": "Inspect any book in a chiseled bookshelf.",
"authors": ["Lukasabbe"],
"contact": {},
"license": "MIT",
"icon": "assets/bookshelfinspector/icon.png",
"environment": "*",
"entrypoints": {
"client": [
"me.lukasabbe.bookshelfinspector.BookshelfinspectorClient"
],
"main": [
"me.lukasabbe.bookshelfinspector.Bookshelfinspector"
]
},
"mixins": [
"bookshelfinspector.mixins.json"
],
"depends": {
"fabricloader": ">=${loader_version}",
"minecraft": ">=${minecraft_version}",
"fabric-api-base": "*",
"fabric-networking-api-v1": "*",
"fabric-lifecycle-events-v1": "*"
}
}