Clean repo for open source release

Remove build artifacts, dev tool configs, unused dependencies,
and third-party source dumps. Add proper README, update .gitignore,
clean up Makefile.
This commit is contained in:
NotEvil
2026-04-12 00:51:22 +02:00
parent 2e7a1d403b
commit f6466360b6
1947 changed files with 238025 additions and 1 deletions

View File

@@ -0,0 +1,367 @@
package com.tiedup.remake.util.teleport;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
/**
* Represents a teleport position with coordinates, rotation, and dimension.
*
* <p>Used by collar teleport commands and warp points in the original mod.</p>
*
* <h2>Use Cases</h2>
* <ul>
* <li>Collar warp points (home, prison, custom locations)</li>
* <li>EntityKidnapper prison teleportation</li>
* <li>Admin teleport commands</li>
* </ul>
*
* <h2>NBT Structure</h2>
* <pre>
* position (CompoundTag)
* ├── x (double)
* ├── y (double)
* ├── z (double)
* ├── yaw (float)
* ├── pitch (float)
* └── dimension (string) - e.g., "minecraft:overworld"
* </pre>
*
* <h2>Original Reference</h2>
* Based on Original/com/yuti/kidnapmod/util/teleport/Position.java
*/
public class Position {
private final double x;
private final double y;
private final double z;
private final float yaw;
private final float pitch;
private final ResourceKey<Level> dimension;
/**
* Create a new position with full rotation.
*
* @param x X coordinate
* @param y Y coordinate
* @param z Z coordinate
* @param yaw Horizontal rotation (0-360)
* @param pitch Vertical rotation (-90 to 90)
* @param dimension Dimension key (e.g., Level.OVERWORLD, Level.NETHER)
*/
public Position(
double x,
double y,
double z,
float yaw,
float pitch,
ResourceKey<Level> dimension
) {
this.x = x;
this.y = y;
this.z = z;
this.yaw = yaw;
this.pitch = pitch;
this.dimension = dimension;
}
/**
* Create a new position without rotation (defaults to 0).
*
* @param x X coordinate
* @param y Y coordinate
* @param z Z coordinate
* @param dimension Dimension key
*/
public Position(
double x,
double y,
double z,
ResourceKey<Level> dimension
) {
this(x, y, z, 0.0f, 0.0f, dimension);
}
/**
* Create a position from BlockPos and dimension.
*
* @param pos Block position
* @param dimension Dimension key
*/
public Position(BlockPos pos, ResourceKey<Level> dimension) {
this(
pos.getX() + 0.5,
pos.getY(),
pos.getZ() + 0.5,
0.0f,
0.0f,
dimension
);
}
/**
* Create a position from Vec3 and dimension.
*
* @param vec Vector position
* @param dimension Dimension key
*/
public Position(Vec3 vec, ResourceKey<Level> dimension) {
this(vec.x, vec.y, vec.z, 0.0f, 0.0f, dimension);
}
/**
* Create a position from an entity's current location.
*
* @param entity The entity
* @return Position at entity's location with rotation
*/
public static Position fromEntity(Entity entity) {
return new Position(
entity.getX(),
entity.getY(),
entity.getZ(),
entity.getYRot(),
entity.getXRot(),
entity.level().dimension()
);
}
// ========================================
// NBT SERIALIZATION
// ========================================
/**
* Save this position to NBT.
*
* @return CompoundTag containing position data
*/
public CompoundTag save() {
CompoundTag tag = new CompoundTag();
tag.putDouble("x", this.x);
tag.putDouble("y", this.y);
tag.putDouble("z", this.z);
tag.putFloat("yaw", this.yaw);
tag.putFloat("pitch", this.pitch);
tag.putString("dimension", this.dimension.location().toString());
return tag;
}
/**
* Save this position to an existing CompoundTag.
*
* @param tag The tag to save to
* @return The modified tag
*/
public CompoundTag save(CompoundTag tag) {
tag.putDouble("x", this.x);
tag.putDouble("y", this.y);
tag.putDouble("z", this.z);
tag.putFloat("yaw", this.yaw);
tag.putFloat("pitch", this.pitch);
tag.putString("dimension", this.dimension.location().toString());
return tag;
}
/**
* Load a position from NBT.
*
* @param tag The CompoundTag to load from
* @return Position or null if invalid
*/
@Nullable
public static Position load(CompoundTag tag) {
if (
tag == null ||
!tag.contains("x") ||
!tag.contains("y") ||
!tag.contains("z")
) {
return null;
}
double x = tag.getDouble("x");
double y = tag.getDouble("y");
double z = tag.getDouble("z");
float yaw = tag.contains("yaw") ? tag.getFloat("yaw") : 0.0f;
float pitch = tag.contains("pitch") ? tag.getFloat("pitch") : 0.0f;
// Parse dimension
ResourceKey<Level> dimension = Level.OVERWORLD; // Default
if (tag.contains("dimension")) {
String dimStr = tag.getString("dimension");
ResourceLocation dimLoc = ResourceLocation.tryParse(dimStr);
if (dimLoc != null) {
dimension = ResourceKey.create(Registries.DIMENSION, dimLoc);
}
}
return new Position(x, y, z, yaw, pitch, dimension);
}
// ========================================
// GETTERS
// ========================================
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getZ() {
return z;
}
public float getYaw() {
return yaw;
}
public float getPitch() {
return pitch;
}
public ResourceKey<Level> getDimension() {
return dimension;
}
/**
* Convert to Vec3.
* @return Vector representation
*/
public Vec3 toVec3() {
return new Vec3(x, y, z);
}
/**
* Convert to BlockPos.
* @return Block position (floored)
*/
public BlockPos toBlockPos() {
return new BlockPos(
(int) Math.floor(x),
(int) Math.floor(y),
(int) Math.floor(z)
);
}
/**
* Get dimension name for display.
* @return Dimension name (e.g., "overworld", "the_nether")
*/
public String getDimensionName() {
return dimension.location().getPath();
}
/**
* Check if this position is in the same dimension as another.
* @param other The other position
* @return true if same dimension
*/
public boolean isSameDimension(Position other) {
return other != null && this.dimension.equals(other.dimension);
}
/**
* Check if this position is in the given dimension.
* @param dim The dimension to check
* @return true if in that dimension
*/
public boolean isInDimension(ResourceKey<Level> dim) {
return this.dimension.equals(dim);
}
/**
* Calculate distance to another position (ignores dimension).
* @param other The other position
* @return Distance in blocks
*/
public double distanceTo(Position other) {
double dx = this.x - other.x;
double dy = this.y - other.y;
double dz = this.z - other.z;
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}
/**
* Calculate horizontal distance to another position (ignores Y and dimension).
* @param other The other position
* @return Horizontal distance in blocks
*/
public double horizontalDistanceTo(Position other) {
double dx = this.x - other.x;
double dz = this.z - other.z;
return Math.sqrt(dx * dx + dz * dz);
}
// ========================================
// OBJECT OVERRIDES
// ========================================
@Override
public String toString() {
return String.format(
"Position{x=%.2f, y=%.2f, z=%.2f, yaw=%.1f, pitch=%.1f, dim=%s}",
x,
y,
z,
yaw,
pitch,
dimension.location()
);
}
/**
* Get a short string for display (e.g., in tooltips).
* @return Short position string like "X: 100, Y: 64, Z: -200"
*/
public String toShortString() {
return String.format("X: %.0f, Y: %.0f, Z: %.0f", x, y, z);
}
/**
* Get a display string with dimension for tooltips.
* @return Display string like "overworld - X: 100, Y: 64, Z: -200"
*/
public String toDisplayString() {
return String.format(
"%s - X: %.0f, Y: %.0f, Z: %.0f",
getDimensionName(),
x,
y,
z
);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Position other)) return false;
return (
Double.compare(other.x, x) == 0 &&
Double.compare(other.y, y) == 0 &&
Double.compare(other.z, z) == 0 &&
Float.compare(other.yaw, yaw) == 0 &&
Float.compare(other.pitch, pitch) == 0 &&
dimension.equals(other.dimension)
);
}
@Override
public int hashCode() {
int result = Double.hashCode(x);
result = 31 * result + Double.hashCode(y);
result = 31 * result + Double.hashCode(z);
result = 31 * result + Float.hashCode(yaw);
result = 31 * result + Float.hashCode(pitch);
result = 31 * result + dimension.hashCode();
return result;
}
}

View File

@@ -0,0 +1,393 @@
package com.tiedup.remake.util.teleport;
import com.tiedup.remake.core.TiedUpMod;
import java.util.function.Function;
import org.jetbrains.annotations.Nullable;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.portal.PortalInfo;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.util.ITeleporter;
/**
* Utility class for teleporting entities across dimensions.
*
* <p>Handles the complexity of cross-dimension teleportation in 1.20.1,
* including proper chunk loading, entity transfer, and rotation preservation.</p>
*
* <h2>Features</h2>
* <ul>
* <li>Same-dimension teleportation</li>
* <li>Cross-dimension teleportation</li>
* <li>Player-specific handling (smooth client sync)</li>
* <li>Rotation preservation</li>
* <li>Safe position validation</li>
* </ul>
*
* <h2>Original Reference</h2>
* Based on Original/com/yuti/kidnapmod/util/teleport/TeleportHelper.java
*/
public class TeleportHelper {
/**
* Teleport an entity to a position.
* Handles both same-dimension and cross-dimension teleportation.
*
* @param entity The entity to teleport
* @param position The target position
* @return The entity after teleportation (may be different instance after dimension change)
*/
@Nullable
public static Entity teleportEntity(Entity entity, Position position) {
if (entity == null || position == null) {
return entity;
}
// Server-side only
if (entity.level().isClientSide) {
TiedUpMod.LOGGER.warn(
"[TeleportHelper] Attempted client-side teleport"
);
return entity;
}
// Get server and target level
MinecraftServer server = entity.getServer();
if (server == null) {
TiedUpMod.LOGGER.error(
"[TeleportHelper] No server found for entity"
);
return entity;
}
ResourceKey<Level> targetDimension = position.getDimension();
ServerLevel targetLevel = server.getLevel(targetDimension);
if (targetLevel == null) {
TiedUpMod.LOGGER.error(
"[TeleportHelper] Target dimension not found: {}",
targetDimension
);
return entity;
}
// Check if same dimension or cross-dimension
if (entity.level().dimension().equals(targetDimension)) {
return teleportSameDimension(entity, position);
} else {
return teleportCrossDimension(entity, targetLevel, position);
}
}
/**
* Teleport an entity within the same dimension.
*
* @param entity The entity to teleport
* @param position The target position
* @return The entity after teleportation
*/
private static Entity teleportSameDimension(
Entity entity,
Position position
) {
if (entity == null || position == null) {
return entity;
}
// For players, use the connection method for smooth sync
if (entity instanceof ServerPlayer player) {
player.connection.teleport(
position.getX(),
position.getY(),
position.getZ(),
position.getYaw(),
position.getPitch()
);
// Reset fall distance to prevent fall damage after teleport
player.fallDistance = 0;
player.resetFallDistance();
TiedUpMod.LOGGER.info(
"[TeleportHelper] Teleported player {} to {}",
player.getName().getString(),
position.toShortString()
);
} else {
// For other entities, set position and rotation directly
entity.teleportTo(
position.getX(),
position.getY(),
position.getZ()
);
entity.setYRot(position.getYaw());
entity.setXRot(position.getPitch());
entity.setYHeadRot(position.getYaw());
// Reset fall distance to prevent fall damage after teleport
entity.fallDistance = 0;
TiedUpMod.LOGGER.info(
"[TeleportHelper] Teleported entity {} to {}",
entity.getName().getString(),
position.toShortString()
);
}
return entity;
}
/**
* Teleport an entity across dimensions.
*
* @param entity The entity to teleport
* @param targetLevel The target dimension
* @param position The target position
* @return The entity after teleportation (may be different instance)
*/
@Nullable
public static Entity teleportCrossDimension(
Entity entity,
ServerLevel targetLevel,
Position position
) {
if (entity == null || targetLevel == null || position == null) {
return entity;
}
// For players, use changeDimension with custom teleporter
if (entity instanceof ServerPlayer player) {
return teleportPlayerCrossDimension(player, targetLevel, position);
}
// For other entities, use changeDimension
Entity newEntity = entity.changeDimension(
targetLevel,
new PositionTeleporter(position)
);
if (newEntity != null) {
TiedUpMod.LOGGER.info(
"[TeleportHelper] Cross-dimension teleport: {} to {} in {}",
entity.getName().getString(),
position.toShortString(),
targetLevel.dimension().location()
);
} else {
TiedUpMod.LOGGER.warn(
"[TeleportHelper] Cross-dimension teleport failed for {}",
entity.getName().getString()
);
}
return newEntity;
}
/**
* Teleport a player across dimensions.
*
* @param player The player to teleport
* @param targetLevel The target dimension
* @param position The target position
* @return The player after teleportation
*/
public static ServerPlayer teleportPlayerCrossDimension(
ServerPlayer player,
ServerLevel targetLevel,
Position position
) {
if (player == null || targetLevel == null || position == null) {
return player;
}
// Use Forge's teleportTo method for cross-dimension
player.changeDimension(targetLevel, new PositionTeleporter(position));
TiedUpMod.LOGGER.info(
"[TeleportHelper] Cross-dimension player teleport: {} to {} in {}",
player.getName().getString(),
position.toShortString(),
targetLevel.dimension().location()
);
return player;
}
/**
* Teleport a living entity to another entity's position.
*
* @param entity The entity to teleport
* @param target The target entity to teleport to
* @return The entity after teleportation
*/
@Nullable
public static Entity teleportToEntity(Entity entity, Entity target) {
if (entity == null || target == null) {
return entity;
}
Position targetPos = Position.fromEntity(target);
return teleportEntity(entity, targetPos);
}
/**
* Check if teleportation to a position is safe.
* Checks for solid ground and non-suffocating blocks.
*
* @param level The level to check in
* @param position The position to check
* @return true if position is safe for teleportation
*/
public static boolean isSafePosition(Level level, Position position) {
if (level == null || position == null) {
return false;
}
// Check if there's solid ground below
var groundPos = position.toBlockPos().below();
var groundState = level.getBlockState(groundPos);
if (!groundState.isSolid()) {
return false; // No solid ground
}
// Check if the position itself is not solid (entity can fit)
var feetPos = position.toBlockPos();
var headPos = feetPos.above();
var feetState = level.getBlockState(feetPos);
var headState = level.getBlockState(headPos);
return !feetState.isSolid() && !headState.isSolid();
}
/**
* Find a safe position near the target position.
* Searches in a small radius for a valid teleport location.
*
* @param level The level to search in
* @param position The target position
* @param radius Search radius
* @return Safe position or original if none found
*/
public static Position findSafePosition(
Level level,
Position position,
int radius
) {
if (level == null || position == null) {
return position;
}
// First check if original position is safe
if (isSafePosition(level, position)) {
return position;
}
// Search in expanding circles
for (int r = 1; r <= radius; r++) {
for (int x = -r; x <= r; x++) {
for (int z = -r; z <= r; z++) {
// Only check edge of current radius
if (Math.abs(x) != r && Math.abs(z) != r) continue;
Position testPos = new Position(
position.getX() + x,
position.getY(),
position.getZ() + z,
position.getYaw(),
position.getPitch(),
position.getDimension()
);
if (isSafePosition(level, testPos)) {
return testPos;
}
}
}
}
// No safe position found, return original
TiedUpMod.LOGGER.warn(
"[TeleportHelper] No safe position found near {}",
position.toShortString()
);
return position;
}
// ========================================
// CUSTOM TELEPORTER FOR FORGE
// ========================================
/**
* Custom teleporter that preserves exact position and rotation.
*/
private static class PositionTeleporter implements ITeleporter {
private final Position position;
public PositionTeleporter(Position position) {
this.position = position;
}
@Override
public Entity placeEntity(
Entity entity,
ServerLevel currentWorld,
ServerLevel destWorld,
float yaw,
Function<Boolean, Entity> repositionEntity
) {
// Reposition the entity first (handles mounting, leashing, etc.)
Entity repositioned = repositionEntity.apply(false);
if (repositioned != null) {
// Set exact position and rotation
repositioned.teleportTo(
position.getX(),
position.getY(),
position.getZ()
);
repositioned.setYRot(position.getYaw());
repositioned.setXRot(position.getPitch());
repositioned.setYHeadRot(position.getYaw());
}
return repositioned;
}
@Nullable
@Override
public PortalInfo getPortalInfo(
Entity entity,
ServerLevel destWorld,
Function<ServerLevel, PortalInfo> defaultPortalInfo
) {
return new PortalInfo(
new Vec3(position.getX(), position.getY(), position.getZ()),
Vec3.ZERO, // No velocity
position.getYaw(),
position.getPitch()
);
}
@Override
public boolean isVanilla() {
return false; // Custom teleporter
}
@Override
public boolean playTeleportSound(
ServerPlayer player,
ServerLevel sourceWorld,
ServerLevel destWorld
) {
return false; // No teleport sound
}
}
}