commit 62d0aa4bae8fdd49d01a473842093d4f5392941f Author: MincoMK Date: Wed Apr 16 20:15:52 2025 +0900 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d5f737e --- /dev/null +++ b/.gitignore @@ -0,0 +1,119 @@ +# User-specific stuff +.idea/ + +*.iml +*.ipr +*.iws + +# IntelliJ +out/ +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +.gradle +build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Cache of project +.gradletasknamecache + +**/build/ + +# Common working directory +run/ +runs/ + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..9e85bcc --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,2 @@ +Copyright (c) 2025 +All rights reserved. diff --git a/README.md b/README.md new file mode 100644 index 0000000..56cb7c9 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# MountTeleportFix +1.21.4 Fabric mod for fixing MC-277807 bug. + +## Installation +Simply drop the jar to `mods` folder (This mod is server side only). As well as the **Fabric API**. \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..fd0709d --- /dev/null +++ b/build.gradle @@ -0,0 +1,98 @@ +plugins { + id 'fabric-loom' version '1.10-SNAPSHOT' + id 'maven-publish' +} + +version = project.mod_version +group = project.maven_group + +base { + archivesName = project.archives_base_name +} + +loom { + accessWidenerPath = file("src/main/resources/${project.archives_base_name}.accesswidener") +} + +fabricApi { + configureDataGeneration { + client = true + } +} + +repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. +} + +dependencies { + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" +} + +processResources { + inputs.property "version", project.version + inputs.property "minecraft_version", project.minecraft_version + inputs.property "loader_version", project.loader_version + filteringCharset "UTF-8" + + filesMatching("fabric.mod.json") { + expand "version": project.version, + "minecraft_version": project.minecraft_version, + "loader_version": project.loader_version + } +} + +def targetJavaVersion = 21 +tasks.withType(JavaCompile).configureEach { + // ensure that the encoding is set to UTF-8, no matter what the system default is + // this fixes some edge cases with special characters not displaying correctly + // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html + // If Javadoc is generated, this must be specified in that task too. + it.options.encoding = "UTF-8" + if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { + it.options.release.set(targetJavaVersion) + } +} + +java { + def javaVersion = JavaVersion.toVersion(targetJavaVersion) + if (JavaVersion.current() < javaVersion) { + toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) + } + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() +} + +jar { + from("LICENSE") { + rename { "${it}_${project.archivesBaseName}" } + } +} + +// configure the maven publication +publishing { + publications { + create("mavenJava", MavenPublication) { + artifactId = project.archives_base_name + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..d3f90fa --- /dev/null +++ b/gradle.properties @@ -0,0 +1,14 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G +# Fabric Properties +# check these on https://modmuss50.me/fabric.html +minecraft_version=1.21.4 +yarn_mappings=1.21.4+build.8 +loader_version=0.16.13 +# Mod Properties +mod_version=1.0-SNAPSHOT +maven_group=org.walruslab +archives_base_name=mountteleportfix +# Dependencies +# check this on https://modmuss50.me/fabric.html +fabric_version=0.119.2+1.21.4 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..82d65ca --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..f91a4fe --- /dev/null +++ b/settings.gradle @@ -0,0 +1,9 @@ +pluginManagement { + repositories { + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + gradlePluginPortal() + } +} diff --git a/src/main/java/org/walruslab/mountteleportfix/MountTeleportFix.java b/src/main/java/org/walruslab/mountteleportfix/MountTeleportFix.java new file mode 100644 index 0000000..cff9bcd --- /dev/null +++ b/src/main/java/org/walruslab/mountteleportfix/MountTeleportFix.java @@ -0,0 +1,10 @@ +package org.walruslab.mountteleportfix; + +import net.fabricmc.api.ModInitializer; + +public class MountTeleportFix implements ModInitializer { + + @Override + public void onInitialize() { + } +} diff --git a/src/main/java/org/walruslab/mountteleportfix/client/MountTeleportFixDataGenerator.java b/src/main/java/org/walruslab/mountteleportfix/client/MountTeleportFixDataGenerator.java new file mode 100644 index 0000000..d35f455 --- /dev/null +++ b/src/main/java/org/walruslab/mountteleportfix/client/MountTeleportFixDataGenerator.java @@ -0,0 +1,12 @@ +package org.walruslab.mountteleportfix.client; + +import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint; +import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator; + +public class MountTeleportFixDataGenerator implements DataGeneratorEntrypoint { + + @Override + public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) { + FabricDataGenerator.Pack pack = fabricDataGenerator.createPack(); + } +} diff --git a/src/main/java/org/walruslab/mountteleportfix/mixin/ServerPlayerNetworkHandlerMixin.java b/src/main/java/org/walruslab/mountteleportfix/mixin/ServerPlayerNetworkHandlerMixin.java new file mode 100644 index 0000000..b04e0a7 --- /dev/null +++ b/src/main/java/org/walruslab/mountteleportfix/mixin/ServerPlayerNetworkHandlerMixin.java @@ -0,0 +1,152 @@ +package org.walruslab.mountteleportfix.mixin; + +import net.minecraft.entity.MovementType; +import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.network.NetworkThreadUtils; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Text; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; + +@Mixin(ServerPlayNetworkHandler.class) +public class ServerPlayerNetworkHandlerMixin { + /** + * @author MincoMK + * @reason Fix MC-277807 + */ + @Overwrite + public void onPlayerMove(PlayerMoveC2SPacket packet) { + ServerPlayNetworkHandler self = (ServerPlayNetworkHandler) (Object) this; + + NetworkThreadUtils.forceMainThread(packet, self, self.player.getServerWorld()); + if (ServerPlayNetworkHandler.isMovementInvalid(packet.getX(0.0), packet.getY(0.0), packet.getZ(0.0), packet.getYaw(0.0F), packet.getPitch(0.0F))) { + self.disconnect(Text.translatable("multiplayer.disconnect.invalid_player_movement")); + } else { + ServerWorld serverWorld = self.player.getServerWorld(); + if (!self.player.notInAnyWorld) { + if (self.ticks == 0) { + self.syncWithPlayerPosition(); + } + + if (self.player.isLoaded()) { + float f = MathHelper.wrapDegrees(packet.getYaw(self.player.getYaw())); + float g = MathHelper.wrapDegrees(packet.getPitch(self.player.getPitch())); + if (self.handlePendingTeleport()) { + self.player.setAngles(f, g); + } else { + double d = ServerPlayNetworkHandler.clampHorizontal(packet.getX(self.player.getX())); + double e = ServerPlayNetworkHandler.clampVertical(packet.getY(self.player.getY())); + double h = ServerPlayNetworkHandler.clampHorizontal(packet.getZ(self.player.getZ())); + if (self.player.hasVehicle()) { + self.player.updatePositionAndAngles(self.player.getX(), self.player.getY(), self.player.getZ(), f, g); + self.player.getServerWorld().getChunkManager().updatePosition(self.player); + } else { + double i = self.player.getX(); + double j = self.player.getY(); + double k = self.player.getZ(); + double l = d - self.lastTickX; + double m = e - self.lastTickY; + double n = h - self.lastTickZ; + double o = self.player.getVelocity().lengthSquared(); + double p = l * l + m * m + n * n; + if (self.player.isSleeping()) { + if (p > 1.0) { + self.requestTeleport(self.player.getX(), self.player.getY(), self.player.getZ(), f, g); + } + } else { + boolean bl = self.player.isGliding(); + if (serverWorld.getTickManager().shouldTick()) { + self.movePacketsCount++; + int q = self.movePacketsCount - self.lastTickMovePacketsCount; + if (q > 5) { + ServerPlayNetworkHandler.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", self.player.getName().getString(), q); + q = 1; + } + + if (self.shouldCheckMovement(bl)) { + float r = bl ? 300.0F : 100.0F; + if (p - o > r * q) { + ServerPlayNetworkHandler.LOGGER.warn("{} moved too quickly! {},{},{}", self.player.getName().getString(), l, m, n); + self.requestTeleport(self.player.getX(), self.player.getY(), self.player.getZ(), self.player.getYaw(), self.player.getPitch()); + return; + } + } + } + + Box box = self.player.getBoundingBox(); + l = d - self.updatedX; + m = e - self.updatedY; + n = h - self.updatedZ; + boolean bl2 = m > 0.0; + if (self.player.isOnGround() && !packet.isOnGround() && bl2) { + self.player.jump(); + } + + boolean bl3 = self.player.groundCollision; + self.player.move(MovementType.PLAYER, new Vec3d(l, m, n)); + l = d - self.player.getX(); + m = e - self.player.getY(); + if (m > -0.5 || m < 0.5) { + m = 0.0; + } + + n = h - self.player.getZ(); + p = l * l + m * m + n * n; + boolean bl4 = false; + if (!self.player.isInTeleportationState() && p > 0.0625 && !self.player.isSleeping() && !self.player.isCreative() && !self.player.isSpectator()) { + bl4 = true; + ServerPlayNetworkHandler.LOGGER.warn("{} moved wrongly!", self.player.getName().getString()); + } + + if (self.player.noClip + || self.player.isSleeping() + || (!bl4 || !serverWorld.isSpaceEmpty(self.player, box)) && !self.isPlayerNotCollidingWithBlocks(serverWorld, box, d, e, h)) { + self.player.updatePositionAndAngles(d, e, h, f, g); + boolean bl5 = self.player.isUsingRiptide(); + self.floating = m >= -0.03125 + && !bl3 + && !self.player.isSpectator() + && !self.server.isFlightEnabled() + && !self.player.getAbilities().allowFlying + && !self.player.hasStatusEffect(StatusEffects.LEVITATION) + && !bl + && !bl5 + && self.isEntityOnAir(self.player); + self.player.getServerWorld().getChunkManager().updatePosition(self.player); + Vec3d vec3d = new Vec3d(self.player.getX() - i, self.player.getY() - j, self.player.getZ() - k); + self.player.setMovement(packet.isOnGround(), packet.horizontalCollision(), vec3d); + self.player.handleFall(vec3d.x, vec3d.y, vec3d.z, packet.isOnGround()); + self.handleMovement(vec3d); + if (bl2) { + self.player.onLanding(); + } + + if (packet.isOnGround() || self.player.hasLandedInFluid() || self.player.isClimbing() || self.player.isSpectator() || bl || bl5) { + self.player.tryClearCurrentExplosion(); + } + + self.player.increaseTravelMotionStats(self.player.getX() - i, self.player.getY() - j, self.player.getZ() - k); + self.updatedX = self.player.getX(); + self.updatedY = self.player.getY(); + self.updatedZ = self.player.getZ(); + } else { + self.requestTeleport(i, j, k, f, g); + self.player.handleFall(self.player.getX() - i, self.player.getY() - j, self.player.getZ() - k, packet.isOnGround()); + + if (!self.player.queuedCollisionChecks.isEmpty()) { + self.player.queuedCollisionChecks.removeLast(); + } + } + } + } + } + } + } + } + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..137e67b --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "id": "mountteleportfix", + "version": "${version}", + "name": "MountTeleportFix", + "description": "", + "authors": [], + "contact": {}, + "license": "All-Rights-Reserved", + "icon": "assets/mountteleportfix/icon.png", + "environment": "server", + "accessWidener": "mountteleportfix.accesswidener", + "entrypoints": { + "fabric-datagen": [ + "org.walruslab.mountteleportfix.client.MountTeleportFixDataGenerator" + ], + "main": [ + "org.walruslab.mountteleportfix.MountTeleportFix" + ] + }, + "mixins": [ + "mountteleportfix.mixins.json" + ], + "depends": { + "fabricloader": ">=${loader_version}", + "fabric": "*", + "minecraft": "${minecraft_version}" + } +} diff --git a/src/main/resources/mountteleportfix.accesswidener b/src/main/resources/mountteleportfix.accesswidener new file mode 100644 index 0000000..f7d080a --- /dev/null +++ b/src/main/resources/mountteleportfix.accesswidener @@ -0,0 +1,23 @@ +accessWidener v2 named + +accessible method net/minecraft/server/network/ServerPlayNetworkHandler handlePendingTeleport ()Z +accessible method net/minecraft/server/network/ServerPlayNetworkHandler isMovementInvalid (DDDFF)Z +accessible method net/minecraft/server/network/ServerPlayNetworkHandler clampHorizontal (D)D +accessible method net/minecraft/server/network/ServerPlayNetworkHandler clampVertical (D)D +accessible field net/minecraft/server/network/ServerPlayNetworkHandler lastTickX D +accessible field net/minecraft/server/network/ServerPlayNetworkHandler lastTickY D +accessible field net/minecraft/server/network/ServerPlayNetworkHandler lastTickZ D +accessible field net/minecraft/server/network/ServerPlayNetworkHandler movePacketsCount I +accessible field net/minecraft/server/network/ServerPlayNetworkHandler lastTickMovePacketsCount I +accessible field net/minecraft/server/network/ServerPlayNetworkHandler LOGGER Lorg/slf4j/Logger; +accessible method net/minecraft/server/network/ServerPlayNetworkHandler shouldCheckMovement (Z)Z +accessible field net/minecraft/server/network/ServerPlayNetworkHandler updatedX D +accessible field net/minecraft/server/network/ServerPlayNetworkHandler updatedY D +accessible field net/minecraft/server/network/ServerPlayNetworkHandler updatedZ D +accessible field net/minecraft/server/network/ServerPlayNetworkHandler floating Z +accessible field net/minecraft/server/network/ServerCommonNetworkHandler server Lnet/minecraft/server/MinecraftServer; +accessible method net/minecraft/server/network/ServerPlayNetworkHandler handleMovement (Lnet/minecraft/util/math/Vec3d;)V +accessible method net/minecraft/server/network/ServerPlayNetworkHandler isEntityOnAir (Lnet/minecraft/entity/Entity;)Z +accessible method net/minecraft/server/network/ServerPlayNetworkHandler isPlayerNotCollidingWithBlocks (Lnet/minecraft/world/WorldView;Lnet/minecraft/util/math/Box;DDD)Z +accessible field net/minecraft/server/network/ServerPlayNetworkHandler ticks I +accessible field net/minecraft/entity/Entity queuedCollisionChecks Ljava/util/List; \ No newline at end of file diff --git a/src/main/resources/mountteleportfix.mixins.json b/src/main/resources/mountteleportfix.mixins.json new file mode 100644 index 0000000..d465abb --- /dev/null +++ b/src/main/resources/mountteleportfix.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "org.walruslab.mountteleportfix.mixin", + "compatibilityLevel": "JAVA_21", + "mixins": [ + "ServerPlayerNetworkHandlerMixin" + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +}