plane update and stuff
This commit is contained in:
@@ -6,7 +6,7 @@ minecraft_version=1.20.1
|
|||||||
yarn_mappings=1.20.1+build.10
|
yarn_mappings=1.20.1+build.10
|
||||||
loader_version=0.18.3
|
loader_version=0.18.3
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=26.2.24.1
|
mod_version=26.2.25
|
||||||
maven_group=dev.tggamesyt
|
maven_group=dev.tggamesyt
|
||||||
archives_base_name=szar
|
archives_base_name=szar
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import net.minecraft.client.render.*;
|
|||||||
import net.minecraft.client.render.entity.*;
|
import net.minecraft.client.render.entity.*;
|
||||||
import net.minecraft.client.render.entity.model.EntityModelLayer;
|
import net.minecraft.client.render.entity.model.EntityModelLayer;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.RotationAxis;
|
||||||
|
|
||||||
public class PlaneEntityRenderer extends EntityRenderer<PlaneEntity> {
|
public class PlaneEntityRenderer extends EntityRenderer<PlaneEntity> {
|
||||||
|
|
||||||
@@ -35,26 +37,48 @@ public class PlaneEntityRenderer extends EntityRenderer<PlaneEntity> {
|
|||||||
int light
|
int light
|
||||||
) {
|
) {
|
||||||
matrices.push();
|
matrices.push();
|
||||||
|
|
||||||
|
// Smooth interpolation of rotation
|
||||||
|
float interpolatedYaw = entity.prevYaw + (entity.getYaw() - entity.prevYaw) * tickDelta;
|
||||||
|
float interpolatedPitch = entity.prevPitch + (entity.getPitch() - entity.prevPitch) * tickDelta;
|
||||||
|
|
||||||
|
// Scale
|
||||||
matrices.scale(4.0F, 4.0F, 4.0F);
|
matrices.scale(4.0F, 4.0F, 4.0F);
|
||||||
|
|
||||||
|
// Move model to correct pivot point
|
||||||
matrices.translate(0.0, 1.5, 0.0);
|
matrices.translate(0.0, 1.5, 0.0);
|
||||||
|
|
||||||
|
// Rotate to match hitbox exactly
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-interpolatedYaw));
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(interpolatedPitch));
|
||||||
|
|
||||||
|
// Rotate 180° to fix backwards-facing
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180.0F));
|
||||||
|
|
||||||
|
// Flip model upright (Minecraft model fix)
|
||||||
matrices.scale(-1.0F, -1.0F, 1.0F);
|
matrices.scale(-1.0F, -1.0F, 1.0F);
|
||||||
|
|
||||||
|
// Set model angles
|
||||||
model.setAngles(
|
model.setAngles(
|
||||||
entity,
|
entity,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
entity.age + tickDelta,
|
entity.age + tickDelta,
|
||||||
0,
|
interpolatedYaw,
|
||||||
0
|
interpolatedPitch
|
||||||
);
|
);
|
||||||
|
|
||||||
VertexConsumer consumer =
|
VertexConsumer consumer =
|
||||||
vertices.getBuffer(RenderLayer.getEntityCutout(getTexture(entity)));
|
vertices.getBuffer(RenderLayer.getEntityCutout(getTexture(entity)));
|
||||||
|
|
||||||
model.render(matrices, consumer, light, OverlayTexture.DEFAULT_UV,
|
model.render(
|
||||||
1.0F, 1.0F, 1.0F, 1.0F);
|
matrices,
|
||||||
|
consumer,
|
||||||
|
light,
|
||||||
|
OverlayTexture.DEFAULT_UV,
|
||||||
|
1.0F, 1.0F, 1.0F, 1.0F
|
||||||
|
);
|
||||||
|
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
super.render(entity, yaw, tickDelta, matrices, vertices, light);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
|||||||
import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry;
|
import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry;
|
||||||
import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry;
|
import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry;
|
||||||
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
|
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||||
import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry;
|
import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.option.KeyBinding;
|
import net.minecraft.client.option.KeyBinding;
|
||||||
@@ -26,6 +27,7 @@ import net.minecraft.client.render.*;
|
|||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.sound.SoundCategory;
|
||||||
import net.minecraft.sound.SoundEvent;
|
import net.minecraft.sound.SoundEvent;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
@@ -73,6 +75,18 @@ public class SzarClient implements ClientModInitializer {
|
|||||||
int loopStart = startOffset + startLength;
|
int loopStart = startOffset + startLength;
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeClient() {
|
public void onInitializeClient() {
|
||||||
|
ClientTickEvents.END_CLIENT_TICK.register(client -> {
|
||||||
|
if (client.player == null) return;
|
||||||
|
|
||||||
|
boolean forward = client.options.attackKey.isPressed();
|
||||||
|
boolean backward = client.options.useKey.isPressed();
|
||||||
|
|
||||||
|
PacketByteBuf buf = PacketByteBufs.create();
|
||||||
|
buf.writeBoolean(forward);
|
||||||
|
buf.writeBoolean(backward);
|
||||||
|
|
||||||
|
ClientPlayNetworking.send(PlayerMovementManager.PACKET_ID, buf);
|
||||||
|
});
|
||||||
ClientPlayNetworking.registerGlobalReceiver(SYNC_PACKET, (client, handler, buf, responseSender) -> {
|
ClientPlayNetworking.registerGlobalReceiver(SYNC_PACKET, (client, handler, buf, responseSender) -> {
|
||||||
// First read the player UUID
|
// First read the player UUID
|
||||||
UUID playerUuid = buf.readUuid();
|
UUID playerUuid = buf.readUuid();
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ package dev.tggamesyt.szar;
|
|||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
import net.minecraft.entity.*;
|
import net.minecraft.entity.*;
|
||||||
|
import net.minecraft.entity.damage.DamageSource;
|
||||||
import net.minecraft.entity.data.DataTracker;
|
import net.minecraft.entity.data.DataTracker;
|
||||||
import net.minecraft.entity.data.TrackedData;
|
import net.minecraft.entity.data.TrackedData;
|
||||||
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
|
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
@@ -22,6 +24,9 @@ public class PlaneEntity extends Entity {
|
|||||||
private PlaneAnimation currentServerAnimation = null;
|
private PlaneAnimation currentServerAnimation = null;
|
||||||
private float enginePower = 0f;
|
private float enginePower = 0f;
|
||||||
private double lastY;
|
private double lastY;
|
||||||
|
double stallSpeed = 1.0;
|
||||||
|
double explodeSpeed = 1.0;
|
||||||
|
private int brakeHoldTicks = 0;
|
||||||
@Environment(EnvType.CLIENT)
|
@Environment(EnvType.CLIENT)
|
||||||
private PlaneAnimation currentAnimation;
|
private PlaneAnimation currentAnimation;
|
||||||
|
|
||||||
@@ -34,6 +39,7 @@ public class PlaneEntity extends Entity {
|
|||||||
public PlaneEntity(EntityType<? extends PlaneEntity> type, World world) {
|
public PlaneEntity(EntityType<? extends PlaneEntity> type, World world) {
|
||||||
super(type, world);
|
super(type, world);
|
||||||
this.noClip = false;
|
this.noClip = false;
|
||||||
|
this.setStepHeight(2.0f);
|
||||||
this.setNoGravity(false); // FORCE gravity ON
|
this.setNoGravity(false); // FORCE gravity ON
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,128 +72,142 @@ public class PlaneEntity extends Entity {
|
|||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
|
|
||||||
PlayerEntity player = getControllingPassenger();
|
PlayerEntity player = getControllingPassenger();
|
||||||
|
|
||||||
|
// -----------------------------
|
||||||
|
// No pilot: just apply basic gravity
|
||||||
|
// -----------------------------
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
Vec3d velocity = getVelocity();
|
Vec3d velocity = getVelocity().add(0, -0.04, 0).multiply(0.95);
|
||||||
|
|
||||||
// Apply gravity even without pilot
|
|
||||||
velocity = velocity.add(0, -0.04, 0);
|
|
||||||
|
|
||||||
velocity = velocity.multiply(0.98);
|
|
||||||
|
|
||||||
setVelocity(velocity);
|
setVelocity(velocity);
|
||||||
move(MovementType.SELF, velocity);
|
move(MovementType.SELF, velocity);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------
|
||||||
/* --------------------------------
|
// Yaw & pitch control
|
||||||
CONTROLLER (AircraftEntity logic)
|
// -----------------------------
|
||||||
-------------------------------- */
|
|
||||||
|
|
||||||
// YAW
|
|
||||||
setYaw(getYaw() - player.sidewaysSpeed * 4.0f);
|
setYaw(getYaw() - player.sidewaysSpeed * 4.0f);
|
||||||
|
if (!isOnGround() || getVelocity().length() > 0.9) setPitch(getPitch() - player.forwardSpeed * 1.5f);
|
||||||
|
setPitch(getPitch() * 0.98f); // auto leveling
|
||||||
|
player.setInvisible(true);
|
||||||
|
|
||||||
// PITCH (only in air)
|
// -----------------------------
|
||||||
if (!isOnGround()) {
|
// Engine target adjustments (server authoritative)
|
||||||
setPitch(getPitch() - player.forwardSpeed * 2.5f);
|
// -----------------------------
|
||||||
|
boolean forward = !getWorld().isClient && PlayerMovementManager.isForwardPressed((ServerPlayerEntity) player);
|
||||||
|
boolean braking = !getWorld().isClient && PlayerMovementManager.isBackwardPressed((ServerPlayerEntity) player);
|
||||||
|
|
||||||
|
if (forward) setEngineTarget(getEngineTarget() + 0.02f);
|
||||||
|
|
||||||
|
if (braking) {
|
||||||
|
brakeHoldTicks++;
|
||||||
|
float baseBrake = isOnGround() ? 0.04f : 0.015f;
|
||||||
|
float progressive = Math.min(brakeHoldTicks * 0.0035f, 0.15f);
|
||||||
|
float brakeStrength = baseBrake + progressive;
|
||||||
|
setEngineTarget(getEngineTarget() - brakeStrength);
|
||||||
|
|
||||||
|
// Apply actual braking locally
|
||||||
|
Vec3d vel = getVelocity();
|
||||||
|
if (vel.lengthSquared() > 0.0001) {
|
||||||
|
Vec3d brakeDir = vel.normalize().multiply(-brakeStrength * 0.6);
|
||||||
|
setVelocity(vel.add(brakeDir));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
brakeHoldTicks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stabilizer (small auto leveling)
|
// -----------------------------
|
||||||
setPitch(getPitch() * 0.98f);
|
// Engine power smoothing
|
||||||
|
// -----------------------------
|
||||||
|
float lerpSpeed = braking ? 0.25f : 0.05f;
|
||||||
|
enginePower += (getEngineTarget() - enginePower) * lerpSpeed;
|
||||||
|
|
||||||
/* --------------------------------
|
// -----------------------------
|
||||||
THROTTLE (AirplaneEntity logic)
|
// PHYSICS (runs on both client & server)
|
||||||
-------------------------------- */
|
// -----------------------------
|
||||||
|
Vec3d forwardVec = getRotationVector().normalize();
|
||||||
if (player.jumping) {
|
|
||||||
setEngineTarget(getEngineTarget() + 0.02f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player.isSneaking()) {
|
|
||||||
setEngineTarget(getEngineTarget() - 0.02f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smooth engine reaction
|
|
||||||
enginePower += (getEngineTarget() - enginePower) * 0.05f;
|
|
||||||
|
|
||||||
/* --------------------------------
|
|
||||||
PHYSICS (STABLE VERSION)
|
|
||||||
-------------------------------- */
|
|
||||||
|
|
||||||
Vec3d forward = getRotationVector().normalize();
|
|
||||||
Vec3d velocity = getVelocity();
|
Vec3d velocity = getVelocity();
|
||||||
|
double horizontalSpeed = Math.sqrt(velocity.x * velocity.x + velocity.z * velocity.z);
|
||||||
|
|
||||||
/* ---------- REALIGN VELOCITY ---------- */
|
// Stall gravity in air
|
||||||
/* Prevents internal momentum stacking */
|
if (!isOnGround() && horizontalSpeed < stallSpeed) {
|
||||||
|
velocity = velocity.add(0, -0.2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward locking (only if not braking)
|
||||||
double speed = velocity.length();
|
double speed = velocity.length();
|
||||||
|
if (speed > 0.001 && enginePower > 0.01f && !braking) {
|
||||||
if (speed > 0.001) {
|
Vec3d newDir = velocity.normalize().lerp(forwardVec, 0.25).normalize();
|
||||||
// Stronger forward locking
|
|
||||||
double alignment = 0.25; // was 0.08
|
|
||||||
Vec3d newDir = velocity.normalize().lerp(forward, alignment).normalize();
|
|
||||||
velocity = newDir.multiply(speed);
|
velocity = newDir.multiply(speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply thrust
|
||||||
/* ---------- THRUST ---------- */
|
|
||||||
|
|
||||||
double thrust = Math.pow(enginePower, 2.0) * 0.08;
|
double thrust = Math.pow(enginePower, 2.0) * 0.08;
|
||||||
velocity = velocity.add(forward.multiply(thrust));
|
velocity = velocity.add(forwardVec.multiply(thrust));
|
||||||
|
|
||||||
/* ---------- GLIDE ---------- */
|
|
||||||
|
|
||||||
|
// Glide (air only)
|
||||||
double diffY = lastY - getY();
|
double diffY = lastY - getY();
|
||||||
if (lastY != 0.0 && diffY != 0.0) {
|
if (!isOnGround() && lastY != 0.0 && diffY != 0.0) {
|
||||||
velocity = velocity.add(
|
velocity = velocity.add(forwardVec.multiply(diffY * 0.04 * (1.0 - Math.abs(forwardVec.y))));
|
||||||
forward.multiply(diffY * 0.04 * (1.0 - Math.abs(forward.y)))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
lastY = getY();
|
lastY = getY();
|
||||||
|
|
||||||
/* ---------- DYNAMIC GRAVITY ---------- */
|
// Dynamic gravity
|
||||||
|
horizontalSpeed = velocity.length() * (1.0 - Math.abs(forwardVec.y));
|
||||||
double horizontalSpeed = velocity.length() * (1.0 - Math.abs(forward.y));
|
|
||||||
double gravityFactor = Math.max(0.0, 1.0 - horizontalSpeed * 1.5);
|
double gravityFactor = Math.max(0.0, 1.0 - horizontalSpeed * 1.5);
|
||||||
|
|
||||||
// ALWAYS apply — do not check hasNoGravity()
|
|
||||||
velocity = velocity.add(0, -0.04 * gravityFactor, 0);
|
velocity = velocity.add(0, -0.04 * gravityFactor, 0);
|
||||||
|
|
||||||
/* ---------- DRAG ---------- */
|
// Drag / friction
|
||||||
|
velocity = isOnGround() ? velocity.multiply(0.94) : velocity.multiply(0.98);
|
||||||
|
|
||||||
velocity = velocity.multiply(0.98);
|
// Max speed clamp
|
||||||
|
double maxSpeed = 2;
|
||||||
|
if (velocity.length() > maxSpeed) velocity = velocity.normalize().multiply(maxSpeed);
|
||||||
|
|
||||||
/* ---------- MAX SPEED CLAMP ---------- */
|
// Save vertical velocity before move for impact check
|
||||||
|
Vec3d preMoveVelocity = velocity;
|
||||||
double maxSpeed = 1.5;
|
|
||||||
if (velocity.length() > maxSpeed) {
|
|
||||||
velocity = velocity.normalize().multiply(maxSpeed);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Move
|
||||||
setVelocity(velocity);
|
setVelocity(velocity);
|
||||||
move(MovementType.SELF, velocity);
|
move(MovementType.SELF, velocity);
|
||||||
|
|
||||||
/* --------------------------------
|
// -----------------------------
|
||||||
ANIMATION STATE SYNC
|
// Crash detection (server only)
|
||||||
-------------------------------- */
|
// Explodes if hitting block with high horizontal or vertical velocity
|
||||||
|
// -----------------------------
|
||||||
|
if (!getWorld().isClient) {
|
||||||
|
double horizontalImpact = Math.sqrt(preMoveVelocity.x * preMoveVelocity.x + preMoveVelocity.z * preMoveVelocity.z);
|
||||||
|
double verticalImpact = Math.abs(preMoveVelocity.y);
|
||||||
|
|
||||||
boolean hasPassenger = getControllingPassenger() != null;
|
boolean crash = (horizontalImpact > 1.5 && horizontalCollision) || (verticalImpact > explodeSpeed && verticalCollision);
|
||||||
|
if (crash) {
|
||||||
|
getWorld().createExplosion(this, getX(), getY(), getZ(), 7.0f, World.ExplosionSourceType.TNT);
|
||||||
|
remove(RemovalReason.KILLED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!hasPassenger) {
|
// Stop tiny movements
|
||||||
playServerAnimation(null);
|
if (velocity.lengthSquared() < 0.005) velocity = Vec3d.ZERO;
|
||||||
}
|
setVelocity(velocity);
|
||||||
else if (enginePower < 0.05f) {
|
|
||||||
playServerAnimation(PlaneAnimation.START_ENGINE);
|
|
||||||
}
|
|
||||||
else if (isOnGround()) {
|
|
||||||
playServerAnimation(PlaneAnimation.LAND_STARTED);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
playServerAnimation(PlaneAnimation.FLYING);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// -----------------------------
|
||||||
|
// Animation sync
|
||||||
|
// -----------------------------
|
||||||
|
boolean hasPassenger = getControllingPassenger() != null;
|
||||||
|
if (!hasPassenger) playServerAnimation(null);
|
||||||
|
else if (enginePower < 0.05f) playServerAnimation(PlaneAnimation.START_ENGINE);
|
||||||
|
else if (isOnGround()) playServerAnimation(PlaneAnimation.LAND_STARTED);
|
||||||
|
else playServerAnimation(PlaneAnimation.FLYING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void removePassenger(Entity passenger) {
|
||||||
|
super.removePassenger(passenger);
|
||||||
|
if (passenger instanceof PlayerEntity player) {
|
||||||
|
player.setInvisible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
53
src/main/java/dev/tggamesyt/szar/PlayerMovementManager.java
Normal file
53
src/main/java/dev/tggamesyt/szar/PlayerMovementManager.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package dev.tggamesyt.szar;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class PlayerMovementManager {
|
||||||
|
|
||||||
|
// Packet ID
|
||||||
|
public static final Identifier PACKET_ID = new Identifier("szar", "player_movement");
|
||||||
|
|
||||||
|
// Stores current key state per player
|
||||||
|
private static final Map<ServerPlayerEntity, MovementState> playerStates = new HashMap<>();
|
||||||
|
|
||||||
|
// Represents pressed keys
|
||||||
|
public static class MovementState {
|
||||||
|
public boolean forwardPressed = false;
|
||||||
|
public boolean backwardPressed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Server-side init (register packet receiver)
|
||||||
|
public static void init() {
|
||||||
|
ServerPlayNetworking.registerGlobalReceiver(PACKET_ID, (server, player, handler, buf, responseSender) -> {
|
||||||
|
boolean forward = buf.readBoolean();
|
||||||
|
boolean backward = buf.readBoolean();
|
||||||
|
|
||||||
|
server.execute(() -> {
|
||||||
|
MovementState state = playerStates.computeIfAbsent(player, k -> new MovementState());
|
||||||
|
state.forwardPressed = forward;
|
||||||
|
state.backwardPressed = backward;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to get player state
|
||||||
|
public static boolean isForwardPressed(ServerPlayerEntity player) {
|
||||||
|
return playerStates.getOrDefault(player, new MovementState()).forwardPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isBackwardPressed(ServerPlayerEntity player) {
|
||||||
|
return playerStates.getOrDefault(player, new MovementState()).backwardPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional: clear state when player disconnects
|
||||||
|
public static void removePlayer(ServerPlayerEntity player) {
|
||||||
|
playerStates.remove(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -293,6 +293,7 @@ public class Szar implements ModInitializer {
|
|||||||
private final Map<UUID, BlockPos> sleepingPlayers = new HashMap<>();
|
private final Map<UUID, BlockPos> sleepingPlayers = new HashMap<>();
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
|
PlayerMovementManager.init();
|
||||||
ServerCosmetics.init();
|
ServerCosmetics.init();
|
||||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||||
ServerPlayerEntity player = handler.getPlayer();
|
ServerPlayerEntity player = handler.getPlayer();
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package dev.tggamesyt.szar.mixin;
|
||||||
|
|
||||||
|
import dev.tggamesyt.szar.PlaneEntity;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.damage.DamageSource;
|
||||||
|
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||||
|
import net.minecraft.entity.effect.StatusEffects;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
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(LivingEntity.class)
|
||||||
|
public abstract class LivingEntityFallDamageMixin {
|
||||||
|
|
||||||
|
// This injects at the start of computeFallDamage
|
||||||
|
@Inject(method = "computeFallDamage", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void preventFallDamageIfOnPlane(float fallDistance, float damageMultiplier, CallbackInfoReturnable<Integer> cir) {
|
||||||
|
LivingEntity self = (LivingEntity) (Object) this;
|
||||||
|
|
||||||
|
// Check if the entity is a player riding a PlaneEntity
|
||||||
|
if (self.hasVehicle() && self.getVehicle() instanceof PlaneEntity) {
|
||||||
|
cir.setReturnValue(0); // Cancel fall damage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package dev.tggamesyt.szar.mixin;
|
||||||
|
|
||||||
|
import dev.tggamesyt.szar.PlaneEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.network.ServerPlayerInteractionManager;
|
||||||
|
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.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
@Mixin(ServerPlayerInteractionManager.class)
|
||||||
|
public class PlaneBlockInteractionMixin {
|
||||||
|
|
||||||
|
@Inject(method = "interactBlock", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void interactBlock(ServerPlayerEntity player, World world, ItemStack stack, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable<ActionResult> cir) {
|
||||||
|
if (player.getVehicle() instanceof PlaneEntity) {
|
||||||
|
cir.setReturnValue(ActionResult.FAIL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "tryBreakBlock", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void preventBlockBreaking(BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
|
||||||
|
ServerPlayerEntity player = ((ServerPlayerInteractionManager)(Object)this).player;
|
||||||
|
if (player.getVehicle() instanceof PlaneEntity) {
|
||||||
|
cir.setReturnValue(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package dev.tggamesyt.szar.mixin;
|
||||||
|
|
||||||
|
import dev.tggamesyt.szar.PlaneEntity;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
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(PlayerEntity.class)
|
||||||
|
public class PlayerInteractionMixin {
|
||||||
|
|
||||||
|
@Inject(method = "interact", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void preventPlaneInteraction(Entity entity, Hand hand, CallbackInfoReturnable<ActionResult> cir) {
|
||||||
|
PlayerEntity player = (PlayerEntity) (Object) this;
|
||||||
|
if (player.getVehicle() instanceof PlaneEntity) {
|
||||||
|
cir.setReturnValue(ActionResult.FAIL); // cancel interaction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
},
|
},
|
||||||
"display": {
|
"display": {
|
||||||
"icon": { "item": "minecraft:tnt" },
|
"icon": { "item": "minecraft:tnt" },
|
||||||
"title": "Too Close",
|
"title": "Hmm, familiar...",
|
||||||
"description": "You were there when the towers fell",
|
"description": "You were there when the towers fell",
|
||||||
"frame": "challenge",
|
"frame": "challenge",
|
||||||
"show_toast": true,
|
"show_toast": true,
|
||||||
|
|||||||
@@ -3,3 +3,4 @@ accessWidener v2 named
|
|||||||
accessible field net/minecraft/client/gui/hud/InGameHud spyglassScale F
|
accessible field net/minecraft/client/gui/hud/InGameHud spyglassScale F
|
||||||
accessible field net/minecraft/entity/LivingEntity jumping Z
|
accessible field net/minecraft/entity/LivingEntity jumping Z
|
||||||
accessible class net/minecraft/client/gui/hud/InGameHud$HeartType
|
accessible class net/minecraft/client/gui/hud/InGameHud$HeartType
|
||||||
|
accessible field net/minecraft/server/network/ServerPlayerInteractionManager player Lnet/minecraft/server/network/ServerPlayerEntity;
|
||||||
@@ -4,9 +4,12 @@
|
|||||||
"package": "dev.tggamesyt.szar.mixin",
|
"package": "dev.tggamesyt.szar.mixin",
|
||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_17",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"PlayerEntityMixin",
|
|
||||||
"CraftingScreenHandlerMixin",
|
"CraftingScreenHandlerMixin",
|
||||||
"CraftingScreenHandlerMixin2",
|
"CraftingScreenHandlerMixin2",
|
||||||
|
"LivingEntityFallDamageMixin",
|
||||||
|
"PlaneBlockInteractionMixin",
|
||||||
|
"PlayerEntityMixin",
|
||||||
|
"PlayerInteractionMixin",
|
||||||
"RadiatedItemMixin"
|
"RadiatedItemMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
|
|||||||
Reference in New Issue
Block a user