diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3a0a1f8..c5ca1c4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,16 +15,17 @@ jobs: 21, # Current Java LTS & minimum supported by Minecraft ] # and run on both Linux and Windows - os: [ubuntu-20.04, windows-2022] + os: [ubuntu-latest, windows-2022] runs-on: ${{ matrix.os }} steps: - name: checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: validate gradle wrapper - uses: gradle/wrapper-validation-action@v1 + uses: gradle/wrapper-validation-action@v3 - name: setup jdk ${{ matrix.java }} - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: + distribution: temurin java-version: ${{ matrix.java }} - name: make gradle wrapper executable if: ${{ runner.os != 'Windows' }} diff --git a/README.md b/README.md index d8ad379..0a4d66e 100644 --- a/README.md +++ b/README.md @@ -18,12 +18,13 @@ Addon to [AntiShadowPatch](https://modrinth.com/mod/antishadowpatch) that adds e * Disable Light Recalculation DataFixer * * When loading 1.19- chunks in 1.20+, the new light engine recalculates light in every single one of them. This option prevents it. If you have an EOL farm, you can load chunks with it once, and the EOL farm will work even without the mod enabled. * Max Count Per Stack -* * Increases max stack size of the item. +* * Increases max stack size of the item. * * Note that while vanilla clients can see overstacked items and hold them in the inventory, they can't really move them and will also be kicked if they see a give command output. You can see this behavior [here](https://www.youtube.com/watch?v=8DBCKKCNCYo). #### Commands (requires Fabric API) * /nsse swap - modifies a block in the player's hand to include a block entity. Similar to block entity swap, but you can carry it around. - +* /nsse swap - sets a block entity of the specific type at the specified position. +* /nsse exists - returns the block entity info at a specified pos if it exists. You can configure every setting individually in notsoshadowextras_config.json \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 4388c10..e0f5d63 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,12 +5,14 @@ org.gradle.jvmargs=-Xmx1G # check these on https://fabricmc.net/develop minecraft_version=1.21.4 yarn_mappings=1.21.4+build.8 - loader_version=0.16.10 - fabric_version=0.118.5+1.21.4 + loader_version=0.16.14 + +# Fabric API + fabric_version=0.119.2+1.21.4 # Mod Properties mod_version = 2.0.0 maven_group = ru.nern archives_base_name = not-so-shadow-extras-1.21.4 - fconfig_version=085f7c7 + fconfig_version=1.1.1 diff --git a/src/main/java/ru/nern/notsoshadowextras/NSSECommands.java b/src/main/java/ru/nern/notsoshadowextras/NSSECommands.java index 43ecff9..b5f9974 100644 --- a/src/main/java/ru/nern/notsoshadowextras/NSSECommands.java +++ b/src/main/java/ru/nern/notsoshadowextras/NSSECommands.java @@ -61,7 +61,7 @@ public static int blockEntityExists(ServerCommandSource source, BlockPos pos) { Text.literal("Block entity does not exist at this position"), false); }else{ source.sendFeedback(() -> - Text.literal(String.format("Block entity does exist. Type: %s", blockEntity.getType().getRegistryEntry().getIdAsString())), false); + Text.literal(String.format("Block entity does exist. Type: %s", Registries.BLOCK_ENTITY_TYPE.getId(blockEntity.getType()))), false); } return 1; diff --git a/src/main/java/ru/nern/notsoshadowextras/mixin/blocks/BulbBlockMixin.java b/src/main/java/ru/nern/notsoshadowextras/mixin/blocks/BulbBlockMixin.java index de3362b..ce5d58c 100644 --- a/src/main/java/ru/nern/notsoshadowextras/mixin/blocks/BulbBlockMixin.java +++ b/src/main/java/ru/nern/notsoshadowextras/mixin/blocks/BulbBlockMixin.java @@ -1,7 +1,5 @@ package ru.nern.notsoshadowextras.mixin.blocks; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.BulbBlock; @@ -12,7 +10,6 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import ru.nern.notsoshadowextras.NSSE; @Mixin(BulbBlock.class) public abstract class BulbBlockMixin extends Block { diff --git a/src/main/java/ru/nern/notsoshadowextras/mixin/blocks/CrafterBlockMixin.java b/src/main/java/ru/nern/notsoshadowextras/mixin/blocks/CrafterBlockMixin.java index acdae6b..1414cc8 100644 --- a/src/main/java/ru/nern/notsoshadowextras/mixin/blocks/CrafterBlockMixin.java +++ b/src/main/java/ru/nern/notsoshadowextras/mixin/blocks/CrafterBlockMixin.java @@ -4,7 +4,6 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.ModifyConstant; -import ru.nern.notsoshadowextras.NSSE; @Mixin(CrafterBlock.class) public class CrafterBlockMixin { diff --git a/src/main/java/ru/nern/notsoshadowextras/mixin/test/TestManagerMixin.java b/src/main/java/ru/nern/notsoshadowextras/mixin/test/TestManagerMixin.java deleted file mode 100644 index b928dd6..0000000 --- a/src/main/java/ru/nern/notsoshadowextras/mixin/test/TestManagerMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package ru.nern.notsoshadowextras.mixin.test; - -import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import net.minecraft.test.TestManager; -import net.minecraft.util.crash.CrashException; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(TestManager.class) -public class TestManagerMixin { - //Used to catch exceptions in game tests. Useful when testing update suppression, and yes, I didn't come with anything better - @WrapMethod(method = "tick") - private void notsoshadowextras$gameTestSuppressionCrashFix(Operation original) { - try { - original.call(); - } catch (StackOverflowError | ClassCastException | IllegalArgumentException | CrashException ignored) {} - } -} diff --git a/src/main/java/ru/nern/notsoshadowextras/test/NSSETests.java b/src/main/java/ru/nern/notsoshadowextras/test/NSSETests.java deleted file mode 100644 index 7f5487e..0000000 --- a/src/main/java/ru/nern/notsoshadowextras/test/NSSETests.java +++ /dev/null @@ -1,289 +0,0 @@ -package ru.nern.notsoshadowextras.test; - -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.block.Blocks; -import net.minecraft.block.CakeBlock; -import net.minecraft.block.entity.*; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.EquipmentSlot; -import net.minecraft.entity.ExperienceOrbEntity; -import net.minecraft.entity.boss.WitherEntity; -import net.minecraft.entity.decoration.ArmorStandEntity; -import net.minecraft.entity.mob.ZombieEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.projectile.WitherSkullEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.state.property.Properties; -import net.minecraft.test.GameTest; -import net.minecraft.test.PositionedException; -import net.minecraft.test.TestContext; -import net.minecraft.util.Hand; -import net.minecraft.util.Identifier; -import net.minecraft.util.crash.CrashException; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.GameMode; -import net.minecraft.world.event.GameEvent; -import ru.nern.notsoshadowextras.NSSECommands; - -public class NSSETests { - @GameTest(templateName = "notsoshadowextras:trapdoor_so_suppression") - public void stackoverflow_trapdoor_test(TestContext context) { - try { - context.setBlockState(3, 3, 3, Blocks.REDSTONE_WIRE); - }catch (CrashException e) { - context.setBlockState(4, 2, 2, Blocks.AIR); - context.complete(); - } - - } - - @GameTest(templateName = "notsoshadowextras:cce_suppression") - public void cce_suppression(TestContext context) throws CommandSyntaxException { - NSSECommands.swapAtPos(context.getWorld(), Identifier.ofVanilla("lectern"), - context.getAbsolutePos(new BlockPos(2, 2, 2))); - try { - context.setBlockState(4, 2, 2, Blocks.AIR); - }catch (CrashException e) { - context.expectBlock(Blocks.STONE_BUTTON, 4, 2, 1); - context.expectBlock(Blocks.STONE_BUTTON, 4, 3, 2); - context.expectBlock(Blocks.STONE_BUTTON, 4, 2, 3); - context.setBlockState(2, 2, 2, Blocks.AIR); - context.complete(); - } - } - - @GameTest(templateName = "notsoshadowextras:floating_components") - public void floating_components(TestContext context) { - int[][] positions = new int[][]{{1, 3}, {2, 3}, {3, 3}, {3, 2}, {3, 1}, {2, 1}, {1, 1}}; - - for(int[] position : positions) { - context.useBlock(new BlockPos(position[0], 2, position[1])); - } - - context.runAtTick(2, () -> { - context.expectBlock(Blocks.COMPARATOR, 1, 3, 3); - context.expectBlock(Blocks.REPEATER, 2, 3, 3); - context.expectBlock(Blocks.REDSTONE_WIRE, 3, 3, 3); - context.expectBlock(Blocks.RAIL, 3, 3, 2); - context.expectBlock(Blocks.POWERED_RAIL, 3, 3, 1); - context.expectBlock(Blocks.DETECTOR_RAIL, 2, 3, 1); - context.expectBlock(Blocks.ACTIVATOR_RAIL, 1, 3, 1); - context.complete(); - }); - } - - @GameTest(templateName = "notsoshadowextras:furnace_xp_dupe") - public void furnace_xp_dupe(TestContext context) throws CommandSyntaxException { - NSSECommands.swapAtPos(context.getWorld(), Identifier.ofVanilla("lectern"), - context.getAbsolutePos(new BlockPos(3, 2, 2))); - PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - - BlockPos furnacePos = new BlockPos(1, 2 ,2); - try { - context.getWorld().breakBlock(context.getAbsolutePos(furnacePos), false, player); - }catch (CrashException ignored) {} - - context.expectEntityAround(EntityType.EXPERIENCE_ORB, furnacePos, 4); - context.killAllEntities(ExperienceOrbEntity.class); - context.setBlockState(3, 2, 2, Blocks.AIR); - - context.setBlockState(furnacePos, Blocks.FURNACE); - context.getWorld().breakBlock(context.getAbsolutePos(furnacePos), false, player); - context.expectEntityAround(EntityType.EXPERIENCE_ORB, furnacePos, 4); - context.complete(); - } - - @GameTest(templateName = "notsoshadowextras:blockentity_swap") - public void block_entity_swap(TestContext context) throws CommandSyntaxException { - NSSECommands.swapAtPos(context.getWorld(), Identifier.ofVanilla("lectern"), - context.getAbsolutePos(new BlockPos(3, 2, 2))); - try { - context.setBlockState(1, 2, 2, Blocks.AIR); - - context.setBlockState(1, 2, 2, Blocks.CHEST); - }catch (CrashException ignored) {} - - context.setBlockState(3, 2, 2, Blocks.AIR); - context.checkBlockEntity(new BlockPos(1, 2, 2), blockEntity -> blockEntity instanceof HopperBlockEntity, - () -> "Block Entity Swap failed"); - - context.complete(); - } - - @GameTest(templateName = "notsoshadowextras:sound_suppression") - public void sound_suppression(TestContext context) throws CommandSyntaxException { - NSSECommands.swapAtPos(context.getWorld(), Identifier.ofVanilla("calibrated_sculk_sensor"), - context.getAbsolutePos(new BlockPos(1, 2, 2))); - - BlockPos pos = new BlockPos(1, 2, 1); - BlockPos absolute = context.getAbsolutePos(pos); - try { - context.getWorld().emitGameEvent(GameEvent.EXPLODE, absolute, GameEvent.Emitter.of(context.getBlockState(pos))); - }catch (IllegalArgumentException e) { - context.complete(); - } - } - - @GameTest(templateName = "notsoshadowextras:invulnerable_armor_stands") - public void armor_stands_invulnerable_to_wither_damage(TestContext context) { - ArmorStandEntity stand = context.getEntities(EntityType.ARMOR_STAND).getFirst(); - WitherEntity wither = new WitherEntity(EntityType.WITHER, context.getWorld()); - - WitherSkullEntity witherSkullEntity = new WitherSkullEntity(context.getWorld(), wither, new Vec3d(0, -10, 0)); - witherSkullEntity.setOwner(wither); - - witherSkullEntity.setPos(stand.getX(), stand.getY() + 6, stand.getZ()); - context.getWorld().spawnEntity(witherSkullEntity); - - context.runAtTick(100, () -> { - context.expectEntity(EntityType.ARMOR_STAND); - context.complete(); - }); - } - - @GameTest(templateName = "notsoshadowextras:shadow_items_in_mob_inventory") - public void shadow_items_in_mob_inventory(TestContext context) { - ItemStack armor = context.spawnItem(Items.DIAMOND_CHESTPLATE, 1, 2, 1).getStack(); - ItemStack handItem = context.spawnItem(Items.DIAMOND_SWORD, 1, 2, 1).getStack(); - - ZombieEntity zombie = context.getEntitiesAround(EntityType.ZOMBIE, new BlockPos(1, 2, 1), 5).getFirst(); - - context.runAtTick(40, () -> { - context.testEntity(zombie, zombieEntity -> zombie.getEquippedStack(EquipmentSlot.MAINHAND) == handItem && zombie.getEquippedStack(EquipmentSlot.CHEST) == armor, "has_shadow_stacks"); - context.complete(); - }); - } - - @GameTest(templateName = "notsoshadowextras:1gt_blocks") - public void blocks_1gt(TestContext context) { - BlockPos bulbPos = new BlockPos(3, 2 ,2); - context.setBlockState(bulbPos.up(), Blocks.REDSTONE_BLOCK); - context.checkBlockState(bulbPos, blockState -> !blockState.get(Properties.LIT), () -> "Expected the copper bulb to not be lit yet"); - - BlockPos crafterPos = new BlockPos(1, 2,2); - context.setBlockState(crafterPos.up(), Blocks.REDSTONE_BLOCK); - - context.runAtTick(1, () -> { - context.expectEntityAround(EntityType.ITEM, crafterPos, 4); - context.complete(); - }); - } - - @GameTest(templateName = "notsoshadowextras:sound_suppression_generic") - public void infinite_cake_fix(TestContext context) throws CommandSyntaxException { - NSSECommands.swapAtPos(context.getWorld(), Identifier.ofVanilla("calibrated_sculk_sensor"), - context.getAbsolutePos(new BlockPos(2, 2, 2))); - - BlockPos cakePos = new BlockPos(0, 2, 2); - try { - PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.getHungerManager().setFoodLevel(0); - context.useBlock(cakePos, player); - }catch (IllegalArgumentException ignored) {} - - context.checkBlockState(cakePos, blockState -> blockState.get(CakeBlock.BITES) != 0, () -> "Cake is a lie :)"); - context.setBlockState(2, 2, 2, Blocks.AIR); - context.complete(); - - } - - @GameTest(templateName = "notsoshadowextras:sound_suppression_generic") - public void item_interact_sound_dupe(TestContext context) throws CommandSyntaxException { - NSSECommands.swapAtPos(context.getWorld(), Identifier.ofVanilla("calibrated_sculk_sensor"), - context.getAbsolutePos(new BlockPos(2, 2, 2))); - - BlockPos interactionPos = new BlockPos(3, 1, 3); - - PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - - //ArmorStandItemMixin test - { - player.setStackInHand(Hand.MAIN_HAND, Items.ARMOR_STAND.getDefaultStack()); - try { - context.useBlock(interactionPos, player); - } catch (IllegalArgumentException ignored) {} - - context.expectEntityAround(EntityType.ARMOR_STAND, interactionPos, 2); - - if (player.getStackInHand(Hand.MAIN_HAND) != ItemStack.EMPTY) { - throw new PositionedException("Armor Stand got duped", context.getAbsolutePos(interactionPos), interactionPos, 0); - } - context.killAllEntities(); - } - - ((LecternBlockEntity)context.getBlockEntity(new BlockPos(2, 2, 0))).setCurrentPage(13); - - - //EndCrystalItemMixin test - { - player.setStackInHand(Hand.MAIN_HAND, Items.END_CRYSTAL.getDefaultStack()); - try { - context.useBlock(interactionPos, player); - } catch (IllegalArgumentException ignored) {} - - context.expectEntityAround(EntityType.END_CRYSTAL, interactionPos, 2); - - System.out.println("PLAYER ITEM: " + player.getStackInHand(Hand.MAIN_HAND).toString()); - if (player.getStackInHand(Hand.MAIN_HAND) != ItemStack.EMPTY) { - throw new PositionedException("End Crystal got duped", context.getAbsolutePos(interactionPos), interactionPos, 0); - } - context.killAllEntities(); - } - - //MinecartItemMixin test - { - player.setStackInHand(Hand.MAIN_HAND, Items.MINECART.getDefaultStack()); - context.setBlockState(interactionPos.up(), Blocks.RAIL); - try { - context.useBlock(interactionPos.up(), player); - } catch (IllegalArgumentException ignored) {} - - context.expectEntityAround(EntityType.MINECART, interactionPos, 2); - - if (player.getStackInHand(Hand.MAIN_HAND) != ItemStack.EMPTY) { - throw new PositionedException("Minecart got duped", context.getAbsolutePos(interactionPos), interactionPos, 0); - } - context.setBlockState(interactionPos.up(), Blocks.AIR); - context.killAllEntities(); - - context.setBlockState(2, 2, 2, Blocks.AIR); - context.complete(); - } - - - //BlockItemMixin test - { - player.setStackInHand(Hand.MAIN_HAND, Items.DIRT.getDefaultStack()); - try { - context.useBlock(interactionPos, player); - } catch (IllegalArgumentException ignored) {} - - context.expectBlock(Blocks.DIRT, interactionPos.up()); - - if (player.getStackInHand(Hand.MAIN_HAND) != ItemStack.EMPTY) { - throw new PositionedException("Generic Block Item got duped", context.getAbsolutePos(interactionPos), interactionPos, 0); - } - context.setBlockState(interactionPos.up(), Blocks.AIR); - } - - //FireChargeItemMixin test - { - player.setStackInHand(Hand.MAIN_HAND, Items.FIRE_CHARGE.getDefaultStack()); - try { - context.useBlock(interactionPos, player); - } catch (IllegalArgumentException ignored) {} - - context.expectBlock(Blocks.FIRE, interactionPos.up()); - - if (player.getStackInHand(Hand.MAIN_HAND) != ItemStack.EMPTY) { - throw new PositionedException("Fire Charge got duped", context.getAbsolutePos(interactionPos), interactionPos, 0); - } - context.setBlockState(interactionPos.up(), Blocks.AIR); - } - - - } - -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 53c92d6..c30a4db 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -19,9 +19,6 @@ "entrypoints": { "main": [ "ru.nern.notsoshadowextras.NSSE" - ], - "fabric-gametest": [ - "ru.nern.notsoshadowextras.test.NSSETests" ] }, "mixins": [ @@ -34,7 +31,8 @@ "java": ">=17" }, "recommends": { - "antishadowpatch": ">=2.0.0" + "antishadowpatch": ">=2.0.0", + "fabric-api": "*" }, "accessWidener": "notsoshadowextras.accesswidener" } diff --git a/src/main/resources/notsoshadowextras.mixins.json b/src/main/resources/notsoshadowextras.mixins.json index 6fe620f..42beb75 100644 --- a/src/main/resources/notsoshadowextras.mixins.json +++ b/src/main/resources/notsoshadowextras.mixins.json @@ -20,7 +20,6 @@ "sound_suppression.dupe_fix.FireChargeItemMixin", "sound_suppression.dupe_fix.MinecartItemMixin", "sound_suppression.dupe_fix.SpawnEggItemMixin", - "test.TestManagerMixin", "update_suppression.HopperBlockEntityMixin", "update_suppression.MinecraftServerMixin_CrashFix", "update_suppression.ServerCrashSafePLMixin_HideST",