mod for the islanders smp

should mostly be finished now

+599 -159
+4 -7
build.gradle
··· 12 12 } 13 13 14 14 repositories { 15 - // Add repositories to retrieve artifacts from in here. 16 - // You should only use this when depending on other mods because 17 - // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. 18 - // See https://docs.gradle.org/current/userguide/declaring_repositories.html 19 - // for more information about repositories. 20 15 maven { 21 16 url = "https://maven.mcbrawls.net/releases" 22 17 } 18 + 19 + maven { 20 + url = "https://maven.radsteve.net/public" 21 + } 23 22 } 24 23 25 24 dependencies { 26 - // To change the versions see the gradle.properties file 27 25 minecraft "com.mojang:minecraft:${project.minecraft_version}" 28 26 mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" 29 27 modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" 30 28 31 - // Fabric API. This is technically optional, but you probably want it anyway. 32 29 modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" 33 30 modImplementation "net.fabricmc:fabric-language-kotlin:${project.fabric_kotlin_version}" 34 31
+6
pack/assets/islanders/items/crown.json
··· 1 + { 2 + "model": { 3 + "type": "minecraft:model", 4 + "model": "islanders:item/crown" 5 + } 6 + }
+314
pack/assets/islanders/models/item/crown.json
··· 1 + { 2 + "format_version": "1.21.5", 3 + "credit": "Made with Blockbench", 4 + "textures": { 5 + "0": "islanders:item/crown_face_1", 6 + "1": "islanders:item/crown_face_2", 7 + "2": "islanders:item/crown_face_3", 8 + "3": "islanders:item/crown_face_4", 9 + "4": "islanders:item/crown_tops", 10 + "particle": "islanders:item/crown_face_1" 11 + }, 12 + "elements": [ 13 + { 14 + "from": [4, 0, 4], 15 + "to": [4, 2, 12], 16 + "rotation": {"angle": 0, "axis": "y", "origin": [4, 0, 4]}, 17 + "faces": { 18 + "north": {"uv": [0, 2, 8, 4], "texture": "#1"}, 19 + "east": {"uv": [0, 2, 8, 4], "texture": "#1"}, 20 + "south": {"uv": [0, 2, 8, 4], "texture": "#1"}, 21 + "west": {"uv": [0, 2, 8, 4], "texture": "#1"}, 22 + "up": {"uv": [0, 2, 8, 4], "texture": "#1"}, 23 + "down": {"uv": [0, 2, 8, 4], "texture": "#1"} 24 + } 25 + }, 26 + { 27 + "from": [4, 0, 4], 28 + "to": [12, 2, 4], 29 + "rotation": {"angle": 0, "axis": "y", "origin": [12, 0, 4]}, 30 + "faces": { 31 + "north": {"uv": [0, 0, 8, 2], "texture": "#0"}, 32 + "east": {"uv": [0, 0, 8, 2], "texture": "#0"}, 33 + "south": {"uv": [0, 0, 8, 2], "texture": "#0"}, 34 + "west": {"uv": [0, 0, 8, 2], "texture": "#0"}, 35 + "up": {"uv": [0, 0, 8, 2], "texture": "#0"}, 36 + "down": {"uv": [0, 0, 8, 2], "texture": "#0"} 37 + } 38 + }, 39 + { 40 + "from": [12, 0, 4], 41 + "to": [12, 2, 12], 42 + "rotation": {"angle": 0, "axis": "y", "origin": [12, 0, 12]}, 43 + "faces": { 44 + "north": {"uv": [0, 0, 8, 2], "texture": "#3"}, 45 + "east": {"uv": [0, 0, 8, 2], "texture": "#3"}, 46 + "south": {"uv": [0, 0, 8, 2], "texture": "#3"}, 47 + "west": {"uv": [0, 0, 8, 2], "texture": "#3"}, 48 + "up": {"uv": [0, 0, 8, 2], "texture": "#3"}, 49 + "down": {"uv": [0, 0, 8, 2], "texture": "#3"} 50 + } 51 + }, 52 + { 53 + "from": [4, 0, 12], 54 + "to": [12, 2, 12], 55 + "rotation": {"angle": 0, "axis": "y", "origin": [4, 0, 12]}, 56 + "faces": { 57 + "north": {"uv": [0, 2, 8, 4], "texture": "#2"}, 58 + "east": {"uv": [0, 2, 8, 4], "texture": "#2"}, 59 + "south": {"uv": [0, 2, 8, 4], "texture": "#2"}, 60 + "west": {"uv": [0, 2, 8, 4], "texture": "#2"}, 61 + "up": {"uv": [0, 2, 8, 4], "texture": "#2"}, 62 + "down": {"uv": [0, 2, 8, 4], "texture": "#2"} 63 + } 64 + }, 65 + { 66 + "from": [4, 2, 4], 67 + "to": [5, 3, 4], 68 + "rotation": {"angle": 0, "axis": "y", "origin": [4, 2, 4]}, 69 + "faces": { 70 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 71 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 72 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 73 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 74 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 75 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 76 + } 77 + }, 78 + { 79 + "from": [4, 2, 5], 80 + "to": [4, 3, 6], 81 + "rotation": {"angle": 0, "axis": "y", "origin": [4, 2, 6]}, 82 + "faces": { 83 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 84 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 85 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 86 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 87 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 88 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 89 + } 90 + }, 91 + { 92 + "from": [4, 2, 7], 93 + "to": [4, 3, 8], 94 + "rotation": {"angle": 0, "axis": "y", "origin": [4, 2, 8]}, 95 + "faces": { 96 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 97 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 98 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 99 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 100 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 101 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 102 + } 103 + }, 104 + { 105 + "from": [4, 2, 9], 106 + "to": [4, 3, 10], 107 + "rotation": {"angle": 0, "axis": "y", "origin": [4, 2, 10]}, 108 + "faces": { 109 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 110 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 111 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 112 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 113 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 114 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 115 + } 116 + }, 117 + { 118 + "from": [4, 2, 11], 119 + "to": [4, 3, 12], 120 + "rotation": {"angle": 0, "axis": "y", "origin": [4, 2, 12]}, 121 + "faces": { 122 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 123 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 124 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 125 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 126 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 127 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 128 + } 129 + }, 130 + { 131 + "from": [5, 2, 12], 132 + "to": [6, 3, 12], 133 + "rotation": {"angle": 0, "axis": "y", "origin": [6, 2, 12]}, 134 + "faces": { 135 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 136 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 137 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 138 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 139 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 140 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 141 + } 142 + }, 143 + { 144 + "from": [7, 2, 12], 145 + "to": [8, 3, 12], 146 + "rotation": {"angle": 0, "axis": "y", "origin": [8, 2, 12]}, 147 + "faces": { 148 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 149 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 150 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 151 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 152 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 153 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 154 + } 155 + }, 156 + { 157 + "from": [8, 2, 12], 158 + "to": [9, 3, 12], 159 + "rotation": {"angle": 0, "axis": "y", "origin": [9, 2, 12]}, 160 + "faces": { 161 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 162 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 163 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 164 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 165 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 166 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 167 + } 168 + }, 169 + { 170 + "from": [10, 2, 12], 171 + "to": [11, 3, 12], 172 + "rotation": {"angle": 0, "axis": "y", "origin": [11, 2, 12]}, 173 + "faces": { 174 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 175 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 176 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 177 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 178 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 179 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 180 + } 181 + }, 182 + { 183 + "from": [12, 2, 11], 184 + "to": [12, 3, 12], 185 + "rotation": {"angle": 0, "axis": "y", "origin": [12, 2, 11]}, 186 + "faces": { 187 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 188 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 189 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 190 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 191 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 192 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 193 + } 194 + }, 195 + { 196 + "from": [12, 2, 9], 197 + "to": [12, 3, 10], 198 + "rotation": {"angle": 0, "axis": "y", "origin": [12, 2, 9]}, 199 + "faces": { 200 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 201 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 202 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 203 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 204 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 205 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 206 + } 207 + }, 208 + { 209 + "from": [12, 2, 7], 210 + "to": [12, 3, 8], 211 + "rotation": {"angle": 0, "axis": "y", "origin": [12, 2, 7]}, 212 + "faces": { 213 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 214 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 215 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 216 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 217 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 218 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 219 + } 220 + }, 221 + { 222 + "from": [12, 2, 5], 223 + "to": [12, 3, 6], 224 + "rotation": {"angle": 0, "axis": "y", "origin": [12, 2, 5]}, 225 + "faces": { 226 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 227 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 228 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 229 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 230 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 231 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 232 + } 233 + }, 234 + { 235 + "from": [6, 2, 4], 236 + "to": [7, 3, 4], 237 + "rotation": {"angle": 0, "axis": "y", "origin": [6, 2, 4]}, 238 + "faces": { 239 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 240 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 241 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 242 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 243 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 244 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 245 + } 246 + }, 247 + { 248 + "from": [9, 2, 4], 249 + "to": [10, 3, 4], 250 + "rotation": {"angle": 0, "axis": "y", "origin": [9, 2, 4]}, 251 + "faces": { 252 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 253 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 254 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 255 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 256 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 257 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 258 + } 259 + }, 260 + { 261 + "from": [11, 2, 4], 262 + "to": [12, 3, 4], 263 + "rotation": {"angle": 0, "axis": "y", "origin": [11, 2, 4]}, 264 + "faces": { 265 + "north": {"uv": [0, 0, 1, 1], "texture": "#4"}, 266 + "east": {"uv": [0, 0, 1, 1], "texture": "#4"}, 267 + "south": {"uv": [0, 0, 1, 1], "texture": "#4"}, 268 + "west": {"uv": [0, 0, 1, 1], "texture": "#4"}, 269 + "up": {"uv": [0, 0, 1, 1], "texture": "#4"}, 270 + "down": {"uv": [0, 0, 1, 1], "texture": "#4"} 271 + } 272 + } 273 + ], 274 + "display": { 275 + "thirdperson_righthand": { 276 + "translation": [0, 1.25, -1.5], 277 + "scale": [0.5, 0.5, 0.5] 278 + }, 279 + "thirdperson_lefthand": { 280 + "translation": [0, 1.25, -1], 281 + "scale": [0.5, 0.5, 0.5] 282 + }, 283 + "firstperson_righthand": { 284 + "translation": [0, 5.75, 0] 285 + }, 286 + "firstperson_lefthand": { 287 + "translation": [0, 6.25, 0] 288 + }, 289 + "ground": { 290 + "translation": [0, 5.25, 0] 291 + }, 292 + "gui": { 293 + "rotation": [37.01, 42.22, -1.92], 294 + "translation": [0.25, 5.25, 0] 295 + }, 296 + "head": { 297 + "translation": [0, 18, 0], 298 + "scale": [2, 2, 2] 299 + }, 300 + "fixed": { 301 + "rotation": [-90, 0, 0], 302 + "translation": [0, 0, -14.75], 303 + "scale": [2, 2, 2] 304 + } 305 + }, 306 + "groups": [ 307 + { 308 + "name": "crown", 309 + "origin": [0, 0, 5], 310 + "color": 0, 311 + "children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 312 + } 313 + ] 314 + }
pack/assets/islanders/textures/item/crown_face_1.png

This is a binary file and will not be displayed.

pack/assets/islanders/textures/item/crown_face_2.png

This is a binary file and will not be displayed.

pack/assets/islanders/textures/item/crown_face_3.png

This is a binary file and will not be displayed.

pack/assets/islanders/textures/item/crown_face_4.png

This is a binary file and will not be displayed.

pack/assets/islanders/textures/item/crown_tops.png

This is a binary file and will not be displayed.

+19
pack/assets/minecraft/items/popped_chorus_fruit.json
··· 1 + { 2 + "model": { 3 + "type": "minecraft:select", 4 + "property": "minecraft:custom_model_data", 5 + "cases": [ 6 + { 7 + "when": "islanders", 8 + "model": { 9 + "type": "minecraft:model", 10 + "model": "islanders:item/crown" 11 + } 12 + } 13 + ], 14 + "fallback": { 15 + "type": "minecraft:model", 16 + "model": "minecraft:item/popped_chorus_fruit" 17 + } 18 + } 19 + }
+6
pack/pack.mcmeta
··· 1 + { 2 + "pack": { 3 + "description": "\u00a7b\u00a7l\u026as\u029f\u1d00\u0274\u1d05\u1d07\u0280s s\u1d0d\u1d18\u00a7r\n\u00a77\u1d04\u0280\u1d07\u1d00\u1d1b\u1d07\u1d05 \u0299\u028f \u00a7l\u1d1b\u1d00\u1d04", 4 + "pack_format": 55 5 + } 6 + }
pack/pack.png

This is a binary file and will not be displayed.

+4 -34
src/main/java/net/radsteve/islanders/mixin/ScreenHandlerMixin.java
··· 9 9 import net.minecraft.screen.ScreenHandler; 10 10 import net.minecraft.screen.slot.Slot; 11 11 import net.minecraft.screen.slot.SlotActionType; 12 - import net.minecraft.server.network.ServerPlayerEntity; 13 12 import net.minecraft.util.collection.DefaultedList; 14 13 import net.radsteve.islanders.SpecialItem; 15 - import net.radsteve.islanders.event.ItemTransferCallback; 16 14 import org.spongepowered.asm.mixin.Final; 17 15 import org.spongepowered.asm.mixin.Mixin; 18 16 import org.spongepowered.asm.mixin.Shadow; 19 - import org.spongepowered.asm.mixin.Unique; 20 17 import org.spongepowered.asm.mixin.injection.At; 21 18 import org.spongepowered.asm.mixin.injection.Inject; 22 19 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; ··· 28 25 public DefaultedList<Slot> slots; 29 26 30 27 @Shadow 31 - public abstract void setCursorStack(ItemStack stack); 32 - 33 - @Shadow public abstract Slot getSlot(int index); 34 - 35 - @Shadow public abstract ItemStack getCursorStack(); 36 - 37 - @Unique 38 - private void islanders$runHandlers(int slotIdx, PlayerEntity player, CallbackInfo ci) { 39 - final Slot slot = slots.get(slotIdx); 40 - final ItemStack stack = slot.getStack(); 41 - 42 - if (ItemTransferCallback.Companion.getEVENT().invoker().canTransfer(stack, (ServerPlayerEntity) player)) { 43 - return; 44 - } 45 - setCursorStack(ItemStack.EMPTY); 46 - 47 - ci.cancel(); 48 - } 49 - 50 - @Inject(method = "internalOnSlotClick", at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/slot/Slot;canTakeItems(Lnet/minecraft/entity/player/PlayerEntity;)Z"), cancellable = true) 51 - private void islanders$internalOnSlotClick$canTakeItems(int slotIdx, int button, SlotActionType slotActionType, PlayerEntity player, CallbackInfo ci) { 52 - // islanders$runHandlers(slotIdx, player, ci); 53 - } 28 + public abstract ItemStack getCursorStack(); 54 29 55 - @Inject(method = "internalOnSlotClick", at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/slot/Slot;onTakeItem(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/item/ItemStack;)V"), cancellable = true) 56 - private void islanders$internalOnSlotClick$onTakeItem(int slotIdx, int button, SlotActionType slotActionType, PlayerEntity player, CallbackInfo ci) { 57 - // islanders$runHandlers(slotIdx, player, ci); 58 - } 59 - 60 - @Inject(method = "internalOnSlotClick", at = @At("HEAD"), cancellable = true) 30 + /*@Inject(method = "internalOnSlotClick", at = @At("HEAD"), cancellable = true) 61 31 private void islanders$internalOnSlotClick$limits(int slotIndex, int button, SlotActionType actionType, PlayerEntity player, CallbackInfo ci) { 62 32 if ((ScreenHandler) (Object) this instanceof PlayerScreenHandler) { 63 33 return; ··· 74 44 return; 75 45 } 76 46 77 - final int actualScreenSlots = slots.size() - player.playerScreenHandler.slots.size() + 9 /* hotbar */; 47 + final int actualScreenSlots = slots.size() - player.playerScreenHandler.slots.size() + 9; 78 48 79 49 if (actionType == SlotActionType.SWAP) { 80 50 final ItemStack stack = getSlot(slotIndex).getStack(); ··· 94 64 if (ItemTransferCallback.Companion.getEVENT().invoker().canTransfer(getCursorStack(), (ServerPlayerEntity) player)) { 95 65 ci.cancel(); 96 66 } 97 - } 67 + }*/ 98 68 99 69 @Inject(method = "internalOnSlotClick", at = @At("HEAD"), cancellable = true) 100 70 private void islanders$internalOnSlotClick$shulkerBoxes(int slotIndex, int button, SlotActionType actionType, PlayerEntity player, CallbackInfo ci) {
-40
src/main/java/net/radsteve/islanders/mixin/SlotMixin.java
··· 1 - package net.radsteve.islanders.mixin; 2 - 3 - import net.minecraft.entity.player.PlayerEntity; 4 - import net.minecraft.item.ItemStack; 5 - import net.minecraft.screen.slot.Slot; 6 - import net.minecraft.server.network.ServerPlayerEntity; 7 - import net.radsteve.islanders.event.ItemTransferCallback; 8 - import org.spongepowered.asm.mixin.Mixin; 9 - import org.spongepowered.asm.mixin.Shadow; 10 - import org.spongepowered.asm.mixin.injection.At; 11 - import org.spongepowered.asm.mixin.injection.Inject; 12 - import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 13 - import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 14 - 15 - import java.util.Optional; 16 - 17 - @Mixin(Slot.class) 18 - public abstract class SlotMixin { 19 - @Shadow 20 - public abstract ItemStack getStack(); 21 - 22 - @Inject(method = "tryTakeStackRange", at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/slot/Slot;takeStack(I)Lnet/minecraft/item/ItemStack;"), cancellable = true) 23 - private void islanders$tryTakeStackRange(int min, int max, PlayerEntity player, CallbackInfoReturnable<Optional<ItemStack>> cir) { 24 - // final ItemStack stack = getStack(); 25 - // 26 - // if (ItemTransferCallback.Companion.getEVENT().invoker().canTransfer(stack, (ServerPlayerEntity) player)) { 27 - // return; 28 - // } 29 - // cir.setReturnValue(Optional.empty()); 30 - } 31 - 32 - @Inject(method = "onTakeItem", at = @At("HEAD"), cancellable = true) 33 - private void islanders$onTakeItem(PlayerEntity player, ItemStack stack, CallbackInfo ci) { 34 - // if (ItemTransferCallback.Companion.getEVENT().invoker().canTransfer(stack, (ServerPlayerEntity) player)) { 35 - // return; 36 - // } 37 - // 38 - // ci.cancel(); 39 - } 40 - }
+6 -1
src/main/kotlin/net/radsteve/islanders/Islanders.kt
··· 5 5 import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents 6 6 import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents 7 7 import net.mcbrawls.scheduler.AbsoluteScheduler 8 + import net.mcbrawls.scheduler.RelativeScheduler 8 9 import net.mcbrawls.scheduler.Scheduler 10 + import net.minecraft.advancement.criterion.Criteria 11 + import net.minecraft.advancement.criterion.TickCriterion 9 12 import net.minecraft.server.MinecraftServer 10 13 import net.radsteve.islanders.command.animacetionCommand 11 14 import net.radsteve.islanders.command.ruleCommand ··· 17 20 private val logger = LoggerFactory.getLogger("islanders") 18 21 public lateinit var server: MinecraftServer 19 22 private set 20 - public val scheduler: Scheduler = AbsoluteScheduler() 23 + public val scheduler: Scheduler = RelativeScheduler() 21 24 22 25 override fun onInitialize() { 23 26 logger.info("Initialising...") ··· 37 40 IslandersData 38 41 MaceAnimation 39 42 DefaultRules 43 + 44 + SpecialItem.entries.forEach { item -> item.criterion } // we love initializers 40 45 41 46 logger.info("Initialised!") 42 47 }
+11 -22
src/main/kotlin/net/radsteve/islanders/SpecialItem.kt
··· 1 1 package net.radsteve.islanders 2 2 3 3 import com.google.common.collect.Multimaps 4 + import net.minecraft.advancement.criterion.Criteria 5 + import net.minecraft.advancement.criterion.TickCriterion 4 6 import net.minecraft.component.DataComponentTypes 5 7 import net.minecraft.enchantment.Enchantments 6 8 import net.minecraft.entity.attribute.EntityAttributeModifier ··· 59 61 if (!player.hasStatusEffect(StatusEffects.GLOWING)) { 60 62 player.addStatusEffect(StatusEffectInstance(StatusEffects.GLOWING, 200, 0, true, false, false)) 61 63 } 62 - player.addStatusEffect(StatusEffectInstance(StatusEffects.SPEED, 20, 0, true, false, false)) 63 - player.addStatusEffect(StatusEffectInstance(StatusEffects.HASTE, 20, 0, true, false, false)) 64 - player.addStatusEffect(StatusEffectInstance(StatusEffects.RESISTANCE, 20, 0, true, false, false)) 65 - player.addStatusEffect(StatusEffectInstance(StatusEffects.JUMP_BOOST, 20, 0, true, false, false)) 66 - player.addStatusEffect(StatusEffectInstance(StatusEffects.STRENGTH, 20, 0, true, false, false)) 67 - player.addStatusEffect(StatusEffectInstance(StatusEffects.REGENERATION, 20, 0, true, false, false)) 64 + player.addStatusEffect(StatusEffectInstance(StatusEffects.SPEED, 200, 0, true, false, false)) 65 + player.addStatusEffect(StatusEffectInstance(StatusEffects.HASTE, 200, 0, true, false, false)) 66 + player.addStatusEffect(StatusEffectInstance(StatusEffects.RESISTANCE, 200, 0, true, false, false)) 67 + player.addStatusEffect(StatusEffectInstance(StatusEffects.JUMP_BOOST, 200, 0, true, false, false)) 68 + player.addStatusEffect(StatusEffectInstance(StatusEffects.STRENGTH, 200, 0, true, false, false)) 69 + player.addStatusEffect(StatusEffectInstance(StatusEffects.REGENERATION, 200, 0, true, false, false)) 68 70 } 69 71 70 72 override fun check(stack: ItemStack): Boolean { ··· 92 94 } 93 95 } 94 96 97 + public val criterion: TickCriterion = Criteria.register("islanders:$id", TickCriterion()) 98 + 95 99 public open fun deapplyEffects(player: ServerPlayerEntity) {} 96 100 public open fun applyEffects(player: ServerPlayerEntity, stack: ItemStack) {} 97 101 public abstract fun check(stack: ItemStack): Boolean ··· 110 114 } 111 115 112 116 public fun obtained(player: ServerPlayerEntity) { 113 - player.server.playerManager.broadcast( 114 - player.displayName!!.copy() 115 - .formatted(Formatting.RESET) 116 - .append( 117 - Text.literal(" has completed the challenge ") 118 - .append( 119 - Text.literal("[Obtain ").formatted(color) 120 - .append(Text.literal(displayName).formatted(Formatting.BOLD)) 121 - .append(Text.literal("]")), 122 - ) 123 - ), 124 - false 125 - ) 126 - 127 117 player.playSoundToPlayer(SoundEvents.ENTITY_ARROW_HIT_PLAYER, SoundCategory.MASTER, 0.5f, 1f) 128 - 129 118 IslandersData.obtained(id, player.uuid) 130 119 } 131 120 132 121 public fun pickedUp(player: ServerPlayerEntity) { 122 + criterion.trigger(player) 133 123 if (!IslandersData.obtained(id)) { 134 124 obtained(player) 135 - return 136 125 } 137 126 138 127 player.server.playerManager.broadcast(
-27
src/main/kotlin/net/radsteve/islanders/event/ItemTransferCallback.kt
··· 1 - package net.radsteve.islanders.event 2 - 3 - import net.fabricmc.fabric.api.event.Event 4 - import net.fabricmc.fabric.api.event.EventFactory 5 - import net.minecraft.item.ItemStack 6 - import net.minecraft.server.network.ServerPlayerEntity 7 - 8 - public fun interface ItemTransferCallback { 9 - public companion object { 10 - public val EVENT: Event<ItemTransferCallback> = EventFactory.createArrayBacked( 11 - ItemTransferCallback::class.java, ItemTransferCallback { _, _ -> true }) { callbacks -> 12 - ItemTransferCallback { item, player -> 13 - var canClick = true 14 - 15 - callbacks.forEach { callback -> 16 - if (!callback.canTransfer(item, player)) { 17 - canClick = false 18 - } 19 - } 20 - 21 - canClick 22 - } 23 - } 24 - } 25 - 26 - public fun canTransfer(item: ItemStack, player: ServerPlayerEntity): Boolean 27 - }
+95 -26
src/main/kotlin/net/radsteve/islanders/rule/RuleHandlers.kt
··· 1 1 package net.radsteve.islanders.rule 2 2 3 + import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents 3 4 import net.minecraft.entity.ItemEntity 4 5 import net.minecraft.item.ItemStack 6 + import net.minecraft.server.MinecraftServer 5 7 import net.minecraft.server.network.ServerPlayerEntity 8 + import net.minecraft.util.Hand 6 9 import net.radsteve.islanders.event.ItemPickupCallback 7 - import net.radsteve.islanders.event.ItemTransferCallback 8 10 import net.radsteve.islanders.event.ResizeItemEntityAndAddRemainingStackCallback 9 11 10 12 public object RuleHandlers { 11 13 init { 12 14 ItemPickupCallback.EVENT.register(Limits) 13 - ItemTransferCallback.EVENT.register(Limits) 14 15 ResizeItemEntityAndAddRemainingStackCallback.EVENT.register(Limits) 16 + ServerTickEvents.END_SERVER_TICK.register(Limits) 15 17 } 16 18 17 - public object Limits : ItemPickupCallback, ItemTransferCallback, ResizeItemEntityAndAddRemainingStackCallback { 19 + public object Limits : ItemPickupCallback, ResizeItemEntityAndAddRemainingStackCallback, ServerTickEvents.EndTick { 18 20 private fun check(item: ItemStack, player: ServerPlayerEntity): Boolean { 19 - // var cancelled = false 20 - // 21 - // RuleManager.ruled<ItemRule.Limit> { rule, limit -> 22 - // val itemsOnPlayer = player.inventory.mainStacks 23 - // .filter { item -> item.item === rule.item } 24 - // .sumOf(ItemStack::getCount) 25 - // 26 - // if (rule.item == item.item && item.count <= limit.maxAmount && itemsOnPlayer == 0) { 27 - // return@ruled 28 - // } 29 - // 30 - // if (itemsOnPlayer + item.count >= limit.maxAmount) { 31 - // cancelled = true 32 - // } 33 - // } 34 - // 35 - return true // FIXME - maybe? 21 + var cancelled = false 22 + 23 + RuleManager.ruled<ItemRule.Limit> { rule, limit -> 24 + if (rule.item != item.item) { 25 + return@ruled 26 + } 27 + 28 + val itemsOnPlayer = player.inventory.mainStacks 29 + .filter { item -> item.item === rule.item } 30 + .sumOf(ItemStack::getCount) 31 + 32 + if (item.count <= limit.maxAmount && itemsOnPlayer == 0) { 33 + return@ruled 34 + } 35 + 36 + if (itemsOnPlayer + item.count >= limit.maxAmount) { 37 + cancelled = true 38 + } 39 + } 40 + 41 + return !cancelled 36 42 } 37 43 38 44 override fun canPickUp(item: ItemStack, player: ServerPlayerEntity): Boolean { 39 45 return check(item, player) 40 46 } 41 47 42 - override fun canTransfer(item: ItemStack, player: ServerPlayerEntity): Boolean { 43 - return check(item, player) 44 - } 45 - 46 48 override fun resize(entity: ItemEntity, player: ServerPlayerEntity) { 47 49 RuleManager.ruled<ItemRule.Limit> { rule, limit -> 48 - if (rule.item != entity.stack.item) return@ruled 50 + if (rule.item != entity.stack.item) { 51 + return@ruled 52 + } 49 53 val itemsOnPlayer = player.inventory.mainStacks 50 54 .filter { item -> item.item === rule.item } 51 55 .sumOf(ItemStack::getCount) 52 56 val maxInsert = limit.maxAmount - itemsOnPlayer 53 - if (maxInsert <= 0) return@ruled 57 + if (maxInsert <= 0) { 58 + return@ruled 59 + } 54 60 val entityStack = entity.stack 55 61 val insertCount = minOf(entityStack.count, maxInsert) 56 62 57 63 if (insertCount > 0) { 58 64 val toInsert = ItemStack(entityStack.item, insertCount) 59 65 player.inventory.insertStack(toInsert) 66 + player.sendPickup(entity, insertCount) 60 67 entityStack.decrement(insertCount) 68 + } 69 + } 70 + } 71 + 72 + override fun onEndTick(server: MinecraftServer) { 73 + server.playerManager.playerList.forEach { player -> 74 + RuleManager.ruled<ItemRule.Limit> { rule, limit -> 75 + val inventory = player.inventory 76 + val item = rule.item 77 + 78 + val matchingIndices = mutableListOf<Int>() 79 + var totalCount = 0 80 + repeat(inventory.size()) { idx -> 81 + val stack = inventory.getStack(idx) 82 + if (stack.item === item && !stack.isEmpty) { 83 + matchingIndices += idx 84 + totalCount += stack.count 85 + } 86 + } 87 + 88 + if (totalCount <= limit.maxAmount || matchingIndices.isEmpty()) { 89 + return@ruled 90 + } 91 + 92 + var amountToDrop = 0 93 + 94 + val primaryIndex = matchingIndices.first() 95 + val primaryStack = inventory.getStack(primaryIndex) 96 + 97 + matchingIndices.drop(1).forEach { idx -> 98 + val stack = inventory.getStack(idx) 99 + if (!stack.isEmpty && stack.item === item) { 100 + val canAdd = primaryStack.maxCount - primaryStack.count 101 + val toMove = minOf(canAdd, stack.count) 102 + 103 + if (toMove > 0) { 104 + primaryStack.increment(toMove) 105 + stack.decrement(toMove) 106 + } 107 + 108 + if (!stack.isEmpty) { 109 + amountToDrop += stack.count 110 + stack.decrement(stack.count) 111 + } 112 + } 113 + } 114 + 115 + val toTrim = primaryStack.count - limit.maxAmount 116 + if (toTrim > 0) { 117 + primaryStack.decrement(toTrim) 118 + amountToDrop += toTrim 119 + } 120 + 121 + var remaining = amountToDrop 122 + while (remaining > 0) { 123 + val dropAmount = minOf(item.maxCount, remaining) 124 + val dropStack = ItemStack(item, dropAmount) 125 + val itemEntity = ItemEntity(player.world, player.x, player.y, player.z, dropStack) 126 + player.world.spawnEntity(itemEntity) 127 + player.swingHand(Hand.MAIN_HAND) 128 + remaining -= dropAmount 129 + } 61 130 } 62 131 } 63 132 }
+40
src/main/resources/data/islanders/advancement/crown.json
··· 1 + { 2 + "display": { 3 + "icon": { 4 + "id": "minecraft:popped_chorus_fruit", 5 + "components": { 6 + "minecraft:enchantment_glint_override": true, 7 + "minecraft:custom_model_data": { 8 + "strings": [ 9 + "islanders" 10 + ] 11 + } 12 + } 13 + }, 14 + "title": { 15 + "text": "Obtain ", 16 + "extra": [ 17 + { 18 + "text": "Islanders Crown", 19 + "bold": true 20 + } 21 + ], 22 + "color": "aqua" 23 + }, 24 + "description": "Obtain the Islanders crown by using the recipe with all Islanders armor trims.", 25 + "frame": "challenge", 26 + "show_toast": true, 27 + "announce_to_chat": true, 28 + "hidden": false 29 + }, 30 + "parent": "islanders:root", 31 + "criteria": { 32 + "crown": { 33 + "trigger": "islanders:crown" 34 + } 35 + }, 36 + "rewards": { 37 + "experience": 1000 38 + }, 39 + "sends_telemetry_event": false 40 + }
+32
src/main/resources/data/islanders/advancement/egg.json
··· 1 + { 2 + "display": { 3 + "icon": { 4 + "id": "minecraft:dragon_egg" 5 + }, 6 + "title": { 7 + "text": "Obtain ", 8 + "extra": [ 9 + { 10 + "text": "Dragon Egg", 11 + "bold": true 12 + } 13 + ], 14 + "color": "dark_purple" 15 + }, 16 + "description": "Obtain the Dragon Egg.", 17 + "frame": "challenge", 18 + "show_toast": true, 19 + "announce_to_chat": true, 20 + "hidden": false 21 + }, 22 + "parent": "islanders:root", 23 + "criteria": { 24 + "crown": { 25 + "trigger": "islanders:egg" 26 + } 27 + }, 28 + "rewards": { 29 + "experience": 1000 30 + }, 31 + "sends_telemetry_event": false 32 + }
+35
src/main/resources/data/islanders/advancement/mace.json
··· 1 + { 2 + "display": { 3 + "icon": { 4 + "id": "minecraft:mace", 5 + "components": { 6 + "minecraft:enchantment_glint_override": true 7 + } 8 + }, 9 + "title": { 10 + "text": "Obtain ", 11 + "extra": [ 12 + { 13 + "text": "Mace", 14 + "bold": true 15 + } 16 + ], 17 + "color": "gold" 18 + }, 19 + "description": "Obtain the Mace.", 20 + "frame": "challenge", 21 + "show_toast": true, 22 + "announce_to_chat": true, 23 + "hidden": false 24 + }, 25 + "parent": "islanders:root", 26 + "criteria": { 27 + "crown": { 28 + "trigger": "islanders:mace" 29 + } 30 + }, 31 + "rewards": { 32 + "experience": 1000 33 + }, 34 + "sends_telemetry_event": false 35 + }
+26
src/main/resources/data/islanders/advancement/root.json
··· 1 + { 2 + "display": { 3 + "icon": { 4 + "id": "minecraft:popped_chorus_fruit", 5 + "components": { 6 + "minecraft:enchantment_glint_override": true, 7 + "minecraft:custom_model_data": { 8 + "strings": [ 9 + "islanders" 10 + ] 11 + } 12 + } 13 + }, 14 + "title": "Islanders SMP", 15 + "frame": "challenge", 16 + "description": "Welcome to the Islanders SMP!", 17 + "show_toast": true, 18 + "announce_to_chat": false, 19 + "background": "minecraft:block/tube_coral_block" 20 + }, 21 + "criteria": { 22 + "tick": { 23 + "trigger": "minecraft:tick" 24 + } 25 + } 26 + }
src/main/resources/data/islanders/advancements/recipes/misc/islanders_crown.json src/main/resources/data/islanders/advancement/recipes/misc/islanders_crown.json
+1 -2
src/main/resources/islanders.mixins.json
··· 13 13 "LivingEntityAccessor", 14 14 "LivingEntityMixin", 15 15 "PlayerEntityMixin", 16 - "ScreenHandlerMixin", 17 - "SlotMixin" 16 + "ScreenHandlerMixin" 18 17 ], 19 18 "injectors": { 20 19 "defaultRequire": 1