Skip to content

Commit ffd7bb0

Browse files
committed
holders
1 parent d0aa403 commit ffd7bb0

11 files changed

Lines changed: 262 additions & 49 deletions

File tree

autodocs/autodoc.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
--#region Information
44
-- GENERATED AUTODOC
5-
-- Generated: 2026-03-02T20:11:48.109650600
5+
-- Generated: 2026-03-04T20:09:33.245086
66
-- Luafy Version: 2.0.0
77
-- Format: Lua LS library file
88
--#endregion

src/main/java/dev/diamond/luafy/Luafy.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import dev.diamond.luafy.autodoc.generator.AbstractAutodocGenerator;
44
import dev.diamond.luafy.command.LuafyCommand;
55
import dev.diamond.luafy.command.HotCommand;
6+
import dev.diamond.luafy.holder.ScriptHolderBlockItem;
67
import dev.diamond.luafy.registry.*;
78
import dev.diamond.luafy.resource.ScriptEventResourceLoader;
89
import dev.diamond.luafy.script.ScriptManager;
@@ -57,6 +58,9 @@ public void onInitialize() {
5758
ScriptEvents.applyEvents();
5859
AutodocGenerators.registerAll();
5960

61+
//
62+
ScriptHolderBlockItem.registerHolderBlockStuff();
63+
6064

6165
// generate LuaLS autodoc
6266
AutodocGenerators.LUA_LS.buildOutput(FabricLoaderImpl.INSTANCE.isDevelopmentEnvironment() ? new File(DEV_ENV_DOC_OUTPUT_FILEPATH) : AbstractAutodocGenerator.getDefaultFile(AutodocGenerators.LUA_LS));

src/main/java/dev/diamond/luafy/command/LuafyCommand.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import dev.diamond.luafy.Luafy;
1111
import dev.diamond.luafy.autodoc.SimpleAutodocumentable;
1212
import dev.diamond.luafy.autodoc.generator.AbstractAutodocGenerator;
13-
import dev.diamond.luafy.holder.HolderItem;
13+
import dev.diamond.luafy.holder.ScriptHolderBlockItem;
1414
import dev.diamond.luafy.lua.LuaTableBuilder;
1515
import dev.diamond.luafy.lua.MetamethodImpl;
1616
import dev.diamond.luafy.registry.LuafyRegistries;
@@ -222,7 +222,7 @@ private static int execScript(CommandContext<CommandSourceStack> ctx, LuaScript
222222
private static int giveHolderItem(CommandContext<CommandSourceStack> ctx) {
223223
// proof of concept
224224
if (ctx.getSource().isPlayer()) {
225-
ctx.getSource().getPlayer().addItem(HolderItem.getItem(ctx.getSource().getLevel()));
225+
ctx.getSource().getPlayer().addItem(ScriptHolderBlockItem.getItem(ctx.getSource().getLevel()));
226226
}
227227
return 1;
228228
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package dev.diamond.luafy.holder;
2+
3+
import dev.diamond.luafy.Luafy;
4+
import net.minecraft.core.Holder;
5+
import net.minecraft.core.Registry;
6+
import net.minecraft.core.RegistryAccess;
7+
import net.minecraft.core.registries.Registries;
8+
import net.minecraft.resources.Identifier;
9+
import net.minecraft.server.dialog.Dialog;
10+
import net.minecraft.world.entity.player.Player;
11+
import net.minecraft.world.level.Level;
12+
13+
import java.util.Optional;
14+
15+
public class HolderDialog {
16+
17+
public static final Identifier ID = Luafy.id("modify_script_holder");
18+
19+
20+
public static void open(Level level, Player player) {
21+
RegistryAccess access = level.registryAccess();
22+
Registry<Dialog> reg = access.lookupOrThrow(Registries.DIALOG);
23+
Optional<Holder.Reference<Dialog>> optional = reg.get(ID);
24+
25+
optional.ifPresent(player::openDialog);
26+
}
27+
28+
29+
}

src/main/java/dev/diamond/luafy/holder/HolderItem.java

Lines changed: 0 additions & 35 deletions
This file was deleted.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package dev.diamond.luafy.holder;
2+
3+
import com.mojang.serialization.Codec;
4+
import com.mojang.serialization.codecs.RecordCodecBuilder;
5+
import dev.diamond.luafy.Luafy;
6+
import net.fabricmc.fabric.api.attachment.v1.AttachmentRegistry;
7+
import net.fabricmc.fabric.api.attachment.v1.AttachmentType;
8+
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
9+
import net.minecraft.core.component.DataComponents;
10+
import net.minecraft.nbt.CompoundTag;
11+
import net.minecraft.network.chat.Component;
12+
import net.minecraft.resources.Identifier;
13+
import net.minecraft.server.MinecraftServer;
14+
import net.minecraft.server.level.ServerLevel;
15+
import net.minecraft.world.InteractionHand;
16+
import net.minecraft.world.InteractionResult;
17+
import net.minecraft.world.entity.player.Player;
18+
import net.minecraft.world.item.ItemStack;
19+
import net.minecraft.world.item.Items;
20+
import net.minecraft.world.item.Rarity;
21+
import net.minecraft.world.item.component.CustomData;
22+
import net.minecraft.world.level.Level;
23+
import net.minecraft.world.level.block.entity.BlockEntity;
24+
import net.minecraft.world.level.block.entity.EnderChestBlockEntity;
25+
import net.minecraft.world.phys.BlockHitResult;
26+
27+
import java.util.Optional;
28+
29+
public class ScriptHolderBlockItem {
30+
31+
public static final String KEY = "script_holder_block";
32+
33+
public static final AttachmentType<ScriptHolderAttachment> SCRIPT_HOLDER_ATTACHMENT = AttachmentRegistry.create(
34+
Luafy.id("script_holder"),
35+
builder -> builder
36+
.initializer(() -> new ScriptHolderAttachment(null))
37+
.persistent(ScriptHolderAttachment.CODEC)
38+
);
39+
40+
public static ItemStack getItem(ServerLevel level) {
41+
ItemStack itemStack = new ItemStack(Items.ENDER_CHEST);
42+
43+
itemStack.set(DataComponents.RARITY, Rarity.UNCOMMON);
44+
itemStack.set(DataComponents.ITEM_NAME, Component.literal("Script Holder"));
45+
itemStack.set(DataComponents.MAX_STACK_SIZE, 64);
46+
itemStack.set(DataComponents.ENCHANTMENT_GLINT_OVERRIDE, true);
47+
48+
CompoundTag compoundTag = new CompoundTag();
49+
compoundTag.putBoolean(KEY, true);
50+
CustomData customData = CustomData.of(compoundTag);
51+
itemStack.set(DataComponents.CUSTOM_DATA, customData);
52+
53+
return itemStack;
54+
}
55+
56+
private static boolean isHoldingItem(Player player, InteractionHand hand) {
57+
ItemStack stack = player.getItemInHand(hand);
58+
return isItem(stack);
59+
}
60+
61+
public static boolean isItem(ItemStack stack) {
62+
CustomData customData = stack.getComponents().get(DataComponents.CUSTOM_DATA);
63+
64+
if (customData == null || stack.getCount() < 1)
65+
return false;
66+
67+
CompoundTag compoundTag = customData.copyTag();
68+
return compoundTag.getBoolean(KEY).orElse(false);
69+
}
70+
71+
private static InteractionResult useBlock(Player player, Level level, InteractionHand interactionHand, BlockHitResult blockHitResult) {
72+
MinecraftServer server = level.getServer();
73+
74+
if (server == null || level.isClientSide() || player.isSpectator()) return InteractionResult.PASS;
75+
76+
BlockEntity be = level.getBlockEntity(blockHitResult.getBlockPos());
77+
if (be instanceof EnderChestBlockEntity && player.canUseGameMasterBlocks()) {
78+
79+
if (ScriptHolderBlockItem.ScriptHolderAttachment.hasHolderAttachment(be)) {
80+
81+
HolderDialog.open(level, player);
82+
83+
return InteractionResult.SUCCESS;
84+
}
85+
}
86+
87+
return InteractionResult.PASS;
88+
}
89+
90+
91+
92+
public static void registerHolderBlockStuff() {
93+
UseBlockCallback.EVENT.register(ScriptHolderBlockItem::useBlock);
94+
}
95+
96+
97+
98+
99+
public record ScriptHolderAttachment(Optional<Identifier> scriptId) {
100+
public static final Codec<ScriptHolderAttachment> CODEC = RecordCodecBuilder.create(instance -> instance.group(
101+
Identifier.CODEC.optionalFieldOf("script_id").forGetter(ScriptHolderAttachment::scriptId)
102+
).apply(instance, ScriptHolderAttachment::new));
103+
104+
public static boolean hasHolderAttachment(BlockEntity blockEntity) {
105+
return blockEntity.hasAttached(SCRIPT_HOLDER_ATTACHMENT);
106+
}
107+
108+
public static ScriptHolderAttachment giveHolderAttachment(BlockEntity holderBlockEntity) {
109+
return holderBlockEntity.getAttachedOrCreate(SCRIPT_HOLDER_ATTACHMENT);
110+
}
111+
112+
public static Optional<Identifier> getHolderScriptId(BlockEntity holderBlockEntity) {
113+
assert hasHolderAttachment(holderBlockEntity);
114+
return holderBlockEntity.getAttached(SCRIPT_HOLDER_ATTACHMENT).scriptId();
115+
}
116+
}
117+
118+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package dev.diamond.luafy.mixin;
2+
3+
import dev.diamond.luafy.holder.ScriptHolderBlockItem;
4+
import net.minecraft.core.BlockPos;
5+
import net.minecraft.world.InteractionResult;
6+
import net.minecraft.world.entity.player.Player;
7+
import net.minecraft.world.item.BlockItem;
8+
import net.minecraft.world.item.ItemStack;
9+
import net.minecraft.world.item.context.BlockPlaceContext;
10+
import net.minecraft.world.level.Level;
11+
import net.minecraft.world.level.block.SoundType;
12+
import net.minecraft.world.level.block.entity.BlockEntity;
13+
import net.minecraft.world.level.block.state.BlockState;
14+
import org.spongepowered.asm.mixin.Mixin;
15+
import org.spongepowered.asm.mixin.injection.At;
16+
import org.spongepowered.asm.mixin.injection.Inject;
17+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
18+
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
19+
20+
@Mixin(BlockItem.class)
21+
public class BlockItemMixin {
22+
23+
24+
@Inject(method = "place", at = @At(value="INVOKE",target="Lnet/minecraft/world/item/ItemStack;consume(ILnet/minecraft/world/entity/LivingEntity;)V"), locals = LocalCapture.CAPTURE_FAILHARD)
25+
public void luafy$onScriptolderBlockPlaced(BlockPlaceContext blockPlaceContext, CallbackInfoReturnable<InteractionResult> cir, BlockPlaceContext no, BlockState no2, BlockPos blockPos, Level level, Player player, ItemStack itemStack, BlockState blockState, SoundType soundType) {
26+
27+
if (ScriptHolderBlockItem.isItem(itemStack)) {
28+
// get command block entity
29+
if (blockState.hasBlockEntity()) {
30+
BlockEntity be = level.getBlockEntity(blockPos);
31+
assert be != null;
32+
ScriptHolderBlockItem.ScriptHolderAttachment.giveHolderAttachment(be);
33+
}
34+
}
35+
36+
}
37+
}

src/main/java/dev/diamond/luafy/mixin/CommandBlockMixin.java

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package dev.diamond.luafy.mixin;
2+
3+
import dev.diamond.luafy.holder.HolderDialog;
4+
import net.minecraft.nbt.CompoundTag;
5+
import net.minecraft.nbt.Tag;
6+
import net.minecraft.resources.Identifier;
7+
import net.minecraft.server.MinecraftServer;
8+
import org.spongepowered.asm.mixin.Mixin;
9+
import org.spongepowered.asm.mixin.injection.At;
10+
import org.spongepowered.asm.mixin.injection.Inject;
11+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
12+
13+
import java.util.Optional;
14+
15+
@Mixin(MinecraftServer.class)
16+
public abstract class MinecraftServerMixin {
17+
18+
19+
@Inject(method = "handleCustomClickAction", at = @At("HEAD"), cancellable = true)
20+
public void luafy$scriptHolderDialogHandler(Identifier id, Optional<Tag> tag, CallbackInfo ci) {
21+
if (tag.isPresent()) {
22+
if (id == HolderDialog.ID) {
23+
24+
25+
System.out.println(tag);
26+
27+
ci.cancel();
28+
}
29+
}
30+
}
31+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"type": "minecraft:multi_action",
3+
"title": {
4+
"translate": "luafy.dialog.modify_script_holder.title",
5+
"fallback": "Modify Script Holder"
6+
},
7+
"body": {
8+
"type": "minecraft:plain_message",
9+
"contents": {
10+
"translate": "luafy.dialog.modify_script_holder.body",
11+
"fallback": "Set Script for Script Holder"
12+
}
13+
},
14+
"inputs": [
15+
{
16+
"type": "minecraft:text",
17+
"key": "id",
18+
"label": {
19+
"translate": "luafy.dialog.modify_script_holder.id_label",
20+
"fallback": "Script Id"
21+
}
22+
}
23+
],
24+
"actions": [
25+
{
26+
"label": {
27+
"translate": "luafy.dialog.button.confirm",
28+
"fallback": "Confirm"
29+
},
30+
"width": 100,
31+
"action": {
32+
"type": "minecraft:dynamic/custom",
33+
"id": "luafy:modify_script_holder"
34+
}
35+
}
36+
]
37+
}

0 commit comments

Comments
 (0)