diff --git a/.github/workflows/mainbuild.yml b/.github/workflows/mainbuild.yml index 25a8c8f..e28ede0 100644 --- a/.github/workflows/mainbuild.yml +++ b/.github/workflows/mainbuild.yml @@ -15,11 +15,11 @@ jobs: steps: - name: checkout repository uses: actions/checkout@v3 - - name: setup jdk 17 + - name: setup jdk 21 uses: actions/setup-java@v3 with: distribution: "adopt" - java-version: 17 + java-version: 21 - name: Cache Gradle packages uses: actions/cache@v3 with: diff --git a/.github/workflows/prbuild.yml b/.github/workflows/prbuild.yml index e03b160..25934c0 100644 --- a/.github/workflows/prbuild.yml +++ b/.github/workflows/prbuild.yml @@ -8,11 +8,11 @@ jobs: steps: - name: checkout repository uses: actions/checkout@v3 - - name: setup jdk 17 + - name: setup jdk 21 uses: actions/setup-java@v3 with: distribution: "adopt" - java-version: 17 + java-version: 21 - name: Cache Gradle packages uses: actions/cache@v3 with: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 67ab623..7a24831 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -12,11 +12,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v2 with: distribution: "adopt" - java-version: 17 + java-version: 21 cache: "gradle" - name: Grant execute permission to gradlew run: chmod +x gradlew diff --git a/build.gradle b/build.gradle index c5cde3c..6b8781b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.5-SNAPSHOT' + id 'fabric-loom' version '1.7-SNAPSHOT' id 'maven-publish' } @@ -9,8 +9,8 @@ repositories { } } -sourceCompatibility = JavaVersion.VERSION_17 -targetCompatibility = JavaVersion.VERSION_17 +sourceCompatibility = JavaVersion.VERSION_21 +targetCompatibility = JavaVersion.VERSION_21 archivesBaseName = project.archives_base_name version = project.minecraft_version + '-' + project.mod_version @@ -59,8 +59,8 @@ tasks.withType(JavaCompile).configureEach { // If Javadoc is generated, this must be specified in that task too. it.options.encoding = "UTF-8" - // Minecraft 1.18 (pre2) upwards uses Java 17. - it.options.release = 17 + // Minecraft 1.20.5 upwards uses Java 21. + it.options.release = 21 } java { diff --git a/gradle.properties b/gradle.properties index 810628b..8fc4f48 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,9 +2,9 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/use -minecraft_version=1.20.3 -yarn_mappings=1.20.3+build.1 -loader_version=0.15.7 +minecraft_version=1.21.1 +yarn_mappings=1.21.1+build.3 +loader_version=0.16.3 # Mod Properties mod_version=1.3.1 maven_group=carpet-addons-not-found @@ -12,5 +12,5 @@ archives_base_name=carpet-addons-not-found # Dependencies # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api # fabric_version=0.25.1+build.416-1.16 -carpet_core_version=1.4.128+v231205 -carpet_minecraft_version=1.20.3 +carpet_core_version=1.4.147+v240613 +carpet_minecraft_version=1.21 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index c1962a7..d64cd49 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 509c4a2..9355b41 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index aeb74cb..1aa94a4 100644 --- a/gradlew +++ b/gradlew @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 93e3f59..25da30d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/src/main/java/carpetaddonsnotfound/flowerpotrules/AlwaysPickFlowersFromPotsRule.java b/src/main/java/carpetaddonsnotfound/flowerpotrules/AlwaysPickFlowersFromPotsRule.java new file mode 100644 index 0000000..c5001a4 --- /dev/null +++ b/src/main/java/carpetaddonsnotfound/flowerpotrules/AlwaysPickFlowersFromPotsRule.java @@ -0,0 +1,30 @@ +package carpetaddonsnotfound.flowerpotrules; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.FlowerPotBlock; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.event.GameEvent; + +public class AlwaysPickFlowersFromPotsRule { + public static boolean execute(BlockState blockState, World world, BlockPos blockPos, PlayerEntity player) { + Block potBlock = blockState.getBlock(); + Block content; + if (!(potBlock instanceof FlowerPotBlock flowerPotBlock) || (content = flowerPotBlock.getContent()) == Blocks.AIR) { + return false; + } + + ItemStack itemStack = new ItemStack(content); + if (!player.giveItemStack(itemStack)) { + player.dropItem(itemStack, false); + } + + world.setBlockState(blockPos, Blocks.FLOWER_POT.getDefaultState(), 3); + world.emitGameEvent(player, GameEvent.BLOCK_CHANGE, blockPos); + return true; + } +} diff --git a/src/main/java/carpetaddonsnotfound/flowerpotrules/FlowerPotRuleManager.java b/src/main/java/carpetaddonsnotfound/flowerpotrules/FlowerPotRuleManager.java new file mode 100644 index 0000000..8d56cd2 --- /dev/null +++ b/src/main/java/carpetaddonsnotfound/flowerpotrules/FlowerPotRuleManager.java @@ -0,0 +1,32 @@ +package carpetaddonsnotfound.flowerpotrules; + +import carpetaddonsnotfound.CarpetAddonsNotFoundSettings; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import java.util.Map; + +public class FlowerPotRuleManager { + public static boolean executeRule(Map contentToPotted, + PlayerEntity player, + Hand hand, + World world, + BlockPos blockPos, + BlockState blockState, + + Block currentContent) { + if (CarpetAddonsNotFoundSettings.replaceFlowersInPots) { + return ReplaceFlowersInPotsRule.execute(contentToPotted, player, hand, world, blockPos, currentContent); + } + + if (CarpetAddonsNotFoundSettings.alwaysPickFlowersFromPots) { + return AlwaysPickFlowersFromPotsRule.execute(blockState, world, blockPos, player); + } + + return false; + } +} diff --git a/src/main/java/carpetaddonsnotfound/flowerpotrules/ReplaceFlowersInPotsRule.java b/src/main/java/carpetaddonsnotfound/flowerpotrules/ReplaceFlowersInPotsRule.java new file mode 100644 index 0000000..f94fec8 --- /dev/null +++ b/src/main/java/carpetaddonsnotfound/flowerpotrules/ReplaceFlowersInPotsRule.java @@ -0,0 +1,43 @@ +package carpetaddonsnotfound.flowerpotrules; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.FlowerPotBlock; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.stat.Stats; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.event.GameEvent; + +import java.util.Map; + +public class ReplaceFlowersInPotsRule { + public static boolean execute(Map contentToPotted, PlayerEntity player, Hand hand, World world, + BlockPos blockPos, Block currentContent) { + ItemStack playerStack = player.getStackInHand(hand); + Item item = playerStack.getItem(); + Block newPot = + (item instanceof BlockItem ? contentToPotted.getOrDefault(((BlockItem) item).getBlock(), Blocks.AIR) + : Blocks.AIR); + if (!(newPot instanceof FlowerPotBlock) || ((FlowerPotBlock) newPot).getContent() == currentContent) { + return false; + } + + ItemStack dropStack = new ItemStack(currentContent.asItem(), 1); + if (!player.giveItemStack(dropStack)) { + player.dropStack(dropStack); + } + + BlockState blockState = newPot.getDefaultState(); + world.setBlockState(blockPos, blockState, 3); + world.emitGameEvent(player, GameEvent.BLOCK_CHANGE, blockPos); + player.incrementStat(Stats.POT_FLOWER); + playerStack.decrementUnlessCreative(1, player); + return true; + } +} diff --git a/src/main/java/carpetaddonsnotfound/instantmining/BlockBreakingSpeedRatioCalculator.java b/src/main/java/carpetaddonsnotfound/instantmining/BlockBreakingSpeedRatioCalculator.java index 71e8adf..3b0d715 100644 --- a/src/main/java/carpetaddonsnotfound/instantmining/BlockBreakingSpeedRatioCalculator.java +++ b/src/main/java/carpetaddonsnotfound/instantmining/BlockBreakingSpeedRatioCalculator.java @@ -1,15 +1,23 @@ package carpetaddonsnotfound.instantmining; import net.minecraft.block.BlockState; +import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.effect.StatusEffectUtil; import net.minecraft.item.ItemStack; +import net.minecraft.registry.DynamicRegistryManager; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.entry.RegistryEntry; public class BlockBreakingSpeedRatioCalculator { - public static float getBlockBreakingSpeedRatio(LivingEntity livingEntity, BlockState blockState) { - int efficiencyLevel = EnchantmentHelper.getEfficiency(livingEntity); + public static float getBlockBreakingSpeedRatio(DynamicRegistryManager registryManager, LivingEntity livingEntity, + BlockState blockState) { + RegistryEntry efficienyRegistryEntry = + registryManager.get(RegistryKeys.ENCHANTMENT).entryOf(Enchantments.EFFICIENCY); + int efficiencyLevel = EnchantmentHelper.getLevel(efficienyRegistryEntry, livingEntity.getWeaponStack()); int hasteAmplifier = StatusEffectUtil.getHasteAmplifier(livingEntity); ItemStack mainHand = livingEntity.getEquippedStack(EquipmentSlot.MAINHAND); @@ -20,7 +28,7 @@ public static float getBlockBreakingSpeedRatio(LivingEntity livingEntity, BlockS return 1.0f; } - var instantMiningRatioCalculator = new CompositeInstantMiningRatioCalculator(); + CompositeInstantMiningRatioCalculator instantMiningRatioCalculator = new CompositeInstantMiningRatioCalculator(); return instantMiningRatioCalculator.getInstantMiningRatio(blockState, mainHand.getItem()); } } diff --git a/src/main/java/carpetaddonsnotfound/mixins/ClientPlayerEntity_SpectatorPlayersUsePortalsMixin.java b/src/main/java/carpetaddonsnotfound/mixins/ClientPlayerEntity_SpectatorPlayersUsePortalsMixin.java new file mode 100644 index 0000000..24e9123 --- /dev/null +++ b/src/main/java/carpetaddonsnotfound/mixins/ClientPlayerEntity_SpectatorPlayersUsePortalsMixin.java @@ -0,0 +1,29 @@ +package carpetaddonsnotfound.mixins; + +import carpetaddonsnotfound.mixins.invokers.EntityInvokerMixin; +import carpetaddonsnotfound.spectatorplayersuseportals.SpectatorPlayersUsePortalsRule; +import com.mojang.authlib.GameProfile; +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.MovementType; +import net.minecraft.util.math.Vec3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayerEntity.class) +public abstract class ClientPlayerEntity_SpectatorPlayersUsePortalsMixin extends AbstractClientPlayerEntity implements + EntityInvokerMixin { + + public ClientPlayerEntity_SpectatorPlayersUsePortalsMixin(ClientWorld world, + GameProfile profile) { + super(world, profile); + } + + @Inject(method = "move", at = @At("TAIL")) + private void movePlayerInSpectator(MovementType movementType, Vec3d movement, CallbackInfo ci) { + SpectatorPlayersUsePortalsRule.movePlayerInSpectator(this); + } +} diff --git a/src/main/java/carpetaddonsnotfound/mixins/DispenserBlock_GetCustomBehaviorMixin.java b/src/main/java/carpetaddonsnotfound/mixins/DispenserBlock_GetCustomBehaviorMixin.java index 743b6df..26b8925 100644 --- a/src/main/java/carpetaddonsnotfound/mixins/DispenserBlock_GetCustomBehaviorMixin.java +++ b/src/main/java/carpetaddonsnotfound/mixins/DispenserBlock_GetCustomBehaviorMixin.java @@ -1,6 +1,7 @@ package carpetaddonsnotfound.mixins; import carpetaddonsnotfound.dispenser.CarpetAddonsNotFoundDispenserBehaviors; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.block.BlockState; import net.minecraft.block.DispenserBlock; import net.minecraft.block.dispenser.DispenserBehavior; @@ -13,7 +14,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(DispenserBlock.class) public abstract class DispenserBlock_GetCustomBehaviorMixin { @@ -39,20 +39,19 @@ public abstract class DispenserBlock_GetCustomBehaviorMixin { method = "dispense", at = @At( value = "INVOKE", - target = "Lnet/minecraft/block/DispenserBlock;getBehaviorForItem(Lnet/minecraft/item/ItemStack;)" + - "Lnet/minecraft/block/dispenser/DispenserBehavior;" + target = "Lnet/minecraft/block/DispenserBlock;getBehaviorForItem(Lnet/minecraft/world/World;" + + "Lnet/minecraft/item/ItemStack;)Lnet/minecraft/block/dispenser/DispenserBehavior;" ), - locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true ) private void dispenseCustomBehaviorNonEmptyItemStack(ServerWorld serverWorld, BlockState state, BlockPos pos, CallbackInfo ci, - DispenserBlockEntity dispenserBlockEntity, - BlockPointer blockPointer, - int i, - ItemStack itemStack) { + @Local DispenserBlockEntity dispenserBlockEntity, + @Local BlockPointer blockPointer, + @Local int i, + @Local ItemStack itemStack) { DispenserBehavior customBehavior = CarpetAddonsNotFoundDispenserBehaviors.getCustomDispenserBehavior( serverWorld, @@ -91,16 +90,14 @@ private void dispenseCustomBehaviorNonEmptyItemStack(ServerWorld serverWorld, target = "Lnet/minecraft/server/world/ServerWorld;syncWorldEvent" + "(ILnet/minecraft/util/math/BlockPos;I)V" ), - locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true ) private void dispenseCustomBehaviorEmptyItemStack(ServerWorld serverWorld, BlockState state, BlockPos pos, CallbackInfo ci, - DispenserBlockEntity dispenserBlockEntity, - BlockPointer blockPointer, - int i) { + @Local DispenserBlockEntity dispenserBlockEntity, + @Local BlockPointer blockPointer) { ItemStack itemStack = ItemStack.EMPTY; DispenserBehavior customBehavior = CarpetAddonsNotFoundDispenserBehaviors.getCustomDispenserBehavior( diff --git a/src/main/java/carpetaddonsnotfound/mixins/EndFrameBlock_EyeToggleMixin.java b/src/main/java/carpetaddonsnotfound/mixins/EndFrameBlock_EyeToggleMixin.java deleted file mode 100644 index 8b33477..0000000 --- a/src/main/java/carpetaddonsnotfound/mixins/EndFrameBlock_EyeToggleMixin.java +++ /dev/null @@ -1,47 +0,0 @@ -package carpetaddonsnotfound.mixins; - -import carpetaddonsnotfound.CarpetAddonsNotFoundSettings; -import carpetaddonsnotfound.helpers.EndPortalFrameHelper; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.EndPortalFrameBlock; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.state.property.BooleanProperty; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(EndPortalFrameBlock.class) -public abstract class EndFrameBlock_EyeToggleMixin extends Block { - @Shadow - @Final - public static BooleanProperty EYE; - - public EndFrameBlock_EyeToggleMixin(Settings settings) { - super(settings); - } - - @SuppressWarnings("deprecation") // It gets called by the new method anyway, so we can fix when they actually change it - @Override - public ActionResult onUse(BlockState state, - World world, - BlockPos pos, - PlayerEntity player, - Hand hand, - BlockHitResult hit) { - if (CarpetAddonsNotFoundSettings.dropEyesOfEnderFromEndPortalFrame && state.get(EYE)) { - EndPortalFrameHelper.setEmptyEndPortalFrameState(world, state, pos); - dropStack(world, pos.up(), new ItemStack(Items.ENDER_EYE, 1)); - return ActionResult.success(world.isClient); - } - - return ActionResult.FAIL; - } -} diff --git a/src/main/java/carpetaddonsnotfound/mixins/EnderEyeItem_EyeToggleMixin.java b/src/main/java/carpetaddonsnotfound/mixins/EnderEyeItem_EyeToggleMixin.java new file mode 100644 index 0000000..c12730d --- /dev/null +++ b/src/main/java/carpetaddonsnotfound/mixins/EnderEyeItem_EyeToggleMixin.java @@ -0,0 +1,38 @@ +package carpetaddonsnotfound.mixins; + +import carpetaddonsnotfound.CarpetAddonsNotFoundSettings; +import carpetaddonsnotfound.helpers.EndPortalFrameHelper; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.EndPortalFrameBlock; +import net.minecraft.item.*; +import net.minecraft.util.ActionResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(EnderEyeItem.class) +public abstract class EnderEyeItem_EyeToggleMixin extends Item { + protected EnderEyeItem_EyeToggleMixin(Settings settings) { + super(settings); + } + + @Inject(method = "useOnBlock", at = @At("HEAD"), cancellable = true) + private void useOnBlockDropEyesOfEnder(ItemUsageContext context, CallbackInfoReturnable cir) { + World world = context.getWorld(); + BlockPos blockPos = context.getBlockPos(); + BlockState blockState = world.getBlockState(blockPos); + if (!CarpetAddonsNotFoundSettings.dropEyesOfEnderFromEndPortalFrame || + !blockState.isOf((Blocks.END_PORTAL_FRAME)) || !blockState.get(EndPortalFrameBlock.EYE)) { + return; + } + + EndPortalFrameHelper.setEmptyEndPortalFrameState(world, blockState, blockPos); + Block.dropStack(world, blockPos.up(), new ItemStack(Items.ENDER_EYE, 1)); + cir.setReturnValue(ActionResult.success(world.isClient)); + } +} diff --git a/src/main/java/carpetaddonsnotfound/mixins/FlowerPotBlockMixin.java b/src/main/java/carpetaddonsnotfound/mixins/FlowerPotBlockMixin.java new file mode 100644 index 0000000..524f839 --- /dev/null +++ b/src/main/java/carpetaddonsnotfound/mixins/FlowerPotBlockMixin.java @@ -0,0 +1,47 @@ +package carpetaddonsnotfound.mixins; + +import carpetaddonsnotfound.flowerpotrules.FlowerPotRuleManager; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.FlowerPotBlock; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; +import net.minecraft.util.ItemActionResult; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +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.CallbackInfoReturnable; + +import java.util.Map; + +@Mixin(FlowerPotBlock.class) +public abstract class FlowerPotBlockMixin { + @Shadow + @Final + private static Map CONTENT_TO_POTTED; + + @Shadow + public abstract Block getContent(); + + @Inject( + method = "onUseWithItem", + at = @At( + value = "HEAD" + ), + cancellable = true + ) + private void onUseWithItemCustom(ItemStack stack, BlockState state, World world, BlockPos pos, PlayerEntity player, + Hand hand, BlockHitResult hit, CallbackInfoReturnable cir) { + boolean ruleExecuted = + FlowerPotRuleManager.executeRule(CONTENT_TO_POTTED, player, hand, world, pos, state, getContent()); + if (ruleExecuted) { + cir.setReturnValue(ItemActionResult.success(world.isClient)); + } + } +} diff --git a/src/main/java/carpetaddonsnotfound/mixins/FlowerPotBlock_PickFlowersFromPotsMixin.java b/src/main/java/carpetaddonsnotfound/mixins/FlowerPotBlock_PickFlowersFromPotsMixin.java deleted file mode 100644 index 058c9d4..0000000 --- a/src/main/java/carpetaddonsnotfound/mixins/FlowerPotBlock_PickFlowersFromPotsMixin.java +++ /dev/null @@ -1,57 +0,0 @@ -package carpetaddonsnotfound.mixins; - -import carpetaddonsnotfound.CarpetAddonsNotFoundSettings; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.FlowerPotBlock; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.event.GameEvent; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(FlowerPotBlock.class) -public abstract class FlowerPotBlock_PickFlowersFromPotsMixin { - @Inject( - method = "onUse", - at = @At( - value = "TAIL" - ), - cancellable = true - ) - private void onUse(BlockState state, - World world, - BlockPos pos, - PlayerEntity player, - Hand hand, - BlockHitResult hit, - CallbackInfoReturnable cir) { - Block potBlock = state.getBlock(); - Block content; - if (!CarpetAddonsNotFoundSettings.alwaysPickFlowersFromPots || - !(potBlock instanceof FlowerPotBlock flowerPotBlock) || (content = flowerPotBlock.getContent()) == Blocks.AIR) { - return; - } - world.setBlockState(pos, Blocks.FLOWER_POT.getDefaultState(), Block.NOTIFY_ALL); - world.emitGameEvent(player, GameEvent.BLOCK_CHANGE, pos); - cir.setReturnValue(ActionResult.SUCCESS); - if (player.isCreative()) { - return; - } - ItemStack contentStack = new ItemStack(content.asItem(), 1); - if (player.getStackInHand(hand).isEmpty()) { - player.setStackInHand(hand, contentStack); - } - else if (!player.giveItemStack(contentStack)) { - player.dropStack(contentStack); - } - } -} diff --git a/src/main/java/carpetaddonsnotfound/mixins/FlowerPotBlock_ReplaceFlowersInPots.java b/src/main/java/carpetaddonsnotfound/mixins/FlowerPotBlock_ReplaceFlowersInPots.java deleted file mode 100644 index 3a09950..0000000 --- a/src/main/java/carpetaddonsnotfound/mixins/FlowerPotBlock_ReplaceFlowersInPots.java +++ /dev/null @@ -1,76 +0,0 @@ -package carpetaddonsnotfound.mixins; - -import carpetaddonsnotfound.CarpetAddonsNotFoundSettings; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.FlowerPotBlock; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.BlockItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.event.GameEvent; -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.CallbackInfoReturnable; - -import java.util.Map; - -@Mixin(FlowerPotBlock.class) -public abstract class FlowerPotBlock_ReplaceFlowersInPots { - @Shadow - @Final - private static Map CONTENT_TO_POTTED; - - @Shadow - @Final - private Block content; - - @Shadow - public abstract Block getContent(); - - @Inject( - method = "onUse", - at = @At( - value = "TAIL", - shift = At.Shift.BEFORE - ), - cancellable = true - ) - private void onUse(BlockState state, - World world, - BlockPos pos, - PlayerEntity player, - Hand hand, - BlockHitResult hit, - CallbackInfoReturnable cir) { - ItemStack playerStack = player.getStackInHand(hand); - Item item = playerStack.getItem(); - Block newPot = (item instanceof BlockItem ? CONTENT_TO_POTTED.getOrDefault(((BlockItem) item).getBlock(), Blocks.AIR) : Blocks.AIR); - if (!CarpetAddonsNotFoundSettings.replaceFlowersInPots || - !(newPot instanceof FlowerPotBlock) || ((FlowerPotBlock) newPot).getContent() == this.getContent()) { - return; - } - cir.setReturnValue(ActionResult.SUCCESS); - world.setBlockState(pos, newPot.getDefaultState(), 3); - world.emitGameEvent(player, GameEvent.BLOCK_CHANGE, pos); - if (player.isCreative()) { - return; - } - playerStack.decrement(1); - ItemStack dropStack = new ItemStack(this.content.asItem(), 1); - if (playerStack.isEmpty()) { - player.setStackInHand(hand, dropStack); - } else if (!player.giveItemStack(dropStack)) { - player.dropStack(dropStack); - } - } -} diff --git a/src/main/java/carpetaddonsnotfound/mixins/LivingEntity_DropAllXpOnPlayerDeathMixin.java b/src/main/java/carpetaddonsnotfound/mixins/LivingEntity_DropAllXpOnPlayerDeathMixin.java index 3d9a25e..c8710ac 100644 --- a/src/main/java/carpetaddonsnotfound/mixins/LivingEntity_DropAllXpOnPlayerDeathMixin.java +++ b/src/main/java/carpetaddonsnotfound/mixins/LivingEntity_DropAllXpOnPlayerDeathMixin.java @@ -1,32 +1,43 @@ package carpetaddonsnotfound.mixins; import carpetaddonsnotfound.CarpetAddonsNotFoundSettings; +import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.world.ServerWorld; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(LivingEntity.class) public abstract class LivingEntity_DropAllXpOnPlayerDeathMixin { - @Redirect(method = "dropXp", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getXpToDrop()I")) - private int onDropXp(LivingEntity instance) { - if (!((LivingEntity) instance instanceof PlayerEntity player) || - !CarpetAddonsNotFoundSettings.dropAllXpOnPlayerDeath) { - return instance.getXpToDrop(); + @Redirect(method = "dropXp", at = @At(value = "INVOKE", + target = "Lnet/minecraft/entity/LivingEntity;getXpToDrop" + + "(Lnet/minecraft/server/world/ServerWorld;" + + "Lnet/minecraft/entity/Entity;)I")) + private int onDropXp(LivingEntity instance, ServerWorld world, Entity attacker) { + if (!CarpetAddonsNotFoundSettings.dropAllXpOnPlayerDeath || + !((LivingEntity) instance instanceof PlayerEntity player)) { + return instance.getXpToDrop(world, attacker); } - var xp = player.experienceLevel + player.experienceProgress; - if (xp <= 16) { - xp = (float) (Math.pow(xp, 2) + 6 * xp); - } - else if (xp < 32) { - xp = (float) (2.5 * Math.pow(xp, 2) - 40.5 * xp + 360); + double totalExperience = calculateTotalExperience(player); + return (int)Math.ceil(totalExperience); + } + + // This exists because just using the totalExperience field doesn't work if levels have been set separately to xp points + @Unique + private double calculateTotalExperience(PlayerEntity player) { + double xpLevel = player.experienceLevel + player.experienceProgress; + if (xpLevel < 17) { + return Math.pow(xpLevel, 2) + 6 * xpLevel; } - else { - xp = (float) (4.5 * Math.pow(xp, 2) - 162.5 * xp + 2220); + + if (xpLevel < 32) { + return 2.5 * Math.pow(xpLevel, 2) - 40.5 * xpLevel + 360; } - return (int) Math.ceil(xp); + return 4.5 * Math.pow(xpLevel, 2) - 162.5 * xpLevel + 2220; } } diff --git a/src/main/java/carpetaddonsnotfound/mixins/NetherPortalBlock_PortalSpectatorDelayMixin.java b/src/main/java/carpetaddonsnotfound/mixins/NetherPortalBlock_PortalSpectatorDelayMixin.java new file mode 100644 index 0000000..b79f9c2 --- /dev/null +++ b/src/main/java/carpetaddonsnotfound/mixins/NetherPortalBlock_PortalSpectatorDelayMixin.java @@ -0,0 +1,21 @@ +package carpetaddonsnotfound.mixins; + +import carpetaddonsnotfound.CarpetAddonsNotFoundSettings; +import net.minecraft.block.NetherPortalBlock; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.world.ServerWorld; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(value = NetherPortalBlock.class) +public abstract class NetherPortalBlock_PortalSpectatorDelayMixin { + @Inject(method = "getPortalDelay", at = @At("HEAD"), cancellable = true) + private void getSpectatorPortalDelay(ServerWorld world, Entity entity, CallbackInfoReturnable cir) { + if (entity instanceof PlayerEntity playerEntity && playerEntity.isSpectator()) { + cir.setReturnValue(CarpetAddonsNotFoundSettings.portalSpectatorDelay); + } + } +} diff --git a/src/main/java/carpetaddonsnotfound/mixins/PlayerEntity_InstantMineMixin.java b/src/main/java/carpetaddonsnotfound/mixins/PlayerEntity_InstantMineMixin.java index 6c44eee..32f1e36 100644 --- a/src/main/java/carpetaddonsnotfound/mixins/PlayerEntity_InstantMineMixin.java +++ b/src/main/java/carpetaddonsnotfound/mixins/PlayerEntity_InstantMineMixin.java @@ -1,16 +1,17 @@ package carpetaddonsnotfound.mixins; import carpetaddonsnotfound.instantmining.BlockBreakingSpeedRatioCalculator; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.block.BlockState; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(PlayerEntity.class) public abstract class PlayerEntity_InstantMineMixin extends LivingEntity { @@ -34,10 +35,11 @@ protected PlayerEntity_InstantMineMixin(EntityType entit at = @At( value = "TAIL" ), - locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true) - public void getInstantMiningBlockBreakingSpeed(BlockState block, CallbackInfoReturnable cir, float f) { - float blockBreakingSpeedRatio = BlockBreakingSpeedRatioCalculator.getBlockBreakingSpeedRatio(this, block); + public void getInstantMiningBlockBreakingSpeed(BlockState block, CallbackInfoReturnable cir, @Local float f) { + DynamicRegistryManager registryManager = this.getWorld().getRegistryManager(); + float blockBreakingSpeedRatio = + BlockBreakingSpeedRatioCalculator.getBlockBreakingSpeedRatio(registryManager, this, block); cir.setReturnValue(f * blockBreakingSpeedRatio); } } diff --git a/src/main/java/carpetaddonsnotfound/mixins/PlayerEntity_PortalSpectatorDelayMixin.java b/src/main/java/carpetaddonsnotfound/mixins/PlayerEntity_PortalSpectatorDelayMixin.java deleted file mode 100644 index 44d56b5..0000000 --- a/src/main/java/carpetaddonsnotfound/mixins/PlayerEntity_PortalSpectatorDelayMixin.java +++ /dev/null @@ -1,23 +0,0 @@ -package carpetaddonsnotfound.mixins; - -import carpetaddonsnotfound.CarpetAddonsNotFoundSettings; -import net.minecraft.entity.player.PlayerEntity; -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.CallbackInfoReturnable; - -// A priority less than 1000 is required for this mixin to be loaded before base carpet. -@Mixin(value = PlayerEntity.class, priority = 999) -public abstract class PlayerEntity_PortalSpectatorDelayMixin { - @Shadow - public abstract boolean isSpectator(); - - @Inject(method = "getMaxNetherPortalTime", at = @At("HEAD"), cancellable = true) - private void getMaxNetherPortalTime(CallbackInfoReturnable cir) { - if (this.isSpectator()) { - cir.setReturnValue(CarpetAddonsNotFoundSettings.portalSpectatorDelay); - } - } -} diff --git a/src/main/java/carpetaddonsnotfound/mixins/ServerPlayerEntity_SpectatorPlayersUsePortalsMixin.java b/src/main/java/carpetaddonsnotfound/mixins/ServerPlayerEntity_SpectatorPlayersUsePortalsMixin.java index 6a0b220..764da37 100644 --- a/src/main/java/carpetaddonsnotfound/mixins/ServerPlayerEntity_SpectatorPlayersUsePortalsMixin.java +++ b/src/main/java/carpetaddonsnotfound/mixins/ServerPlayerEntity_SpectatorPlayersUsePortalsMixin.java @@ -1,76 +1,27 @@ package carpetaddonsnotfound.mixins; -import carpetaddonsnotfound.CarpetAddonsNotFoundSettings; -import carpetaddonsnotfound.network.ServerNetworkHandler; +import carpetaddonsnotfound.mixins.invokers.EntityInvokerMixin; +import carpetaddonsnotfound.spectatorplayersuseportals.SpectatorPlayersUsePortalsRule; import com.mojang.authlib.GameProfile; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.entity.EndGatewayBlockEntity; import net.minecraft.entity.MovementType; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.registry.RegistryKey; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; @Mixin(ServerPlayerEntity.class) -public abstract class ServerPlayerEntity_SpectatorPlayersUsePortalsMixin extends PlayerEntity { +public abstract class ServerPlayerEntity_SpectatorPlayersUsePortalsMixin extends PlayerEntity implements + EntityInvokerMixin { public ServerPlayerEntity_SpectatorPlayersUsePortalsMixin(World world, BlockPos pos, float yaw, GameProfile gameProfile) { super(world, pos, yaw, gameProfile); } - @Shadow - public abstract boolean isSpectator(); - - /* - Calls original move() function then performs additional action - this.getBlockPos() returns coordinates of the lowest block that spectator's bounding box would be touching - if it was in survival game-mode at the same coordinates with default pose. - */ @Override public void move(MovementType type, Vec3d movement) { - World world = this.getWorld(); super.move(type, movement); - if (!CarpetAddonsNotFoundSettings.spectatorPlayersUsePortals || !this.isSpectator() || this.hasVehicle() || - this.hasPassengers() || !this.canUsePortals()) { - return; - } - //shift one up makes it seem like bounding box is closer to camera. - BlockPos pos = this.getBlockPos().add(0, 1, 0); - BlockState state = world.getBlockState(pos); - Block block = state.getBlock(); - //from EndPortalBlock.onEntityCollision() - if (block == Blocks.END_PORTAL) { - RegistryKey registryKey = world.getRegistryKey() == World.END ? World.OVERWORLD : World.END; - ServerWorld serverWorld = ((ServerWorld) world).getServer().getWorld(registryKey); - if (serverWorld == null) { - return; - } - this.moveToWorld(serverWorld); - } - if (block == Blocks.END_GATEWAY) { - EndGatewayBlockEntity.tryTeleportingEntity(world, pos, state, this, - (EndGatewayBlockEntity) world.getBlockEntity(pos)); - } - //from NetherPortalBlock.onEntityCollision() - if (block == Blocks.NETHER_PORTAL) { - this.setInNetherPortal(pos); - SyncSetInNetherPortalWithClient(world, pos); - } - } - - private void SyncSetInNetherPortalWithClient(World world, BlockPos pos) { - if (world.isClient()) { - return; - } - - ServerPlayerEntity thisServerPlayerEntity = (ServerPlayerEntity) (Object) this; - ServerNetworkHandler.sendSpectatorPlayerIsInPortalData(thisServerPlayerEntity, pos); + SpectatorPlayersUsePortalsRule.movePlayerInSpectator(this); } } diff --git a/src/main/java/carpetaddonsnotfound/mixins/invokers/EntityInvokerMixin.java b/src/main/java/carpetaddonsnotfound/mixins/invokers/EntityInvokerMixin.java index 8b9f396..9b87d33 100644 --- a/src/main/java/carpetaddonsnotfound/mixins/invokers/EntityInvokerMixin.java +++ b/src/main/java/carpetaddonsnotfound/mixins/invokers/EntityInvokerMixin.java @@ -14,4 +14,7 @@ public interface EntityInvokerMixin { @Invoker("getZ") double invokeGetZ(); + + @Invoker("tryCheckBlockCollision") + void invokeTryCheckBlockCollision(); } diff --git a/src/main/java/carpetaddonsnotfound/mixins/network/ClientPlayNetworkHandler_CustomPacketsMixin.java b/src/main/java/carpetaddonsnotfound/mixins/network/ClientPlayNetworkHandler_CustomPacketsMixin.java deleted file mode 100644 index a249a83..0000000 --- a/src/main/java/carpetaddonsnotfound/mixins/network/ClientPlayNetworkHandler_CustomPacketsMixin.java +++ /dev/null @@ -1,35 +0,0 @@ -package carpetaddonsnotfound.mixins.network; - -import carpetaddonsnotfound.network.CarpetAddonsNotFoundClient; -import carpetaddonsnotfound.network.ClientNetworkHandler; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientCommonNetworkHandler; -import net.minecraft.client.network.ClientConnectionState; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.network.ClientConnection; -import net.minecraft.network.packet.CustomPayload; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -/** - * Most of this is from carpet base but tweaked to work for us. We can reuse this for other rules if needed, so any - * handlers should be placed in the ClientNetworkHandler class. - */ -@Mixin(ClientPlayNetworkHandler.class) -public abstract class ClientPlayNetworkHandler_CustomPacketsMixin extends ClientCommonNetworkHandler { - protected ClientPlayNetworkHandler_CustomPacketsMixin(MinecraftClient minecraft, - ClientConnection connection, - ClientConnectionState commonListenerCookie) { - super(minecraft, connection, commonListenerCookie); - } - - @Inject(method = "onCustomPayload", at = @At(value = "HEAD"), cancellable = true) - private void onCustomPayload(CustomPayload packet, CallbackInfo ci) { - if (packet instanceof CarpetAddonsNotFoundClient.CarpetAddonsNotFoundPayload cpp) { - ClientNetworkHandler.handleData(cpp.data(), client.player); - ci.cancel(); - } - } -} diff --git a/src/main/java/carpetaddonsnotfound/mixins/network/CustomPayloadS2CPacket_CustomPacketMixin.java b/src/main/java/carpetaddonsnotfound/mixins/network/CustomPayloadS2CPacket_CustomPacketMixin.java deleted file mode 100644 index eaf337f..0000000 --- a/src/main/java/carpetaddonsnotfound/mixins/network/CustomPayloadS2CPacket_CustomPacketMixin.java +++ /dev/null @@ -1,26 +0,0 @@ -package carpetaddonsnotfound.mixins.network; - -import carpetaddonsnotfound.network.CarpetAddonsNotFoundClient; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.CustomPayload; -import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(CustomPayloadS2CPacket.class) -public abstract class CustomPayloadS2CPacket_CustomPacketMixin { - @Inject(method = "readPayload", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/network/packet/s2c/common/CustomPayloadS2CPacket;readUnknownPayload(Lnet/minecraft/util/Identifier;Lnet/minecraft/network/PacketByteBuf;)Lnet/minecraft/network/packet/UnknownCustomPayload;"), - cancellable = true) - private static void onCustomPayload(Identifier resourceLocation, PacketByteBuf friendlyByteBuf, CallbackInfoReturnable cir) - { - if (resourceLocation.equals(CarpetAddonsNotFoundClient.CARPET_ADDONS_NOT_FOUND_CHANNEL)) - { - cir.setReturnValue(new CarpetAddonsNotFoundClient.CarpetAddonsNotFoundPayload(friendlyByteBuf)); - } - } -} diff --git a/src/main/java/carpetaddonsnotfound/network/CarpetAddonsNotFoundClient.java b/src/main/java/carpetaddonsnotfound/network/CarpetAddonsNotFoundClient.java deleted file mode 100644 index a025d55..0000000 --- a/src/main/java/carpetaddonsnotfound/network/CarpetAddonsNotFoundClient.java +++ /dev/null @@ -1,29 +0,0 @@ -package carpetaddonsnotfound.network; - -import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.CustomPayload; -import net.minecraft.util.Identifier; - -/** - * Client for the mod. Most of this is taken from CarpetClient - */ -public final class CarpetAddonsNotFoundClient { - public static final Identifier CARPET_ADDONS_NOT_FOUND_CHANNEL = new Identifier("carpet-addons-not-found"); - - public record CarpetAddonsNotFoundPayload(NbtCompound data) implements CustomPayload { - public CarpetAddonsNotFoundPayload(PacketByteBuf input) { - this(input.readNbt()); - } - - @Override - public void write(PacketByteBuf output) { - output.writeNbt(data); - } - - @Override - public Identifier id() { - return CARPET_ADDONS_NOT_FOUND_CHANNEL; - } - } -} diff --git a/src/main/java/carpetaddonsnotfound/network/ClientNetworkHandler.java b/src/main/java/carpetaddonsnotfound/network/ClientNetworkHandler.java deleted file mode 100644 index d6b4a72..0000000 --- a/src/main/java/carpetaddonsnotfound/network/ClientNetworkHandler.java +++ /dev/null @@ -1,54 +0,0 @@ -package carpetaddonsnotfound.network; - -import carpetaddonsnotfound.CarpetAddonsNotFoundSettings; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import net.minecraft.util.math.BlockPos; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.BiConsumer; - -/** - * Network handler for the game client. Following what the base Carpet mod is doing here in terms of design. - * Unfortunately doesn't look like we can hook into any of what carpet provides. - */ -public class ClientNetworkHandler { - private static final Map> dataHandlers = new HashMap<>(); - - static { - dataHandlers.put(NbtCompoundKeys.SpectatorPlayerInPortal.TAG, ((clientPlayerEntity, nbtElement) -> { - NbtCompound serverPlayerData = (NbtCompound) nbtElement; - int serverPlayerBlockPosX = serverPlayerData.getInt(NbtCompoundKeys.SpectatorPlayerInPortal.BLOCK_POS_X); - int serverPlayerBlockPosY = serverPlayerData.getInt(NbtCompoundKeys.SpectatorPlayerInPortal.BLOCK_POS_Y); - int serverPlayerBlockPosZ = serverPlayerData.getInt(NbtCompoundKeys.SpectatorPlayerInPortal.BLOCK_POS_Z); - BlockPos serverPlayerBlockPos = new BlockPos(serverPlayerBlockPosX, serverPlayerBlockPosY, serverPlayerBlockPosZ); - clientPlayerEntity.setInNetherPortal(serverPlayerBlockPos); - })); - } - - /** - * Taken from carpet base; handles incoming data, and it is executed on the main Minecraft Thread - * - * @param compound - * the nbt data - * @param player - * the client side player - */ - public static void handleData(NbtCompound compound, ClientPlayerEntity player) { - for (String key : compound.getKeys()) { - if (!dataHandlers.containsKey(key)) { - CarpetAddonsNotFoundSettings.LOG.error("Unknown carpet addons not found data: " + key); - continue; - } - - try { - dataHandlers.get(key).accept(player, compound.get(key)); - } - catch (Exception exc) { - CarpetAddonsNotFoundSettings.LOG.info("Corrupt carpet addons not found data for " + key); - } - } - } -} diff --git a/src/main/java/carpetaddonsnotfound/network/NbtCompoundKeys.java b/src/main/java/carpetaddonsnotfound/network/NbtCompoundKeys.java deleted file mode 100644 index 24c8411..0000000 --- a/src/main/java/carpetaddonsnotfound/network/NbtCompoundKeys.java +++ /dev/null @@ -1,13 +0,0 @@ -package carpetaddonsnotfound.network; - -/** - * Holds the NbtCompound keys used when syncing the client and server sides. - */ -public class NbtCompoundKeys { - public static class SpectatorPlayerInPortal { - public static String BLOCK_POS_X = "SpectatorPlayerBlockPosX"; - public static String BLOCK_POS_Y = "SpectatorPlayerBlockPosY"; - public static String BLOCK_POS_Z = "SpectatorPlayerBlockPosZ"; - public static String TAG = "SpectatorInPortal"; - } -} diff --git a/src/main/java/carpetaddonsnotfound/network/ServerNetworkHandler.java b/src/main/java/carpetaddonsnotfound/network/ServerNetworkHandler.java deleted file mode 100644 index 99732cb..0000000 --- a/src/main/java/carpetaddonsnotfound/network/ServerNetworkHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -package carpetaddonsnotfound.network; - -import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.math.BlockPos; - -/** - * Network handler for the game server. Following what the base Carpet mod is doing here in terms of design. - * Unfortunately doesn't look like we can hook into any of what carpet provides. - */ -public final class ServerNetworkHandler { - /** - * Sends a packet to the client player with the block position information for the nether portal block the (spectator) - * server side player is currently in - * - * @param player - * the server side player - * @param playerBlockPos - * the player block position - */ - public static void sendSpectatorPlayerIsInPortalData(ServerPlayerEntity player, BlockPos playerBlockPos) { - DataBuilder data = DataBuilder.create().withBlockPos(playerBlockPos); - player.networkHandler.sendPacket(data.build()); - } - - private static class DataBuilder { - private final NbtCompound tag; - - private DataBuilder() { - this.tag = new NbtCompound(); - } - - private static DataBuilder create() { - return new DataBuilder(); - } - - private DataBuilder withBlockPos(BlockPos blockPos) { - NbtCompound blockPosNbtCompound = new NbtCompound(); - blockPosNbtCompound.putInt(NbtCompoundKeys.SpectatorPlayerInPortal.BLOCK_POS_X, blockPos.getX()); - blockPosNbtCompound.putInt(NbtCompoundKeys.SpectatorPlayerInPortal.BLOCK_POS_Y, blockPos.getY()); - blockPosNbtCompound.putInt(NbtCompoundKeys.SpectatorPlayerInPortal.BLOCK_POS_Z, blockPos.getZ()); - tag.put(NbtCompoundKeys.SpectatorPlayerInPortal.TAG, blockPosNbtCompound); - return this; - } - - private CustomPayloadS2CPacket build() { - return new CustomPayloadS2CPacket(new CarpetAddonsNotFoundClient.CarpetAddonsNotFoundPayload(tag)); - } - } -} diff --git a/src/main/java/carpetaddonsnotfound/spectatorplayersuseportals/SpectatorPlayersUsePortalsRule.java b/src/main/java/carpetaddonsnotfound/spectatorplayersuseportals/SpectatorPlayersUsePortalsRule.java new file mode 100644 index 0000000..4653e99 --- /dev/null +++ b/src/main/java/carpetaddonsnotfound/spectatorplayersuseportals/SpectatorPlayersUsePortalsRule.java @@ -0,0 +1,37 @@ +package carpetaddonsnotfound.spectatorplayersuseportals; + +import carpetaddonsnotfound.CarpetAddonsNotFoundSettings; +import carpetaddonsnotfound.mixins.invokers.EntityInvokerMixin; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.world.World; + +public class SpectatorPlayersUsePortalsRule { + public static void movePlayerInSpectator(PlayerEntity playerEntity) { + final boolean allowVehicles = false; + World world = playerEntity.getWorld(); + if (!CarpetAddonsNotFoundSettings.spectatorPlayersUsePortals || !playerEntity.isSpectator() || + !playerEntity.canUsePortals(allowVehicles)) { + return; + } + + //shift one up makes it seem like bounding box is closer to camera. + BlockPos actualPlayerPos = playerEntity.getBlockPos(); + BlockPos shiftedPlayerPos = actualPlayerPos.add(0, 1, 0); + BlockState blockState = world.getBlockState(shiftedPlayerPos); + Block block = blockState.getBlock(); + if (block != Blocks.END_PORTAL && block != Blocks.END_GATEWAY && block != Blocks.NETHER_PORTAL) { + return; + } + + // Bit hacky but this temporarily sets the players bounding box to be closer to the camera for the check block + // collision method + playerEntity.setBoundingBox(new Box(shiftedPlayerPos)); + ((EntityInvokerMixin) playerEntity).invokeTryCheckBlockCollision(); + playerEntity.setBoundingBox(new Box(actualPlayerPos)); + } +} diff --git a/src/main/resources/carpet-addons-not-found.mixins.json b/src/main/resources/carpet-addons-not-found.mixins.json index 82b98a3..dee17e1 100644 --- a/src/main/resources/carpet-addons-not-found.mixins.json +++ b/src/main/resources/carpet-addons-not-found.mixins.json @@ -1,23 +1,22 @@ { "required": true, "package": "carpetaddonsnotfound.mixins", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "mixins": [ "DispenserBlock_GetCustomBehaviorMixin", + "EnderEyeItem_EyeToggleMixin", "EndermanEntity_PassiveEndermenMixin", - "EndFrameBlock_EyeToggleMixin", "ExperienceOrbEntity_XpBubbleColumnInteractionMixin", "FlowerBlock_ReplaceFlowersMixin", - "FlowerPotBlock_PickFlowersFromPotsMixin", - "FlowerPotBlock_ReplaceFlowersInPots", + "FlowerPotBlockMixin", "LivingEntity_DropAllXpOnPlayerDeathMixin", + "NetherPortalBlock_PortalSpectatorDelayMixin", "PhantomSpawnerMixin", "PistonBlock_MovableEmptyEndPortalFrameMixin", "PistonBlock_MovableSpawnersMixin", "PistonExtensionBlock_MovableEmptyEndPortalFrameMixin", "PlayerEntity_CreativePlayerOneHitKillMixin", "PlayerEntity_InstantMineMixin", - "PlayerEntity_PortalSpectatorDelayMixin", "ServerChunkManager_PhantomsObeyHostileMobCapMixin", "ServerPlayerEntity_SpectatorPlayersUsePortalsMixin", "SpawnEggItem_SpawnEggsSpawnMobsWithNoAIMixin", @@ -28,13 +27,12 @@ "accessors.EntityAccessorMixin", "invokers.EntityInvokerMixin", "invokers.ExperienceOrbEntityInvokerMixin", - "invokers.SpawnHelperInfoInvokerMixin", - "network.CustomPayloadS2CPacket_CustomPacketMixin" + "invokers.SpawnHelperInfoInvokerMixin" ], "injectors": { "defaultRequire": 1 }, "client": [ - "network.ClientPlayNetworkHandler_CustomPacketsMixin" + "ClientPlayerEntity_SpectatorPlayersUsePortalsMixin" ] } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 6dc82dd..2670ab6 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -17,10 +17,10 @@ }, "mixins": ["carpet-addons-not-found.mixins.json"], "depends": { - "fabricloader": ">=0.15.7", - "minecraft": ">=1.20.3", - "java": ">=17", - "carpet": ">=1.4.128" + "fabricloader": ">=0.16.3", + "minecraft": ">=1.21.1", + "java": ">=21", + "carpet": ">=1.4.147" }, "suggests": {}, "custom": {