mod for the islanders smp
at master 171 lines 6.3 kB view raw
1package net.radsteve.islanders.mixin; 2 3import com.google.common.collect.Iterators; 4import it.unimi.dsi.fastutil.ints.Int2ObjectMap; 5import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; 6import net.minecraft.item.Item; 7import net.minecraft.item.Items; 8import net.minecraft.network.packet.c2s.play.ClickSlotC2SPacket; 9import net.minecraft.registry.entry.RegistryEntry; 10import net.minecraft.registry.tag.ItemTags; 11import net.minecraft.screen.ScreenHandler; 12import net.minecraft.screen.slot.Slot; 13import net.minecraft.screen.sync.ItemStackHash; 14import net.minecraft.server.network.ServerPlayNetworkHandler; 15import net.minecraft.server.network.ServerPlayerEntity; 16import net.radsteve.islanders.Islanders; 17import org.spongepowered.asm.mixin.Mixin; 18import org.spongepowered.asm.mixin.Shadow; 19import org.spongepowered.asm.mixin.Unique; 20import org.spongepowered.asm.mixin.injection.At; 21import org.spongepowered.asm.mixin.injection.Inject; 22import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 23 24/// Warning: This is a huge mess and you should not touch this with a ten-foot pole 25/// This prevents special items from being put into bundles. 26/// Time counter: 5h 27@Mixin(ServerPlayNetworkHandler.class) 28public class BundleHandlerMixin { 29 @Shadow 30 public ServerPlayerEntity player; 31 32 /// DIRECTION ONE - item clicked first and dragged onto bundle 33 34 @Unique 35 private ClickSlotC2SPacket islanders$lastClickPacket = null; 36 37 @Unique 38 private Item islanders$lastClickedItem = null; 39 40 @Inject(method = "onClickSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/ScreenHandler;disableSyncing()V"), cancellable = true) 41 private void islanders$onClickSlot(ClickSlotC2SPacket packet, CallbackInfo ci) { 42 if (islanders$lastClickPacket == null) { 43 islanders$lastClickPacket = packet; 44 return; 45 } 46 47 final var modifiedStacks = packet.modifiedStacks(); 48 if (modifiedStacks.size() != 1) { 49 islanders$lastClickPacket = packet; 50 return; 51 } 52 53 final int slotIdx = Iterators.getOnlyElement(modifiedStacks.keySet().iterator()); 54 final Slot currentSlot = player.currentScreenHandler.slots.get(slotIdx); 55 if (!currentSlot.getStack().itemMatches((entry) -> entry.isIn(ItemTags.BUNDLES))) { 56 islanders$lastClickPacket = packet; 57 islanders$lastClickedItem = currentSlot.getStack().getItem(); 58 return; 59 } 60 61 if (!(modifiedStacks.get(slotIdx) instanceof ItemStackHash.Impl)) { 62 islanders$lastClickPacket = packet; 63 return; 64 } 65 66 final var lastModifiedStacks = islanders$lastClickPacket.modifiedStacks(); 67 if (lastModifiedStacks.size() != 1) { 68 islanders$lastClickPacket = packet; 69 return; 70 } 71 72 final Item specialItem = islanders$lastClickedItem; 73 74 if (!(specialItem == Items.DRAGON_EGG || specialItem == Items.MACE || specialItem == Items.POPPED_CHORUS_FRUIT /* TODO: extra validation */)) { 75 islanders$lastClickPacket = packet; 76 return; 77 } 78 79 final ScreenHandler screenHandler = player.currentScreenHandler; 80 81 for (Int2ObjectMap.Entry<ItemStackHash> entry : Int2ObjectMaps.fastIterable(packet.modifiedStacks())) { 82 screenHandler.setReceivedHash(entry.getIntKey(), entry.getValue()); 83 } 84 85 screenHandler.setReceivedCursorHash(packet.cursor()); 86 screenHandler.enableSyncing(); 87 screenHandler.updateToClient(); 88 screenHandler.sendContentUpdates(); 89 ci.cancel(); 90 91 islanders$lastClickPacket = packet; 92 93 Islanders.getLogger().info("{} tried moving special item into bundle", player.getNameForScoreboard()); 94 } 95 96 /// DIRECTION TWO - bundle clicked first and dragged onto item 97 /// This is a mess. Do not touch :) 98 99 @Unique 100 private ClickSlotC2SPacket islanders$lastClickPacket$0 = null; 101 @Unique 102 private RegistryEntry<Item> islanders$lastClickedItem$0 = null; 103 104 @Inject(method = "onClickSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/ScreenHandler;disableSyncing()V"), cancellable = true) 105 private void islanders$onClickSlot$0(ClickSlotC2SPacket packet, CallbackInfo ci) { 106 if (islanders$lastClickPacket$0 == null) { 107 islanders$lastClickPacket$0 = packet; 108 } 109 110 final var modifiedStacks = packet.modifiedStacks(); 111 112 if (islanders$lastClickedItem$0 == null) { 113 islanders$lastClickPacket$0 = packet; 114 if (!modifiedStacks.isEmpty()) { 115 final int slotIdx = Iterators.get(modifiedStacks.keySet().iterator(), 0); 116 final Slot currentSlot = player.currentScreenHandler.slots.get(slotIdx); 117 islanders$lastClickedItem$0 = currentSlot.getStack().getRegistryEntry(); 118 } 119 return; 120 } 121 122 final boolean lastIsBundle = islanders$lastClickedItem$0.isIn(ItemTags.BUNDLES); 123 124 if (modifiedStacks.isEmpty() && !lastIsBundle) { 125 islanders$lastClickPacket$0 = packet; 126 return; 127 } 128 129 RegistryEntry<Item> currentItem; 130 if (modifiedStacks.isEmpty()) { 131 currentItem = islanders$lastClickedItem$0; 132 } else { 133 final int slotIdx = Iterators.get(modifiedStacks.keySet().iterator(), 0); 134 final Slot currentSlot = player.currentScreenHandler.slots.get(slotIdx); 135 currentItem = currentSlot.getStack().getRegistryEntry(); 136 } 137 138 if (islanders$lastClickPacket$0 == null) { 139 return; 140 } 141 142 if (!islanders$lastClickedItem$0.isIn(ItemTags.BUNDLES)) { 143 islanders$lastClickPacket$0 = packet; 144 islanders$lastClickedItem$0 = currentItem; 145 return; 146 } 147 148 final Item specialItem = currentItem.value(); 149 150 if (!(specialItem == Items.DRAGON_EGG || specialItem == Items.MACE || specialItem == Items.POPPED_CHORUS_FRUIT /* TODO: extra validation */)) { 151 islanders$lastClickPacket$0 = packet; 152 islanders$lastClickedItem$0 = currentItem; 153 return; 154 } 155 156 final ScreenHandler screenHandler = player.currentScreenHandler; 157 158 for (Int2ObjectMap.Entry<ItemStackHash> entry : Int2ObjectMaps.fastIterable(packet.modifiedStacks())) { 159 screenHandler.setReceivedHash(entry.getIntKey(), entry.getValue()); 160 } 161 162 screenHandler.setReceivedCursorHash(packet.cursor()); 163 screenHandler.enableSyncing(); 164 screenHandler.updateToClient(); 165 screenHandler.sendContentUpdates(); 166 ci.cancel(); 167 168 islanders$lastClickPacket$0 = packet; 169 Islanders.getLogger().info("{} tried moving special item into bundle", player.getNameForScoreboard()); 170 } 171}