forked from mirrors/cobblemon
Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
679920b786 | ||
|
|
c8ec4e6f1f | ||
|
|
cbcc6abe40 | ||
|
|
64c9d47b0f | ||
|
|
c0d2803f61 | ||
|
|
e249d5238f | ||
|
|
e32e505e95 | ||
|
|
7642a84108 | ||
|
|
b6e20d69cc | ||
|
|
9d04e20a30 | ||
|
|
d2624813f7 | ||
|
|
f6f607904e | ||
|
|
9284497cec | ||
|
|
36cb12952a | ||
|
|
2700dc7f39 |
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common;
|
||||
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.SmoothDouble;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface OrientationControllable {
|
||||
OrientationController getOrientationController();
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common;
|
||||
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.SmoothDouble;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface Rollable {
|
||||
|
||||
// From Minecraft's Camera
|
||||
Vector3f FORWARDS = new Vector3f(0.0F, 0.0F, -1.0F);
|
||||
Vector3f UP = new Vector3f(0.0F, 1.0F, 0.0F);
|
||||
Vector3f LEFT = new Vector3f(-1.0F, 0.0F, 0.0F);
|
||||
|
||||
@Nullable Matrix3f getOrientation();
|
||||
|
||||
Rollable updateOrientation(Function<Matrix3f, Matrix3f> update);
|
||||
|
||||
/**
|
||||
* @return The forward vector (0, 0, -1) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getForwardVector() {
|
||||
if (getOrientation() == null) return new Vector3f(FORWARDS);
|
||||
return getOrientation().transform(FORWARDS, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The left vector (-1, 0, 0) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getLeftVector() {
|
||||
if (getOrientation() == null) return new Vector3f(LEFT);
|
||||
return getOrientation().transform(LEFT, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The up vector (0, 1, 0) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getUpVector() {
|
||||
if (getOrientation() == null) return new Vector3f(UP);
|
||||
return getOrientation().transform(UP, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param yaw change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
|
||||
default Rollable rotateYaw(float yaw) {
|
||||
return updateOrientation(prev -> prev.rotateY((float) Math.toRadians(-yaw)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pitch change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
|
||||
default Rollable rotatePitch(float pitch) {
|
||||
return updateOrientation(prev -> prev.rotateX((float) Math.toRadians(-pitch)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param roll change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
default Rollable rotateRoll(float roll) {
|
||||
return updateOrientation(prev -> prev.rotateZ((float) Math.toRadians(-roll)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Order matters when rotating an object. If you need a different order, individually call rotateYaw, rotatePitch, and rotateRoll
|
||||
*
|
||||
* @param yaw change in degrees
|
||||
* @param pitch change in degrees
|
||||
* @param roll change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
default Rollable rotate(float yaw, float pitch, float roll) {
|
||||
return rotateYaw(yaw).rotatePitch(pitch).rotateRoll(roll);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The pitch angle in degrees as a float.
|
||||
* Value is between [-180, 180] with 0 being South, 90 being West, 180/-180 being North, and -90 being East
|
||||
*/
|
||||
default float getYaw() {
|
||||
return (float) Mth.wrapDegrees(-Math.toDegrees(FORWARDS.angleSigned(getForwardVector(), UP)) + 180);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The yaw angle in degrees as a float.
|
||||
* Value is between [-90, 90] with 0 being straight forward, 90 being straight down, and -90 being straight up
|
||||
*/
|
||||
default float getPitch() {
|
||||
return (float) Mth.wrapDegrees(-Math.toDegrees(Math.asin(getForwardVector().y)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The roll angle in degrees as a float.
|
||||
* Value is between [-180, 180] with 0 being no roll (normal), 90 being 90 degrees CW, 180/-180 being 180 degrees CW/CCW, and -90 being 90 degrees CCW
|
||||
*/
|
||||
default float getRoll() {
|
||||
//Cobblemon.LOGGER.info("{}", (float) Math.toDegrees(getUpVector().angleSigned(UP, getForwardVector())));
|
||||
return (float) Mth.wrapDegrees(-Math.toDegrees(getUpVector().angleSigned(UP, getForwardVector())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the angular velocity in degrees per second as a Vec3
|
||||
*/
|
||||
Vec3 angRollVel( double deltaTime );
|
||||
|
||||
public Vec3 rotationOnMouseXY(
|
||||
double yMouse,
|
||||
double xMouse,
|
||||
SmoothDouble yMouseSmoother,
|
||||
SmoothDouble xMouseSmoother,
|
||||
double sensitivity,
|
||||
double deltaTime
|
||||
);
|
||||
|
||||
boolean shouldRoll();
|
||||
|
||||
boolean useAngVelSmoothing();
|
||||
|
||||
void clearRotation();
|
||||
|
||||
}
|
||||
@@ -10,9 +10,10 @@ package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.CobblemonItems;
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents;
|
||||
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent;
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController;
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies;
|
||||
import com.cobblemon.mod.common.api.riding.Rideable;
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore;
|
||||
@@ -31,14 +32,11 @@ import com.cobblemon.mod.common.util.DataKeys;
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.SmoothDouble;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
@@ -46,18 +44,14 @@ import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.food.FoodProperties;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3f;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@@ -65,11 +59,10 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(Player.class)
|
||||
public abstract class PlayerMixin extends LivingEntity implements Rollable, ScannableEntity {
|
||||
public abstract class PlayerMixin extends LivingEntity implements ScannableEntity, OrientationControllable {
|
||||
|
||||
@Shadow public abstract CompoundTag getShoulderEntityLeft();
|
||||
|
||||
@@ -87,7 +80,7 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
|
||||
@Shadow public abstract void displayClientMessage(Component message, boolean overlay);
|
||||
|
||||
@Unique private Matrix3f orientation = null;
|
||||
@Unique private OrientationController cobblemon$orientationController = new OrientationController(this);
|
||||
|
||||
protected PlayerMixin(EntityType<? extends LivingEntity> p_20966_, Level p_20967_) {
|
||||
super(p_20966_, p_20967_);
|
||||
@@ -241,7 +234,7 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
|
||||
@Override
|
||||
public void absMoveTo(double x, double y, double z, float yaw, float pitch) {
|
||||
if (shouldRoll()) {
|
||||
if (cobblemon$orientationController.getActive()) {
|
||||
this.absMoveTo(x, y, z);
|
||||
this.setYRot(yaw % 360.0f);
|
||||
this.setXRot(pitch % 360.0f);
|
||||
@@ -254,111 +247,6 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
public void tick(CallbackInfo ci) {
|
||||
if (this.shouldRoll()) {
|
||||
// Proof of concept for yaw movement
|
||||
if (this.getMainHandItem().is(Items.STICK)) {
|
||||
this.rotateYaw(2);
|
||||
}
|
||||
else if (this.getMainHandItem().is(Items.BLAZE_ROD)) {
|
||||
this.rotateYaw(-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Matrix3f getOrientation() {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rollable updateOrientation(Function<Matrix3f, Matrix3f> update) {
|
||||
//Disabled to allow non mouse inputs to modify roll
|
||||
if (!shouldRoll()) return this;
|
||||
|
||||
if (this.orientation == null) {
|
||||
this.orientation = new Matrix3f();
|
||||
this.rotate(getYRot() - 180, getXRot(), 0);
|
||||
}
|
||||
this.orientation = update.apply(this.orientation);
|
||||
setYRot(this.getYaw());
|
||||
setXRot(this.getPitch());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRoll() {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return false;
|
||||
if (player.isHolding(Items.DIAMOND)) return true;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return false;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return false;
|
||||
|
||||
return pokemonEntity.getRiding().shouldRoll(pokemonEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3 rotationOnMouseXY(
|
||||
double yMouse,
|
||||
double xMouse,
|
||||
SmoothDouble yMouseSmoother,
|
||||
SmoothDouble xMouseSmoother,
|
||||
double sensitivity,
|
||||
double deltaTime
|
||||
) {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return Vec3.ZERO;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return Vec3.ZERO;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return Vec3.ZERO;
|
||||
|
||||
return pokemonEntity.getRiding().rotationOnMouseXY(
|
||||
pokemonEntity,
|
||||
player,
|
||||
yMouse,
|
||||
xMouse,
|
||||
yMouseSmoother,
|
||||
xMouseSmoother,
|
||||
sensitivity,
|
||||
deltaTime
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAngVelSmoothing() {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return true;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return true;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return true;
|
||||
|
||||
return pokemonEntity.getRiding().useAngVelSmoothing(pokemonEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3 angRollVel( double deltaTime ) {
|
||||
var ret = new Vec3(0.0, 0.0, 0.0);
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return ret;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return ret;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return ret;
|
||||
|
||||
return pokemonEntity.getRiding().angRollVel( pokemonEntity, player, deltaTime );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clearRotation() {
|
||||
this.orientation = null;
|
||||
}
|
||||
|
||||
@WrapOperation(
|
||||
method = "rideTick()V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;wantsToStopRiding()Z")
|
||||
@@ -370,4 +258,8 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
return original.call(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrientationController getOrientationController() {
|
||||
return cobblemon$orientationController;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork;
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController;
|
||||
import com.cobblemon.mod.common.mixin.accessor.ChunkMapAccessor;
|
||||
import com.cobblemon.mod.common.mixin.accessor.TrackedEntityAccessor;
|
||||
import com.cobblemon.mod.common.net.messages.client.orientation.S2CUpdateOrientationPacket;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.ServerEntity;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerPlayerConnection;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.joml.Matrix3f;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Mixin(ServerEntity.class)
|
||||
public abstract class ServerEntityMixin {
|
||||
|
||||
@Shadow @Final private Consumer<Packet<?>> broadcast;
|
||||
@Shadow @Final private Entity entity;
|
||||
@Unique
|
||||
private Matrix3f cobblemon$lastSentOrientation;
|
||||
private boolean cobblemon$lastSentActive;
|
||||
|
||||
@Inject(method = "sendChanges", at = @At("TAIL"))
|
||||
private void cobblemon$sendOrientationChanges(CallbackInfo ci) {
|
||||
if (!(this.entity instanceof OrientationControllable controllable)) return;
|
||||
|
||||
|
||||
OrientationController controller = controllable.getOrientationController();
|
||||
Matrix3f currOrientation = controller.getOrientation();
|
||||
boolean currActive = controller.getActive();
|
||||
|
||||
if (currOrientation == null || currOrientation.equals(cobblemon$lastSentOrientation) && (currActive == cobblemon$lastSentActive)) return;
|
||||
cobblemon$lastSentOrientation = new Matrix3f(currOrientation);
|
||||
cobblemon$lastSentActive = currActive;
|
||||
|
||||
|
||||
if (!(entity.level() instanceof ServerLevel level)) return;
|
||||
|
||||
ChunkMap chunkMap = level.getChunkSource().chunkMap;
|
||||
Int2ObjectMap<?> entityMap = ((ChunkMapAccessor) chunkMap).getEntityMap();
|
||||
Object tracked = entityMap.get(entity.getId());
|
||||
if (!(tracked instanceof TrackedEntityAccessor tracker)) return;
|
||||
|
||||
Set<ServerPlayerConnection> seenBy = tracker.getSeenBy();
|
||||
for (ServerPlayerConnection conn : seenBy) {
|
||||
ServerPlayer player = conn.getPlayer();
|
||||
if (player == entity) continue;
|
||||
CobblemonNetwork.INSTANCE.sendPacketToPlayer(player, new S2CUpdateOrientationPacket(currOrientation, currActive, entity.getId()));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
OrientationController controller = controllable.getOrientationController();
|
||||
Matrix3f currOrientation = controller.getOrientation();
|
||||
|
||||
if(currOrientation != cobblemon$lastSentOrientation) {
|
||||
cobblemon$lastSentOrientation = new Matrix3f(currOrientation);
|
||||
|
||||
//this.broadcast.accept(new S2CUpdateOrientationPacket(currOrientation,this.entity.getId()))
|
||||
|
||||
if (!(entity.level() instanceof ServerLevel level)) return;
|
||||
|
||||
ChunkMap chunkMap = level.getChunkSource().chunkMap;
|
||||
Long2ObjectMap<ChunkMap.TrackedEntity> entityMap = ((ChunkMapAccessor) chunkMap).getEntityMap();
|
||||
TrackedEntity trackedEntity = entityMap.get(entity.getId());
|
||||
if (trackedEntity == null) return;
|
||||
Set<ServerPlayerConnection> seenBy = ((TrackedEntityAccessor) trackedEntity).getSeenBy();
|
||||
for (ServerPlayerConnection conn : seenBy) {
|
||||
ServerPlayer player = conn.getPlayer();
|
||||
if (player == entity) continue; // optional safety filter
|
||||
CobblemonNetwork.sendPacketToPlayer(player, new S2CUpdateOrientationPacket(orientation, entity.getId()));
|
||||
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
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.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ServerPlayer.class)
|
||||
public abstract class ServerPlayerMixin {
|
||||
|
||||
@Inject(method = "rideTick", at = @At("HEAD"))
|
||||
private void cobblemon$updateOrientationControllerRideTick(CallbackInfo ci) {
|
||||
if (!(this instanceof OrientationControllable controllable)) return;
|
||||
var shouldUseCustomOrientation = cobblemon$shouldUseCustomOrientation((ServerPlayer)(Object)this);
|
||||
controllable.getOrientationController().setActive(shouldUseCustomOrientation);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private boolean cobblemon$shouldUseCustomOrientation(ServerPlayer player) {
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return false;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return false;
|
||||
return pokemonEntity.getRiding().shouldRoll(pokemonEntity);
|
||||
}
|
||||
|
||||
@Inject(method = "stopRiding", at = @At("HEAD"))
|
||||
public void cobblemon$resetOrientationOnDismount(CallbackInfo ci) {
|
||||
if (!(this instanceof OrientationControllable controllable)) return;
|
||||
controllable.getOrientationController().setActive(false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.accessor;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(ChunkMap.class)
|
||||
public interface ChunkMapAccessor {
|
||||
@Accessor("entityMap")
|
||||
Int2ObjectMap<?> getEntityMap();
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.accessor;
|
||||
|
||||
import net.minecraft.server.network.ServerPlayerConnection;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Mixin(targets = "net.minecraft.server.level.ChunkMap$TrackedEntity")
|
||||
public interface TrackedEntityAccessor {
|
||||
@Accessor("seenBy")
|
||||
Set<ServerPlayerConnection> getSeenBy();
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
@@ -35,10 +35,6 @@ public abstract class CameraMixin {
|
||||
@Shadow private float xRot;
|
||||
@Shadow private float yRot;
|
||||
|
||||
@Shadow public abstract float getXRot();
|
||||
|
||||
@Shadow public abstract float getYRot();
|
||||
|
||||
@Unique private float returnTimer = 0;
|
||||
@Unique private float rollAngleStart = 0;
|
||||
@Unique Minecraft minecraft = Minecraft.getInstance();
|
||||
@@ -47,51 +43,53 @@ public abstract class CameraMixin {
|
||||
|
||||
@Inject(method = "setRotation", at = @At("HEAD"), cancellable = true)
|
||||
public void open_camera$setRotation(float f, float g, CallbackInfo ci) {
|
||||
if (!(this.entity instanceof Rollable rollable) || disableRollableCameraDebug) return;
|
||||
if (!rollable.shouldRoll() && rollable.getOrientation() != null) {
|
||||
if (!(this.entity instanceof OrientationControllable controllable) || disableRollableCameraDebug) return;
|
||||
var controller = controllable.getOrientationController();
|
||||
if (!controller.isActive() && controller.getOrientation() != null) {
|
||||
if(this.returnTimer < 1) {
|
||||
//Rotation is taken from entity since we no longer handle mouse ourselves
|
||||
//Stops a period of time when you can't input anything.
|
||||
rollable.getOrientation().set(
|
||||
controller.getOrientation().set(
|
||||
new Matrix3f()
|
||||
.rotateY((float) Math.toRadians(180 - this.entity.getYRot()))
|
||||
.rotateX((float) Math.toRadians(-this.entity.getXRot()))
|
||||
);
|
||||
if(rollAngleStart == 0){
|
||||
this.returnTimer = 1;
|
||||
rollable.clearRotation();
|
||||
controller.reset();
|
||||
return;
|
||||
}
|
||||
rollable.getOrientation().rotateZ((float) Math.toRadians(-rollAngleStart*(1-returnTimer)));
|
||||
controller.getOrientation().rotateZ((float) Math.toRadians(-rollAngleStart*(1-returnTimer)));
|
||||
applyRotation();
|
||||
this.returnTimer += .05F;
|
||||
ci.cancel();
|
||||
} else {
|
||||
this.returnTimer = 1;
|
||||
rollable.clearRotation();
|
||||
controller.reset();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (rollable.getOrientation() == null) return;
|
||||
if (controller.getOrientation() == null) return;
|
||||
applyRotation();
|
||||
|
||||
this.returnTimer = 0;
|
||||
this.rollAngleStart = rollable.getRoll();
|
||||
this.rollAngleStart = controller.getRoll();
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void applyRotation(){
|
||||
if (!(this.entity instanceof Rollable rollable) || rollable.getOrientation() == null) return;
|
||||
var newRotation = rollable.getOrientation().normal(new Matrix3f()).getNormalizedRotation(new Quaternionf());
|
||||
if (!(this.entity instanceof OrientationControllable controllable) || controllable.getOrientationController().getOrientation() == null) return;
|
||||
var controller = controllable.getOrientationController();
|
||||
var newRotation = controller.getOrientation().normal(new Matrix3f()).getNormalizedRotation(new Quaternionf());
|
||||
if (this.minecraft.options.getCameraType().isMirrored()) {
|
||||
newRotation.rotateY((float)Math.toRadians(180));
|
||||
}
|
||||
this.rotation.set(newRotation);
|
||||
this.xRot = rollable.getPitch();
|
||||
this.yRot = rollable.getYaw();
|
||||
this.forwards.set(rollable.getForwardVector());
|
||||
this.up.set(rollable.getUpVector());
|
||||
this.left.set(rollable.getLeftVector());
|
||||
this.xRot = controller.getPitch();
|
||||
this.yRot = controller.getYaw();
|
||||
this.forwards.set(controller.getForwardVector());
|
||||
this.up.set(controller.getUpVector());
|
||||
this.left.set(controller.getLeftVector());
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -31,14 +31,14 @@ public class ItemInHandRendererMixin {
|
||||
if (abstractClientPlayer.isUsingItem() && abstractClientPlayer.getUseItem().getItem() instanceof PokedexItem) {
|
||||
ci.cancel();
|
||||
}
|
||||
else if (abstractClientPlayer instanceof Rollable rollable && rollable.shouldRoll()) {
|
||||
else if (abstractClientPlayer instanceof OrientationControllable controllable && controllable.getOrientationController().isActive()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(method = "renderHandsWithItems", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;mulPose(Lorg/joml/Quaternionf;)V", ordinal = 1))
|
||||
private void cobblemon$renderHandswithItems(PoseStack instance, Quaternionf quaternion) {
|
||||
if (!(Minecraft.getInstance().player instanceof Rollable rollable && rollable.shouldRoll())) {
|
||||
if (!(Minecraft.getInstance().player instanceof OrientationControllable controllable && controllable.getOrientationController().isActive())) {
|
||||
instance.mulPose(quaternion);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,15 @@
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork;
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.joml.Matrix3f;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
@@ -20,24 +26,53 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public class LocalPlayerMixin {
|
||||
public abstract class LocalPlayerMixin extends LivingEntity {
|
||||
|
||||
@Unique Matrix3f cobblemon$lastOrientation;
|
||||
|
||||
protected LocalPlayerMixin(EntityType<? extends LivingEntity> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
}
|
||||
|
||||
@Inject(method = "sendPosition", at = @At("TAIL"))
|
||||
private void cobblemon_updateRotationMatrix(CallbackInfo ci) {
|
||||
if (!(this instanceof Rollable rollable)) return;
|
||||
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
|
||||
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
|
||||
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
|
||||
private void cobblemon$updateRotationMatrix(CallbackInfo ci) {
|
||||
if (!(this instanceof OrientationControllable controllable)) return;
|
||||
var controller = controllable.getOrientationController();
|
||||
if (!controller.isActive() || controller.getOrientation() == cobblemon$lastOrientation) return;
|
||||
cobblemon$lastOrientation = controller.getOrientation() != null ? new Matrix3f(controller.getOrientation()) : null;
|
||||
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(controller.getOrientation()));
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientPacketListener;send(Lnet/minecraft/network/protocol/Packet;)V"))
|
||||
private void cobblemon_updateRotationMatrixPassenger(CallbackInfo ci) {
|
||||
if (!(this instanceof Rollable rollable)) return;
|
||||
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
|
||||
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
|
||||
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
|
||||
private void cobblemon$updateRotationMatrixPassenger(CallbackInfo ci) {
|
||||
if (!(this instanceof OrientationControllable controllable)) return;
|
||||
var controller = controllable.getOrientationController();
|
||||
if (!controller.isActive() || controller.getOrientation() == cobblemon$lastOrientation) return;
|
||||
cobblemon$lastOrientation = controller.getOrientation() != null ? new Matrix3f(controller.getOrientation()) : null;
|
||||
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(controller.getOrientation()));
|
||||
}
|
||||
|
||||
@Inject(method = "rideTick", at = @At("HEAD"))
|
||||
private void cobblemon$updateOrientationControllerRideTick(CallbackInfo ci) {
|
||||
if (Minecraft.getInstance().player != (Object)this) return;
|
||||
if (!(this instanceof OrientationControllable controllable)) return;
|
||||
var shouldUseCustomOrientation = cobblemon$shouldUseCustomOrientation((LocalPlayer)(Object)this);
|
||||
controllable.getOrientationController().setActive(shouldUseCustomOrientation);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private boolean cobblemon$shouldUseCustomOrientation(LocalPlayer player) {
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return false;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return false;
|
||||
return pokemonEntity.getRiding().shouldRoll(pokemonEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopRiding() {
|
||||
super.stopRiding();
|
||||
if (Minecraft.getInstance().player != (Object)this) return;
|
||||
if (!(this instanceof OrientationControllable controllable)) return;
|
||||
controllable.getOrientationController().setActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
|
||||
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.mojang.blaze3d.Blaze3D;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.MouseHandler;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
@@ -49,8 +49,6 @@ public class MouseHandlerMixin {
|
||||
|
||||
@Shadow private double accumulatedDY;
|
||||
|
||||
@Shadow private double accumulatedScrollX;
|
||||
|
||||
@Inject(
|
||||
method = "onScroll",
|
||||
at = @At(
|
||||
@@ -121,9 +119,9 @@ public class MouseHandlerMixin {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(player instanceof Rollable rollable)) return true;
|
||||
if (!(player instanceof OrientationControllable controllable)) return true;
|
||||
|
||||
if (!rollable.shouldRoll()) {
|
||||
if (!controllable.getOrientationController().isActive()) {
|
||||
xMouseSmoother.reset();
|
||||
yMouseSmoother.reset();
|
||||
pitchSmoother.reset();
|
||||
@@ -132,68 +130,100 @@ public class MouseHandlerMixin {
|
||||
return true;
|
||||
}
|
||||
|
||||
var defaultSensitivity = this.minecraft.options.sensitivity().get() * 0.6000000238418579 + 0.20000000298023224;
|
||||
var ridingSensitivity = Math.pow(defaultSensitivity, 3);
|
||||
|
||||
//Send mouse input to be interpreted into rotation
|
||||
//deltas by the ride controller
|
||||
Vec3 angVecMouse = rollable.rotationOnMouseXY(
|
||||
cursorDeltaY,
|
||||
cursorDeltaX ,
|
||||
yMouseSmoother,
|
||||
xMouseSmoother,
|
||||
ridingSensitivity,
|
||||
movementTime
|
||||
);
|
||||
Vec3 angVecMouse = cobblemon$getRideMouseRotation(cursorDeltaX, cursorDeltaY, movementTime);
|
||||
|
||||
//Perform Rotation using mouse influenced rotation deltas.
|
||||
rollable.rotate(
|
||||
controllable.getOrientationController().rotate(
|
||||
(float) angVecMouse.x,
|
||||
(float) angVecMouse.y,
|
||||
(float) angVecMouse.z
|
||||
);
|
||||
|
||||
|
||||
//Gather and apply the current rotation deltas
|
||||
var angRot = rollable.angRollVel(movementTime);
|
||||
var angRot = cobblemon$getAngularVelocity(movementTime);
|
||||
|
||||
//Apply smoothing if requested by the controller.
|
||||
//This Might be best if done by the controller itself?
|
||||
if( rollable.useAngVelSmoothing() )
|
||||
if(cobblemon$shouldUseAngVelSmoothing())
|
||||
{
|
||||
if( angRot != null ) {
|
||||
var yaw = yawSmoother.getNewDeltaValue(angRot.x * 0.5f, d);
|
||||
var pitch = pitchSmoother.getNewDeltaValue(angRot.y * 0.5f, d);
|
||||
var roll = rollSmoother.getNewDeltaValue(angRot.z * 0.5f, d);
|
||||
rollable.rotate((float) yaw, (float) pitch, (float) roll);
|
||||
}
|
||||
var yaw = yawSmoother.getNewDeltaValue(angRot.x * 0.5f, d);
|
||||
var pitch = pitchSmoother.getNewDeltaValue(angRot.y * 0.5f, d);
|
||||
var roll = rollSmoother.getNewDeltaValue(angRot.z * 0.5f, d);
|
||||
controllable.getOrientationController().rotate((float) yaw, (float) pitch, (float) roll);
|
||||
}
|
||||
//Otherwise simply apply the smoothing
|
||||
else
|
||||
{
|
||||
if( angRot != null ) {
|
||||
rollable.rotate((float) (
|
||||
angRot.x * 10 * d),
|
||||
(float) (angRot.y * 10 * d),
|
||||
(float) (angRot.z * 10 * d)
|
||||
);
|
||||
}
|
||||
controllable.getOrientationController().rotate((float) (angRot.x * 10 * d), (float) (angRot.y * 10 * d), (float) (angRot.z * 10 * d));
|
||||
}
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Inject(method = "handleAccumulatedMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;isMouseGrabbed()Z", ordinal = 0))
|
||||
private void cobblemon$maintainMovementWhenInScreens(CallbackInfo ci, @Local(ordinal = 1) double e) {
|
||||
if (minecraft.player == null) return;
|
||||
if (!(minecraft.player instanceof Rollable rollable)) return;
|
||||
if (!rollable.shouldRoll()) return;
|
||||
if (!(minecraft.player instanceof OrientationControllable controllable)) return;
|
||||
if (!controllable.getOrientationController().isActive()) return;
|
||||
if (minecraft.isPaused()) return;
|
||||
|
||||
var pitch = pitchSmoother.getNewDeltaValue(0, e);
|
||||
var roll = rollSmoother.getNewDeltaValue(0, e);
|
||||
rollable.rotate(0.0F, (float)pitch, (float)roll);
|
||||
controllable.getOrientationController().rotate(0.0F, (float)pitch, (float)roll);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private Vec3 cobblemon$getAngularVelocity(double deltaTime) {
|
||||
var player = minecraft.player;
|
||||
if (player == null) return Vec3.ZERO;
|
||||
if (!(player instanceof OrientationControllable)) return Vec3.ZERO;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return Vec3.ZERO;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return Vec3.ZERO;
|
||||
|
||||
return pokemonEntity.getRiding().angRollVel(pokemonEntity, player, deltaTime);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private Vec3 cobblemon$getRideMouseRotation(double mouseX, double mouseY, double deltaTime) {
|
||||
var player = minecraft.player;
|
||||
if (player == null) return Vec3.ZERO;
|
||||
var vehicle = player.getVehicle();
|
||||
if (vehicle == null) return Vec3.ZERO;
|
||||
if (!(vehicle instanceof PokemonEntity pokemon)) return Vec3.ZERO;
|
||||
|
||||
var sensitivity = cobblemon$getRidingSensitivity();
|
||||
|
||||
return pokemon.getRiding().rotationOnMouseXY(
|
||||
pokemon,
|
||||
player,
|
||||
mouseY,
|
||||
mouseX,
|
||||
yMouseSmoother,
|
||||
xMouseSmoother,
|
||||
sensitivity,
|
||||
deltaTime
|
||||
);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private double cobblemon$getRidingSensitivity() {
|
||||
var sensitivity = this.minecraft.options.sensitivity().get() * 0.6000000238418579 + 0.20000000298023224;
|
||||
return Math.pow(sensitivity, 3);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private boolean cobblemon$shouldUseAngVelSmoothing() {
|
||||
var player = minecraft.player;
|
||||
if (player == null) return true;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return true;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return true;
|
||||
|
||||
return pokemonEntity.getRiding().useAngVelSmoothing(pokemonEntity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.cobblemon.mod.common.client.net.gui.PokedexUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.npc.CloseNPCEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.npc.OpenNPCEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.orientation.S2CUpdateOrientationHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
|
||||
@@ -73,6 +74,7 @@ import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityP
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.npc.CloseNPCEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.npc.OpenNPCEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.orientation.S2CUpdateOrientationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonPasturedPacket
|
||||
@@ -387,6 +389,9 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(PokemonPasturedPacket.ID, PokemonPasturedPacket::decode, PokemonPasturedHandler))
|
||||
list.add(PacketRegisterInfo(PokemonUnpasturedPacket.ID, PokemonUnpasturedPacket::decode, PokemonUnpasturedHandler))
|
||||
|
||||
// Orientation
|
||||
list.add(PacketRegisterInfo(S2CUpdateOrientationPacket.ID, S2CUpdateOrientationPacket::decode, S2CUpdateOrientationHandler))
|
||||
|
||||
// Behaviours
|
||||
list.add(PacketRegisterInfo(PlayPosableAnimationPacket.ID, PlayPosableAnimationPacket::decode, PlayPosableAnimationHandler))
|
||||
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package com.cobblemon.mod.common.api.orientation
|
||||
|
||||
import com.cobblemon.mod.common.util.math.geometry.toDegrees
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import org.joml.Matrix3f
|
||||
import org.joml.Vector3f
|
||||
import kotlin.math.asin
|
||||
|
||||
open class OrientationController(val entity: LivingEntity) {
|
||||
|
||||
companion object {
|
||||
val FORWARDS: Vector3f = Vector3f(0.0f, 0.0f, -1.0f)
|
||||
val UP: Vector3f = Vector3f(0.0f, 1.0f, 0.0f)
|
||||
val LEFT: Vector3f = Vector3f(-1.0f, 0.0f, 0.0f)
|
||||
}
|
||||
|
||||
open var active: Boolean = false
|
||||
|
||||
var orientation: Matrix3f? = null
|
||||
private set
|
||||
|
||||
/** Adding this simply because it irritates me seeing `getActive` when most of this is Java. */
|
||||
fun isActive() = active
|
||||
|
||||
fun updateOrientation(fn: (Matrix3f) -> Matrix3f?) {
|
||||
if (!active) return
|
||||
if (orientation == null) {
|
||||
orientation = Matrix3f()
|
||||
rotate(entity.yRot - 180, entity.xRot, 0f)
|
||||
}
|
||||
orientation = fn(orientation!!)
|
||||
entity.yRot = yaw
|
||||
entity.xRot = pitch
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
orientation = null
|
||||
active = false
|
||||
}
|
||||
|
||||
fun rotate(yaw: Float, pitch: Float, roll: Float) {
|
||||
rotateYaw(yaw)
|
||||
rotatePitch(pitch)
|
||||
rotateRoll(roll)
|
||||
}
|
||||
|
||||
val forwardVector: Vector3f
|
||||
get() = orientation?.transform(FORWARDS, Vector3f()) ?: Vector3f(FORWARDS)
|
||||
|
||||
val leftVector: Vector3f
|
||||
get() = orientation?.transform(LEFT, Vector3f()) ?: Vector3f(LEFT)
|
||||
|
||||
val upVector : Vector3f
|
||||
get() = orientation?.transform(UP, Vector3f()) ?: Vector3f(UP)
|
||||
|
||||
fun rotateYaw(yaw: Float) = updateOrientation { it.rotateY(-yaw.toRadians()) }
|
||||
fun rotatePitch(pitch: Float) = updateOrientation { it.rotateX(-pitch.toRadians()) }
|
||||
fun rotateRoll(roll: Float) = updateOrientation { it.rotateZ(-roll.toRadians()) }
|
||||
|
||||
val yaw: Float
|
||||
get() = Mth.wrapDegrees(-FORWARDS.angleSigned(forwardVector, UP).toDegrees() + 180)
|
||||
|
||||
val pitch: Float
|
||||
get() = Mth.wrapDegrees(-asin(forwardVector.y).toDegrees())
|
||||
|
||||
val roll: Float
|
||||
get() = Mth.wrapDegrees(-upVector.angleSigned(UP, forwardVector).toDegrees())
|
||||
|
||||
}
|
||||
@@ -10,23 +10,17 @@ package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.toProperties
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.math.sin
|
||||
import kotlin.math.sin
|
||||
|
||||
data class RidingManager(val entity: PokemonEntity) {
|
||||
var lastSpeed = 0F
|
||||
@@ -74,15 +68,11 @@ data class RidingManager(val entity: PokemonEntity) {
|
||||
*/
|
||||
fun tick(entity: PokemonEntity, driver: Player, input: Vec3) {
|
||||
val controller = getController(entity) ?: return
|
||||
|
||||
val pose = controller.pose(entity)
|
||||
entity.entityData.set(PokemonEntity.POSE_TYPE, pose)
|
||||
//val speedPlayer = driver.deltaMovement.horizontalDistance()
|
||||
//driver.displayClientMessage(Component.literal("Speed player: ").withStyle { it.withColor(ChatFormatting.GREEN) }.append(Component.literal("$speedPlayer b/t")), true)
|
||||
//val speedEntity = entity.deltaMovement.length() //* 20 * 60 * 60) / ( 1000 )
|
||||
//println(speedEntity)
|
||||
//driver.displayClientMessage(Component.literal("Speed: ").withStyle { it.withColor(ChatFormatting.GREEN) }.append(Component.literal("${String.format("%.2f", speedEntity)} km/h")), true)
|
||||
|
||||
controller.tick(entity, driver, input)
|
||||
if (!entity.level().isClientSide) {
|
||||
val pose = controller.pose(entity)
|
||||
entity.entityData.set(PokemonEntity.POSE_TYPE, pose)
|
||||
}
|
||||
}
|
||||
|
||||
fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
@@ -217,4 +207,4 @@ data class RidingManager(val entity: PokemonEntity) {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.dismountOnShift(entity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-8
@@ -9,7 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.riding.controller
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.net.Decodable
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
import com.cobblemon.mod.common.api.riding.RidingState
|
||||
@@ -54,6 +54,8 @@ interface RideController : Encodable, Decodable {
|
||||
*/
|
||||
val condition: (PokemonEntity) -> Boolean
|
||||
|
||||
fun tick(entity: PokemonEntity, driver: Player, input: Vec3) {}
|
||||
|
||||
/**
|
||||
* Specifies the pose the ridden mount should be positioned in. This queries the pose provider using
|
||||
* the entity as a means of determining the conditions the entity is currently under. This allows for
|
||||
@@ -84,9 +86,7 @@ interface RideController : Encodable, Decodable {
|
||||
|
||||
fun clampPassengerRotation(entity: PokemonEntity, driver: LivingEntity) {}
|
||||
|
||||
fun updatePassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
driver.yRot = entity.yRot
|
||||
}
|
||||
fun updatePassengerRotation(entity: PokemonEntity, driver: LivingEntity) {}
|
||||
|
||||
/**
|
||||
* Manipulates the movement input as necessary by the controller. This is primarily used to apply limits
|
||||
@@ -113,7 +113,7 @@ interface RideController : Encodable, Decodable {
|
||||
|
||||
fun useRidingAltPose(entity: PokemonEntity, driver: Player): Boolean = false
|
||||
|
||||
//If function is not overwritten by controllers then just perform the defualt
|
||||
//If function is not overwritten by controllers then just perform the defauit
|
||||
//rolling function which is roll on mousex and pitch on mousey
|
||||
fun rotationOnMouseXY(
|
||||
entity: PokemonEntity,
|
||||
@@ -125,10 +125,9 @@ interface RideController : Encodable, Decodable {
|
||||
sensitivity: Double,
|
||||
deltaTime: Double
|
||||
): Vec3 {
|
||||
if (driver !is Rollable) return Vec3.ZERO
|
||||
if (driver !is OrientationControllable) return Vec3.ZERO
|
||||
|
||||
//Might need to add the smoothing here for default.
|
||||
val rollable = driver as Rollable
|
||||
val invertRoll = if (Cobblemon.config.invertRoll) -1 else 1
|
||||
val invertPitch = if (Cobblemon.config.invertPitch) -1 else 1
|
||||
return Vec3(0.0, yMouse * invertPitch, xMouse * invertRoll)
|
||||
@@ -150,4 +149,4 @@ interface RideController : Encodable, Decodable {
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeIdentifier(this.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-5
@@ -13,7 +13,6 @@ import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.entity.PokemonSideDelegate
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
@@ -42,11 +41,8 @@ import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix3f
|
||||
import org.joml.Vector3f
|
||||
|
||||
class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
companion object {
|
||||
@@ -440,4 +436,4 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
}
|
||||
cryAnimation = animation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net.orientation
|
||||
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.orientation.S2CUpdateOrientationPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
object S2CUpdateOrientationHandler : ClientNetworkPacketHandler<S2CUpdateOrientationPacket> {
|
||||
override fun handle(packet: S2CUpdateOrientationPacket, client: Minecraft) {
|
||||
val level = client.level ?: return
|
||||
val entity = level.getEntity(packet.entityId)
|
||||
if (entity is OrientationControllable) {
|
||||
entity.orientationController.updateOrientation { _ -> packet.orientation }
|
||||
packet.active?.let {
|
||||
entity.orientationController.active = it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -11,13 +11,12 @@ package com.cobblemon.mod.common.client.render.models.blockbench
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.client.ClientMoLangFunctions.animationFunctions
|
||||
import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
|
||||
import com.cobblemon.mod.common.client.entity.NPCClientDelegate
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
|
||||
import com.cobblemon.mod.common.client.render.AnimatedModelTextureSupplier
|
||||
import com.cobblemon.mod.common.client.render.ModelLayer
|
||||
@@ -717,12 +716,13 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
var scale = 1F
|
||||
// We could improve this to be generalized for other entities. First we'd have to figure out wtf is going on, though.
|
||||
if (entity is PokemonEntity) {
|
||||
if(entity.passengers.isNotEmpty() && entity.controllingPassenger is Rollable && (entity.controllingPassenger as Rollable).orientation != null){
|
||||
if(entity.passengers.isNotEmpty() && entity.controllingPassenger is OrientationControllable
|
||||
&& (entity.controllingPassenger as OrientationControllable).orientationController.orientation != null){
|
||||
val controllingPassenger = entity.controllingPassenger
|
||||
val transformationMatrix = Matrix4f()
|
||||
val center = Vector3f(0f, entity.bbHeight/2, 0f)
|
||||
transformationMatrix.translate(center)
|
||||
transformationMatrix.mul(Matrix4f((controllingPassenger as Rollable).orientation!!))
|
||||
transformationMatrix.mul(Matrix4f((controllingPassenger as OrientationControllable).orientationController.orientation!!))
|
||||
transformationMatrix.translate(center.negate())
|
||||
matrixStack.mulPose(transformationMatrix)
|
||||
} else {
|
||||
@@ -819,4 +819,4 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
condition = condition,
|
||||
animations = { animations(it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-8
@@ -9,7 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.render.player
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.Rideable
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockAnimationRepository
|
||||
@@ -20,6 +20,7 @@ import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.client.player.AbstractClientPlayer
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix3f
|
||||
import org.joml.Matrix4f
|
||||
import org.joml.Vector3f
|
||||
|
||||
@@ -48,10 +49,6 @@ object MountedPlayerRenderer {
|
||||
val locatorOffsetToCenter = locatorOffset.sub(center, Vector3f())
|
||||
|
||||
val transformationMatrix = Matrix4f()
|
||||
if (player is Rollable && player.shouldRoll()){
|
||||
//transformationMatrix.rotate(Axis.YP.rotationDegrees(-yBodyRot))
|
||||
//transformationMatrix.mulLocal(player.orientation)
|
||||
}
|
||||
|
||||
val rotatedOffset = transformationMatrix.transformPosition(locatorOffsetToCenter, Vector3f()).add(center).sub(Vector3f(0f, player.bbHeight/2, 0f))
|
||||
matrix.translate(rotatedOffset)
|
||||
@@ -73,12 +70,14 @@ object MountedPlayerRenderer {
|
||||
}
|
||||
|
||||
//Rotates player
|
||||
if (player is Rollable && player.shouldRoll() && !disableRollableRenderDebug) {
|
||||
val controller = (player as? OrientationControllable)?.orientationController ?: return
|
||||
if (controller.active && !disableRollableRenderDebug) {
|
||||
val center = Vector3f(0f, player.bbHeight / 2, 0f)
|
||||
val transformationMatrix = Matrix4f()
|
||||
transformationMatrix.translate(center)
|
||||
|
||||
transformationMatrix.mul(Matrix4f(player.orientation))
|
||||
val orientation = controller.orientation ?: Matrix3f()
|
||||
transformationMatrix.mul(Matrix4f(orientation))
|
||||
|
||||
transformationMatrix.translate(center.negate(Vector3f()))
|
||||
//Pre-Undo Yaw
|
||||
@@ -131,4 +130,4 @@ object MountedPlayerRenderer {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-5
@@ -9,7 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.render.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.battle.ClientBallDisplay
|
||||
@@ -178,18 +178,20 @@ class PokemonRenderer(
|
||||
packedLight: Int
|
||||
) {
|
||||
val driver = entity.firstPassenger ?: return
|
||||
val rollable = driver as? Rollable ?: return
|
||||
|
||||
val rollable = driver as? OrientationControllable ?: return
|
||||
val controller = rollable.orientationController
|
||||
poseMatrix.pushPose()
|
||||
|
||||
if(!DISABLE_ROLLING_DEBUG && rollable.shouldRoll()){
|
||||
if(!DISABLE_ROLLING_DEBUG && controller.active){
|
||||
val matrix = poseMatrix.last().pose()
|
||||
val yaw = Mth.rotLerp(partialTicks, entity.yBodyRotO, entity.yBodyRot)
|
||||
val center = Vector3f(0f, entity.bbHeight/2, 0f)
|
||||
val transformationMatrix = Matrix4f()
|
||||
//Move origin to center of Pokemon
|
||||
transformationMatrix.translate(center)
|
||||
transformationMatrix.mul(Matrix4f(rollable.orientation))
|
||||
|
||||
val orientation = controller.orientation ?: Matrix3f()
|
||||
transformationMatrix.mul(Matrix4f(orientation))
|
||||
//Move origin to base of the entity
|
||||
transformationMatrix.translate(center.negate(Vector3f()))
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.entity.pokemon
|
||||
import com.cobblemon.mod.common.*
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.drop.DropTable
|
||||
import com.cobblemon.mod.common.api.entity.Despawner
|
||||
import com.cobblemon.mod.common.api.entity.PokemonSender
|
||||
@@ -305,6 +304,11 @@ open class PokemonEntity(
|
||||
.addPokemonEntityFunctions(this)
|
||||
}
|
||||
|
||||
var flyDistO = 0F
|
||||
|
||||
var isPokemonWalking = false
|
||||
var isPokemonFlying = false
|
||||
|
||||
init {
|
||||
delegate.initialize(this)
|
||||
delegate.changePokemon(pokemon)
|
||||
@@ -394,6 +398,8 @@ open class PokemonEntity(
|
||||
// return super.canWalkOnFluid(state)
|
||||
}
|
||||
|
||||
override fun canSprint() = true
|
||||
|
||||
override fun handleEntityEvent(status: Byte) {
|
||||
delegate.handleStatus(status)
|
||||
super.handleEntityEvent(status)
|
||||
@@ -418,7 +424,13 @@ open class PokemonEntity(
|
||||
yHeadRotO = Mth.wrapDegrees(yHeadRotO)
|
||||
/* I'm sure it's not even us but something altering the logic of the loops in LivingEntity */
|
||||
|
||||
isPokemonFlying = flyDist - flyDistO > 0.005F
|
||||
isPokemonWalking = walkDist - walkDistO > 0.005F
|
||||
|
||||
val isMoving = entityData.get(MOVING)
|
||||
|
||||
super.tick()
|
||||
flyDistO = flyDist
|
||||
|
||||
if (isBattling) {
|
||||
// Deploy a platform if a non-wild Pokemon is touching water but not underwater.
|
||||
@@ -1771,7 +1783,7 @@ open class PokemonEntity(
|
||||
val center = Vector3f(0f, this.bbHeight/2, 0f)
|
||||
|
||||
val seatToCenter = center.sub(seatOffset, Vector3f())
|
||||
val matrix = (this.passengers.first() as Rollable).orientation ?: Matrix3f().rotate((180f-passenger.yRot).toRadians(), Vector3f(0f, 1f, 0f))
|
||||
val matrix = (this.passengers.first() as? OrientationControllable)?.orientationController?.orientation ?: Matrix3f().rotate((180f-passenger.yRot).toRadians(), Vector3f(0f, 1f, 0f))
|
||||
val rotatedOffset = matrix.transform(seatToCenter, Vector3f()).add(center).sub(Vector3f(0f, passenger.bbHeight/2, 0f))
|
||||
|
||||
positionUpdater.accept(passenger, this.x + rotatedOffset.x, this.y + rotatedOffset.y, this.z + rotatedOffset.z)
|
||||
@@ -1932,4 +1944,4 @@ open class PokemonEntity(
|
||||
override fun resolveEntityScan(): LivingEntity {
|
||||
return this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-11
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.entity.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.entity.PokemonSender
|
||||
import com.cobblemon.mod.common.api.entity.PokemonSideDelegate
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
@@ -23,23 +22,19 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.activestate.ActivePokemonState
|
||||
import com.cobblemon.mod.common.pokemon.activestate.SentOutState
|
||||
import com.cobblemon.mod.common.util.getIsSubmerged
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.playSoundServer
|
||||
import com.cobblemon.mod.common.util.update
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import java.util.Optional
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.syncher.EntityDataAccessor
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.pathfinder.PathType
|
||||
import org.joml.Matrix3f
|
||||
import org.joml.Vector3f
|
||||
import java.util.*
|
||||
|
||||
/** Handles purely server logic for a Pokémon */
|
||||
class PokemonServerDelegate : PokemonSideDelegate {
|
||||
@@ -119,7 +114,14 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
}
|
||||
entity.entityData.set(PokemonEntity.ASPECTS, trackedAspects)
|
||||
entity.entityData.set(PokemonEntity.LABEL_LEVEL, entity.pokemon.level)
|
||||
entity.entityData.set(PokemonEntity.MOVING, entity.platform == PlatformType.NONE && entity.deltaMovement.multiply(1.0, if (entity.onGround()) 0.0 else 1.0, 1.0).length() > 0.005F)
|
||||
|
||||
if (entity.getCurrentPoseType() in PoseType.FLYING_POSES) {
|
||||
entity.entityData.set(PokemonEntity.MOVING, entity.isPokemonFlying)
|
||||
}
|
||||
else {
|
||||
entity.entityData.set(PokemonEntity.MOVING, entity.isPokemonWalking)
|
||||
}
|
||||
|
||||
entity.entityData.set(PokemonEntity.FRIENDSHIP, entity.pokemon.friendship)
|
||||
entity.entityData.set(PokemonEntity.CAUGHT_BALL, trackedBall)
|
||||
|
||||
@@ -288,4 +290,4 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
entity.remove(Entity.RemovalReason.KILLED)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.messages.client.orientation
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readMatrix3f
|
||||
import com.cobblemon.mod.common.util.writeMatrix3f
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import org.joml.Matrix3f
|
||||
|
||||
/**
|
||||
* Packet sent from the server to update the current orientation of the
|
||||
* given entity for the remote entity receiving this packet.
|
||||
*
|
||||
* @author Jackowes
|
||||
* @since March 30th, 2025
|
||||
*/
|
||||
|
||||
class S2CUpdateOrientationPacket internal constructor(val orientation: Matrix3f?, val active: Boolean?, val entityId: Int) : NetworkPacket<S2CUpdateOrientationPacket> {
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeVarInt(entityId)
|
||||
buffer.writeBoolean(orientation != null)
|
||||
if (orientation != null && active != null) {
|
||||
buffer.writeMatrix3f(orientation)
|
||||
buffer.writeBoolean(active)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("s2c_update_orientation")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): S2CUpdateOrientationPacket {
|
||||
val entityId = buffer.readVarInt()
|
||||
val valid = buffer.readBoolean()
|
||||
val orientation = if (valid) buffer.readMatrix3f() else null
|
||||
val active = if (valid) buffer.readBoolean() else null
|
||||
return S2CUpdateOrientationPacket(orientation, active, entityId)
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -26,7 +26,7 @@ abstract class SpawnExtraDataEntityPacket<T: NetworkPacket<T>, E : Entity>(var v
|
||||
|
||||
abstract fun encodeEntityData(buffer: RegistryFriendlyByteBuf)
|
||||
|
||||
abstract fun applyData(entity: E)
|
||||
abstract fun applyData(entity: E, level: ClientLevel)
|
||||
|
||||
abstract fun checkType(entity: Entity): Boolean
|
||||
|
||||
@@ -48,7 +48,7 @@ abstract class SpawnExtraDataEntityPacket<T: NetworkPacket<T>, E : Entity>(var v
|
||||
)
|
||||
// Cobblemon start
|
||||
if (this.checkType(entity)) {
|
||||
this.applyData(entity as E)
|
||||
this.applyData(entity as E, world)
|
||||
}
|
||||
// Cobblemon end
|
||||
world.addEntity(entity)
|
||||
@@ -59,4 +59,4 @@ abstract class SpawnExtraDataEntityPacket<T: NetworkPacket<T>, E : Entity>(var v
|
||||
companion object {
|
||||
fun decodeVanillaPacket(buffer: RegistryFriendlyByteBuf) = ClientboundAddEntityPacket(buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
|
||||
import com.cobblemon.mod.common.net.IntSize
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@@ -36,7 +37,7 @@ class SpawnGenericBedrockPacket(
|
||||
) : SpawnExtraDataEntityPacket<SpawnGenericBedrockPacket, GenericBedrockEntity>(vanillaSpawnPacket) {
|
||||
override val id: ResourceLocation = ID
|
||||
|
||||
override fun applyData(entity: GenericBedrockEntity) {
|
||||
override fun applyData(entity: GenericBedrockEntity, level: ClientLevel) {
|
||||
entity.category = this.category
|
||||
entity.aspects = this.aspects
|
||||
entity.entityData.set(GenericBedrockEntity.POSE_TYPE, this.poseType)
|
||||
@@ -74,4 +75,4 @@ class SpawnGenericBedrockPacket(
|
||||
return SpawnGenericBedrockPacket(category, aspects, poseType, scale, width, height, startAge, vanillaPacket)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -22,6 +22,7 @@ import com.cobblemon.mod.common.util.writeEnumConstant
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import com.cobblemon.mod.common.util.writeText
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import java.util.UUID
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.chat.Component
|
||||
@@ -69,7 +70,7 @@ class SpawnNPCPacket(
|
||||
buffer.writeBoolean(this.hideNameTag)
|
||||
}
|
||||
|
||||
override fun applyData(entity: NPCEntity) {
|
||||
override fun applyData(entity: NPCEntity, level: ClientLevel) {
|
||||
entity.npc = NPCClasses.getByIdentifier(this.npcClass) ?: error("received unknown NPCClass: $npcClass")
|
||||
entity.customName = name
|
||||
entity.entityData.set(NPCEntity.LEVEL, this.level)
|
||||
@@ -104,4 +105,4 @@ class SpawnNPCPacket(
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
|
||||
import com.cobblemon.mod.common.pokeball.PokeBall
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@@ -30,7 +31,7 @@ class SpawnPokeballPacket(
|
||||
buffer.writeCollection(aspects) { _, aspect -> buffer.writeString(aspect)}
|
||||
}
|
||||
|
||||
override fun applyData(entity: EmptyPokeBallEntity) {
|
||||
override fun applyData(entity: EmptyPokeBallEntity, level: ClientLevel) {
|
||||
entity.pokeBall = this.pokeBall
|
||||
entity.aspects = this.aspects
|
||||
}
|
||||
@@ -47,4 +48,4 @@ class SpawnPokeballPacket(
|
||||
return SpawnPokeballPacket(pokeBall, aspects, vanillaPacket)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-4
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import java.util.UUID
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
@@ -44,7 +45,8 @@ class SpawnPokemonPacket(
|
||||
var spawnYaw: Float,
|
||||
var friendship: Int,
|
||||
var freezeFrame: Float,
|
||||
vanillaSpawnPacket: ClientboundAddEntityPacket
|
||||
var passengers: IntArray,
|
||||
vanillaSpawnPacket: ClientboundAddEntityPacket,
|
||||
) : SpawnExtraDataEntityPacket<SpawnPokemonPacket, PokemonEntity>(vanillaSpawnPacket) {
|
||||
|
||||
override val id: ResourceLocation = ID
|
||||
@@ -70,6 +72,7 @@ class SpawnPokemonPacket(
|
||||
entity.entityData.get(PokemonEntity.SPAWN_DIRECTION),
|
||||
entity.entityData.get(PokemonEntity.FRIENDSHIP),
|
||||
entity.entityData.get(PokemonEntity.FREEZE_FRAME),
|
||||
entity.passengers.map { it.id }.toIntArray(),
|
||||
vanillaSpawnPacket
|
||||
)
|
||||
|
||||
@@ -94,9 +97,10 @@ class SpawnPokemonPacket(
|
||||
buffer.writeFloat(this.spawnYaw)
|
||||
buffer.writeInt(this.friendship)
|
||||
buffer.writeFloat(this.freezeFrame)
|
||||
buffer.writeVarIntArray(this.passengers)
|
||||
}
|
||||
|
||||
override fun applyData(entity: PokemonEntity) {
|
||||
override fun applyData(entity: PokemonEntity, level: ClientLevel) {
|
||||
entity.ownerUUID = ownerId
|
||||
entity.pokemon.apply {
|
||||
scaleModifier = this@SpawnPokemonPacket.scaleModifier
|
||||
@@ -121,6 +125,12 @@ class SpawnPokemonPacket(
|
||||
entity.entityData.set(PokemonEntity.SPAWN_DIRECTION, spawnYaw)
|
||||
entity.entityData.set(PokemonEntity.FRIENDSHIP, friendship)
|
||||
entity.entityData.set(PokemonEntity.FREEZE_FRAME, freezeFrame)
|
||||
|
||||
entity.ejectPassengers()
|
||||
passengers.forEach {
|
||||
val passenger = level.getEntity(it) ?: return@forEach
|
||||
passenger.startRiding(entity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun checkType(entity: Entity): Boolean = entity is PokemonEntity
|
||||
@@ -148,10 +158,11 @@ class SpawnPokemonPacket(
|
||||
val spawnAngle = buffer.readFloat()
|
||||
val friendship = buffer.readInt()
|
||||
val freezeFrame = buffer.readFloat()
|
||||
val passengers = buffer.readVarIntArray()
|
||||
val vanillaPacket = decodeVanillaPacket(buffer)
|
||||
|
||||
return SpawnPokemonPacket(ownerId, scaleModifier, speciesId, gender, shiny, formName, aspects, battleId, phasingTargetId, beamModeEmitter, platform, nickname, labelLevel, poseType, unbattlable, hideLabel, caughtBall, spawnAngle, friendship, freezeFrame, vanillaPacket)
|
||||
return SpawnPokemonPacket(ownerId, scaleModifier, speciesId, gender, shiny, formName, aspects, battleId, phasingTargetId, beamModeEmitter, platform, nickname, labelLevel, poseType, unbattlable, hideLabel, caughtBall, spawnAngle, friendship, freezeFrame, passengers, vanillaPacket)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+12
-3
@@ -8,16 +8,25 @@
|
||||
|
||||
package com.cobblemon.mod.common.net.serverhandling.orientation
|
||||
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import kotlin.math.atan2
|
||||
|
||||
object OrientationPacketHandler : ServerNetworkPacketHandler<C2SUpdateOrientationPacket> {
|
||||
override fun handle(packet: C2SUpdateOrientationPacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
if (player is Rollable) {
|
||||
player.updateOrientation { _ -> packet.orientation }
|
||||
if (player is OrientationControllable) {
|
||||
player.orientationController.updateOrientation { _ -> packet.orientation }
|
||||
|
||||
println("Packet Received! Roll ${"%.2f".format(player.orientationController.roll)} degrees")
|
||||
|
||||
// val orientation = packet.orientation
|
||||
// val roll = orientation?.let { atan2(it.m10, it.m00) } ?: 0f
|
||||
// val rollDegrees = Math.toDegrees(roll.toDouble())
|
||||
// println("Packet Received! Roll: ${"%.2f".format(rollDegrees)} degrees")
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+26
-32
@@ -11,7 +11,7 @@ package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
@@ -19,9 +19,7 @@ import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.riding.states.BirdAirState
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
@@ -32,9 +30,7 @@ import kotlin.math.*
|
||||
class BirdAirController : RideController {
|
||||
override val key = KEY
|
||||
override val poseProvider = PoseProvider(PoseType.HOVER)
|
||||
.with(PoseOption(PoseType.FLY) {
|
||||
val player = it.passengers.firstOrNull() as? Player ?: return@PoseOption false
|
||||
it.deltaMovement.length() > 0.5 })
|
||||
.with(PoseOption(PoseType.FLY) { it.entityData.get(PokemonEntity.MOVING) })
|
||||
|
||||
override val condition: (PokemonEntity) -> Boolean = { true }
|
||||
|
||||
@@ -82,15 +78,15 @@ class BirdAirController : RideController {
|
||||
calculateRideSpaceVel(entity, driver, state)
|
||||
|
||||
//Translate ride space velocity to world space velocity.
|
||||
val rollable = driver as? Rollable
|
||||
if (rollable != null) {
|
||||
val controller = (driver as? OrientationControllable)?.orientationController
|
||||
if (controller != null) {
|
||||
//Need to deadzone this when straight up or down
|
||||
|
||||
upForce += -1.0 * sin(Math.toRadians(rollable.pitch.toDouble())) * state.rideVel.z
|
||||
forwardForce += cos(Math.toRadians(rollable.pitch.toDouble())) * state.rideVel.z
|
||||
upForce += -1.0 * sin(Math.toRadians(controller.pitch.toDouble())) * state.rideVel.z
|
||||
forwardForce += cos(Math.toRadians(controller.pitch.toDouble())) * state.rideVel.z
|
||||
|
||||
upForce += cos(Math.toRadians(rollable.pitch.toDouble())) * state.rideVel.y
|
||||
forwardForce += sin(Math.toRadians(rollable.pitch.toDouble())) * state.rideVel.y
|
||||
upForce += cos(Math.toRadians(controller.pitch.toDouble())) * state.rideVel.y
|
||||
forwardForce += sin(Math.toRadians(controller.pitch.toDouble())) * state.rideVel.y
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +109,7 @@ class BirdAirController : RideController {
|
||||
|
||||
override fun angRollVel(entity: PokemonEntity, driver: Player, deltaTime: Double): Vec3 {
|
||||
|
||||
val rollable = driver as? Rollable
|
||||
val controller = (driver as? OrientationControllable)?.orientationController
|
||||
val state = getState(entity, ::BirdAirState)
|
||||
|
||||
//TODO: Tie in handling
|
||||
@@ -121,14 +117,14 @@ class BirdAirController : RideController {
|
||||
val topSpeed = getRuntime(entity).resolveDouble(topSpeedExpr)
|
||||
val rotationChangeRate = 10.0
|
||||
|
||||
if (rollable != null) {
|
||||
var yawForce = rotationChangeRate * sin(Math.toRadians(rollable.roll.toDouble()))
|
||||
if (controller != null) {
|
||||
var yawForce = rotationChangeRate * sin(Math.toRadians(controller.roll.toDouble()))
|
||||
//for a bit of correction on the rolls influence pitch as well
|
||||
var pitchForce = -0.35 * rotationChangeRate * abs(sin(Math.toRadians(rollable.roll.toDouble())))
|
||||
var pitchForce = -0.35 * rotationChangeRate * abs(sin(Math.toRadians(controller.roll.toDouble())))
|
||||
|
||||
//limit rotation modulation when pitched up heavily or pitched down heavily
|
||||
yawForce *= abs(cos(Math.toRadians(rollable.pitch.toDouble())))
|
||||
pitchForce *= abs(cos(Math.toRadians(rollable.pitch.toDouble()))) * 1.5
|
||||
yawForce *= abs(cos(Math.toRadians(controller.pitch.toDouble())))
|
||||
pitchForce *= abs(cos(Math.toRadians(controller.pitch.toDouble()))) * 1.5
|
||||
|
||||
return Vec3(yawForce, pitchForce, 0.0)
|
||||
}
|
||||
@@ -146,8 +142,8 @@ class BirdAirController : RideController {
|
||||
sensitivity: Double,
|
||||
deltaTime: Double
|
||||
): Vec3 {
|
||||
if (driver !is Rollable) return Vec3.ZERO
|
||||
val rollable = driver as Rollable
|
||||
if (driver !is OrientationControllable) return Vec3.ZERO
|
||||
val controller = (driver as OrientationControllable).orientationController
|
||||
|
||||
val state = getState(entity, ::BirdAirState)
|
||||
val handling = getRuntime(entity).resolveDouble(handlingExpr)
|
||||
@@ -169,12 +165,12 @@ class BirdAirController : RideController {
|
||||
//Limit roll by non linearly decreasing inputs towards
|
||||
// a rotation limit based on the current distance from
|
||||
// that rotation limit
|
||||
if (abs(rollable.roll + rollForce) < rotLimit) {
|
||||
if (sign(rollForce) == sign(rollable.roll).toDouble()) {
|
||||
val d = abs(abs(rollable.roll) - rotLimit)
|
||||
if (abs(controller.roll + rollForce) < rotLimit) {
|
||||
if (sign(rollForce) == sign(controller.roll).toDouble()) {
|
||||
val d = abs(abs(controller.roll) - rotLimit)
|
||||
rollForce *= (d.pow(2)) / (rotLimit.pow(2))
|
||||
}
|
||||
} else if (sign(rollForce) == sign(rollable.roll).toDouble()) {
|
||||
} else if (sign(rollForce) == sign(controller.roll).toDouble()) {
|
||||
rollForce = 0.0
|
||||
}
|
||||
|
||||
@@ -273,8 +269,6 @@ class BirdAirController : RideController {
|
||||
* Calculates the change in the ride space vector due to player input and ride state
|
||||
*/
|
||||
fun calculateRideSpaceVel(entity: PokemonEntity, driver: Player, state: BirdAirState) {
|
||||
|
||||
|
||||
//retrieve stats
|
||||
val topSpeed = getRuntime(entity).resolveDouble(topSpeedExpr)
|
||||
val glideTopSpeed = getRuntime(entity).resolveDouble(glideTopSpeedExpr)
|
||||
@@ -305,10 +299,10 @@ class BirdAirController : RideController {
|
||||
activeInput = true
|
||||
}
|
||||
|
||||
val rollable = driver as? Rollable
|
||||
if (rollable != null) {
|
||||
val controller = (driver as? OrientationControllable)?.orientationController
|
||||
if (controller != null) {
|
||||
//Base glide speed change on current pitch of the ride.
|
||||
glideSpeedChange = sin(Math.toRadians(rollable.pitch.toDouble()))
|
||||
glideSpeedChange = sin(Math.toRadians(controller.pitch.toDouble()))
|
||||
glideSpeedChange = glideSpeedChange.pow(3) * 0.5
|
||||
|
||||
//TODO: Possibly create a deadzone around parallel where glide doesn't affect speed?
|
||||
@@ -353,8 +347,8 @@ class BirdAirController : RideController {
|
||||
//Vertical movement based on driver input.
|
||||
val vertTopSpeed = topSpeed / 2.0
|
||||
val vertInput = when {
|
||||
Minecraft.getInstance().options.keyJump.isDown() -> 1.0
|
||||
Minecraft.getInstance().options.keyShift.isDown() -> -1.0
|
||||
driver.jumping -> 1.0
|
||||
driver.isShiftKeyDown -> -1.0
|
||||
else -> 0.0
|
||||
}
|
||||
|
||||
@@ -399,4 +393,4 @@ class BirdAirController : RideController {
|
||||
state.rideVel.y,
|
||||
lerp( state.rideVel.z,0.0, topSpeed / ( 20.0 * 30.0)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-15
@@ -9,13 +9,12 @@
|
||||
package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@@ -28,7 +27,6 @@ import net.minecraft.world.phys.shapes.Shapes
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
import kotlin.math.sqrt
|
||||
|
||||
class DolphinController : RideController {
|
||||
companion object {
|
||||
@@ -54,7 +52,8 @@ class DolphinController : RideController {
|
||||
|
||||
override val key: ResourceLocation = KEY
|
||||
override val poseProvider: PoseProvider = PoseProvider(PoseType.FLOAT)
|
||||
.with(PoseOption(PoseType.SWIM) { it.deltaMovement.length() >= 0.05 })
|
||||
.with(PoseOption(PoseType.SWIM) { it.entityData.get(PokemonEntity.MOVING) })
|
||||
|
||||
override val condition: (PokemonEntity) -> Boolean = { entity ->
|
||||
|
||||
//If there are only fluid blocks or air block below the ride
|
||||
@@ -110,12 +109,12 @@ class DolphinController : RideController {
|
||||
//Not sure if this is desired? Will need to mess around with this
|
||||
//a bit more
|
||||
var zComp = 0.0
|
||||
val rollable = driver as? Rollable
|
||||
if (rollable != null)
|
||||
val controller = (driver as? OrientationControllable)?.orientationController
|
||||
if (controller != null)
|
||||
{
|
||||
//Can be used again if I better figure out how to deadzone it near the tops?
|
||||
zComp = -1.0 * g.toDouble() * sin(Math.toRadians(rollable.roll.toDouble()))
|
||||
yComp = -1.0 * g.toDouble() * sin(Math.toRadians(rollable.pitch.toDouble()))
|
||||
zComp = -1.0 * g.toDouble() * sin(Math.toRadians(controller.roll.toDouble()))
|
||||
yComp = -1.0 * g.toDouble() * sin(Math.toRadians(controller.pitch.toDouble()))
|
||||
}
|
||||
|
||||
val currVelocity = Vec3(0.0, yComp , g.toDouble())
|
||||
@@ -130,17 +129,17 @@ class DolphinController : RideController {
|
||||
return Vec3(0.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
val rollable = driver as? Rollable
|
||||
val controller = (driver as? OrientationControllable)?.orientationController
|
||||
|
||||
//this should be changed to be speed maybe?
|
||||
val movingForce = driver.zza
|
||||
if (rollable != null) {
|
||||
var yawAngVel = 3 * sin(Math.toRadians(rollable.roll.toDouble())).toFloat()
|
||||
var pitchAngVel = -1 * Math.abs(sin(Math.toRadians(rollable.roll.toDouble())).toFloat())
|
||||
if (controller != null) {
|
||||
var yawAngVel = 3 * sin(Math.toRadians(controller.roll.toDouble())).toFloat()
|
||||
var pitchAngVel = -1 * Math.abs(sin(Math.toRadians(controller.roll.toDouble())).toFloat())
|
||||
|
||||
//limit rotation modulation when pitched up heavily or pitched down heavily
|
||||
yawAngVel *= (abs(cos(Math.toRadians(rollable.pitch.toDouble())))).toFloat()
|
||||
pitchAngVel *= (abs(cos(Math.toRadians(rollable.pitch.toDouble())))).toFloat()
|
||||
yawAngVel *= (abs(cos(Math.toRadians(controller.pitch.toDouble())))).toFloat()
|
||||
pitchAngVel *= (abs(cos(Math.toRadians(controller.pitch.toDouble())))).toFloat()
|
||||
//if you are not pressing forward then don't turn
|
||||
//yawAngVel *= movingForce
|
||||
//Ignore x,y,z its angular velocity:
|
||||
@@ -199,4 +198,4 @@ class DolphinController : RideController {
|
||||
val z = buffer.readDouble()
|
||||
this.lastVelocity = Vec3(x, y, z)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-15
@@ -45,6 +45,18 @@ class FallToFlightCompositeController : RideController {
|
||||
var flightController: RideController = GliderAirController()
|
||||
private set
|
||||
|
||||
override fun tick(entity: PokemonEntity, driver: Player, input: Vec3) {
|
||||
val state = getState(entity, ::CompositeState)
|
||||
val shouldBeFlying = checkShouldBeFlying(entity, state.activeController == flightController)
|
||||
if (state.activeController == flightController && !shouldBeFlying) { // && entity.onGround() && state.timeTransitioned + 20 < entity.level().gameTime) {
|
||||
state.activeController = landController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
|
||||
} else if (state.activeController == landController && shouldBeFlying) {
|
||||
state.activeController = flightController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun pose(entity: PokemonEntity): PoseType {
|
||||
return getActiveController(entity).poseProvider.select(entity)
|
||||
}
|
||||
@@ -77,20 +89,7 @@ class FallToFlightCompositeController : RideController {
|
||||
}
|
||||
}
|
||||
|
||||
override fun speed(
|
||||
entity: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
val state = getState(entity, ::CompositeState)
|
||||
val shouldBeFlying = checkShouldBeFlying(entity, state.activeController == flightController)
|
||||
if (state.activeController == flightController && !shouldBeFlying) { // && entity.onGround() && state.timeTransitioned + 20 < entity.level().gameTime) {
|
||||
state.activeController = landController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
|
||||
} else if (state.activeController == landController && shouldBeFlying) {
|
||||
state.activeController = flightController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
}
|
||||
|
||||
override fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
return getActiveController(entity).speed(entity, driver)
|
||||
}
|
||||
|
||||
@@ -149,4 +148,4 @@ class FallToFlightCompositeController : RideController {
|
||||
companion object {
|
||||
val KEY = cobblemonResource("composite/fall_to_flight")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-7
@@ -10,16 +10,13 @@ package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.riding.states.GenericLandState
|
||||
import com.cobblemon.mod.common.pokemon.riding.states.JetAirState
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
@@ -28,7 +25,9 @@ import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import kotlin.math.*
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
|
||||
class GenericLandController : RideController {
|
||||
companion object {
|
||||
@@ -66,8 +65,11 @@ class GenericLandController : RideController {
|
||||
|
||||
@Transient
|
||||
override val key: ResourceLocation = KEY
|
||||
|
||||
@Transient
|
||||
override val poseProvider: PoseProvider = PoseProvider(PoseType.STAND).with(PoseOption(PoseType.WALK) { it.deltaMovement.horizontalDistance() > 0.1 })
|
||||
override val poseProvider: PoseProvider = PoseProvider(PoseType.STAND)
|
||||
.with(PoseOption(PoseType.WALK) { it.entityData.get(PokemonEntity.MOVING) })
|
||||
|
||||
@Transient
|
||||
override val condition: (PokemonEntity) -> Boolean = { entity ->
|
||||
// Are there any blocks under the mon that aren't air or fluid
|
||||
@@ -115,7 +117,7 @@ class GenericLandController : RideController {
|
||||
calculateRideSpaceVel(entity, driver, state)
|
||||
|
||||
//Jump the thang!
|
||||
if (Minecraft.getInstance().options.keyJump.isDown() && entity.onGround()) {
|
||||
if (driver.jumping && entity.onGround()) {
|
||||
state.rideVel = Vec3(state.rideVel.x, 2.0, state.rideVel.z)
|
||||
}
|
||||
|
||||
@@ -245,4 +247,4 @@ class GenericLandController : RideController {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -51,8 +51,10 @@ class GenericLiquidController : RideController {
|
||||
private set
|
||||
|
||||
override val key: ResourceLocation = KEY
|
||||
|
||||
override val poseProvider: PoseProvider = PoseProvider(PoseType.FLOAT)
|
||||
.with(PoseOption(PoseType.SWIM) { it.isSwimming && it.entityData.get(PokemonEntity.MOVING) })
|
||||
|
||||
override val condition: (PokemonEntity) -> Boolean = { entity ->
|
||||
//This could be kinda weird... what if the top of the mon is in a fluid but the bottom isnt?
|
||||
Shapes.create(entity.boundingBox).blockPositionsAsListRounded().any {
|
||||
@@ -120,4 +122,4 @@ class GenericLiquidController : RideController {
|
||||
this.reverseDriveFactor = buffer.readString().asExpression()
|
||||
this.strafeFactor = buffer.readString().asExpression()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ import net.minecraft.world.phys.Vec3
|
||||
class GliderAirController : RideController {
|
||||
override val key = KEY
|
||||
override val poseProvider = PoseProvider(PoseType.HOVER)
|
||||
.with(PoseOption(PoseType.FLY) { it.deltaMovement.horizontalDistance() > 0.1 })
|
||||
.with(PoseOption(PoseType.FLY) { it.entityData.get(PokemonEntity.MOVING) })
|
||||
override val condition: (PokemonEntity) -> Boolean = { true }
|
||||
|
||||
var glideSpeed: Expression = "0.1".asExpression()
|
||||
|
||||
+17
-17
@@ -10,7 +10,7 @@ package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
@@ -38,7 +38,7 @@ import kotlin.math.sin
|
||||
class HelicopterAirController : RideController {
|
||||
override val key = KEY
|
||||
override val poseProvider = PoseProvider(PoseType.HOVER)
|
||||
.with(PoseOption(PoseType.FLY) { it.deltaMovement.horizontalDistance() > 0.1 })
|
||||
.with(PoseOption(PoseType.FLY) { it.entityData.get(PokemonEntity.MOVING) })
|
||||
|
||||
//If there are only fluid blocks or air block below the ride
|
||||
//then activate the controller. If it is in water the ride will
|
||||
@@ -87,12 +87,12 @@ class HelicopterAirController : RideController {
|
||||
var xVel = 0.0
|
||||
var zVel = 0.0
|
||||
|
||||
val rollable = driver as? Rollable
|
||||
val controller = (driver as? OrientationControllable)?.orientationController
|
||||
|
||||
//Horizontal velocity is based on pitch and roll
|
||||
if (rollable != null) {
|
||||
xVel = -1.0 * sin(Math.toRadians(rollable.roll.toDouble()))
|
||||
zVel = sin(Math.toRadians(rollable.pitch.toDouble()))
|
||||
if (controller != null) {
|
||||
xVel = -1.0 * sin(Math.toRadians(controller.roll.toDouble()))
|
||||
zVel = sin(Math.toRadians(controller.pitch.toDouble()))
|
||||
}
|
||||
|
||||
return Vec3(xVel, yVel, zVel)
|
||||
@@ -101,7 +101,7 @@ class HelicopterAirController : RideController {
|
||||
|
||||
override fun angRollVel(entity: PokemonEntity, driver: Player, deltaTime: Double): Vec3 {
|
||||
|
||||
val rollable = driver as? Rollable
|
||||
val controller = (driver as? OrientationControllable)?.orientationController
|
||||
|
||||
//In degrees per second? It was supposed to be I think but
|
||||
//I have messed something up
|
||||
@@ -113,7 +113,7 @@ class HelicopterAirController : RideController {
|
||||
|
||||
|
||||
//TODO: Fix accumulated movement causing pitch and roll out of set bounds
|
||||
if (rollable != null) {
|
||||
if (controller != null) {
|
||||
//If the roll or pitch have exceeded the limit then do not modulate that
|
||||
//rotation in that direction further
|
||||
|
||||
@@ -124,20 +124,20 @@ class HelicopterAirController : RideController {
|
||||
|
||||
//The three denotes that the force will be 1/3 what it would have been at
|
||||
//the rotation limit
|
||||
rollForce *= 2.0.pow(-1.0 * (abs(rollable.roll.toDouble()) / ROTATION_LIMIT))
|
||||
rollForce *= 2.0.pow(-1.0 * (abs(controller.roll.toDouble()) / ROTATION_LIMIT))
|
||||
|
||||
pitchForce *= 2.0.pow(-1.0 * (abs(rollable.pitch.toDouble()) / ROTATION_LIMIT))
|
||||
pitchForce *= 2.0.pow(-1.0 * (abs(controller.pitch.toDouble()) / ROTATION_LIMIT))
|
||||
|
||||
if (rollable.roll >= ROTATION_LIMIT && rollForce > 0.0) {
|
||||
if (controller.roll >= ROTATION_LIMIT && rollForce > 0.0) {
|
||||
rollForce = 0.0;
|
||||
}
|
||||
if (rollable.roll <= -ROTATION_LIMIT && rollForce < 0.0) {
|
||||
if (controller.roll <= -ROTATION_LIMIT && rollForce < 0.0) {
|
||||
rollForce = 0.0;
|
||||
}
|
||||
if (rollable.pitch >= ROTATION_LIMIT && pitchForce > 0.0) {
|
||||
if (controller.pitch >= ROTATION_LIMIT && pitchForce > 0.0) {
|
||||
pitchForce = 0.0;
|
||||
}
|
||||
if (rollable.pitch <= -ROTATION_LIMIT && pitchForce < 0.0) {
|
||||
if (controller.pitch <= -ROTATION_LIMIT && pitchForce < 0.0) {
|
||||
pitchForce = 0.0;
|
||||
}
|
||||
|
||||
@@ -181,9 +181,9 @@ class HelicopterAirController : RideController {
|
||||
sensitivity: Double,
|
||||
deltaTime: Double
|
||||
): Vec3 {
|
||||
if (driver !is Rollable) return Vec3.ZERO
|
||||
if (driver !is OrientationControllable) return Vec3.ZERO
|
||||
|
||||
val rollable = driver as Rollable
|
||||
val controller = (driver as OrientationControllable).orientationController
|
||||
val invertYaw = if (Cobblemon.config.invertYaw) -1 else 1
|
||||
//yaw, pitch, roll
|
||||
return Vec3(xMouse * invertYaw, 0.0, 0.0)
|
||||
@@ -216,4 +216,4 @@ class HelicopterAirController : RideController {
|
||||
val KEY = cobblemonResource("air/helicopter")
|
||||
val ROTATION_LIMIT = 30.0f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -11,7 +11,7 @@ package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
@@ -30,7 +30,7 @@ import kotlin.math.*
|
||||
class JetAirController : RideController {
|
||||
override val key = KEY
|
||||
override val poseProvider = PoseProvider(PoseType.HOVER)
|
||||
.with(PoseOption(PoseType.FLY) { it.deltaMovement.length() > 0 })
|
||||
.with(PoseOption(PoseType.FLY) { it.entityData.get(PokemonEntity.MOVING) })
|
||||
|
||||
override val condition: (PokemonEntity) -> Boolean = { true }
|
||||
|
||||
@@ -105,17 +105,17 @@ class JetAirController : RideController {
|
||||
//Gather state information
|
||||
val state = getState(entity, ::JetAirState)
|
||||
|
||||
val rollable = driver as? Rollable
|
||||
val controller = (driver as? OrientationControllable)?.orientationController
|
||||
|
||||
//Calculate ride space velocity
|
||||
calculateRideSpaceVel(entity, driver, state)
|
||||
|
||||
//Translate ride space velocity to world space velocity.
|
||||
if( rollable != null ) {
|
||||
if(controller != null) {
|
||||
|
||||
upForce = -1.0 * sin(Math.toRadians( rollable.pitch.toDouble() )) * state.rideVel.z
|
||||
upForce = -1.0 * sin(Math.toRadians(controller.pitch.toDouble())) * state.rideVel.z
|
||||
|
||||
forwardForce = cos(Math.toRadians( rollable.pitch.toDouble() )) * state.rideVel.z
|
||||
forwardForce = cos(Math.toRadians(controller.pitch.toDouble())) * state.rideVel.z
|
||||
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ class JetAirController : RideController {
|
||||
sensitivity: Double,
|
||||
deltaTime: Double ): Vec3
|
||||
{
|
||||
if(driver !is Rollable) return Vec3.ZERO
|
||||
if(driver !is OrientationControllable) return Vec3.ZERO
|
||||
//TODO: figure out a cleaner solution to this issue of large jumps when skipping frames or lagging
|
||||
//Cap at a rate of 5fps so frame skips dont lead to huge jumps
|
||||
val cappedDeltaTime = min( deltaTime, 0.2)
|
||||
|
||||
+52
-53
@@ -23,7 +23,6 @@ import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.resolveInt
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -47,64 +46,67 @@ class RunUpToFlightCompositeController : RideController {
|
||||
var flightController: RideController = BirdAirController()
|
||||
private set
|
||||
|
||||
private fun shouldTransitionToGround(state: RunUpToFlightCompositeState, entity: PokemonEntity): Boolean {
|
||||
return state.activeController == flightController
|
||||
&& entity.onGround()
|
||||
&& state.timeTransitioned + 20 < entity.level().gameTime
|
||||
}
|
||||
|
||||
private fun shouldTransitionToAir(state: RunUpToFlightCompositeState, entity: PokemonEntity, driver: Player): Boolean {
|
||||
return state.activeController == landController
|
||||
&& driver.jumping
|
||||
&& state.timeTransitioned + 20 < entity.level().gameTime
|
||||
}
|
||||
|
||||
override fun tick(entity: PokemonEntity, driver: Player, input: Vec3) {
|
||||
val state = getState(entity, ::RunUpToFlightCompositeState)
|
||||
val flightState = flightController.getState(entity, ::BirdAirState)
|
||||
val groundState = landController.getState(entity, ::GenericLandState)
|
||||
if (shouldTransitionToGround(state, entity)) {
|
||||
//Pass the speed to the next state
|
||||
groundState.currSpeed = flightState.currSpeed
|
||||
groundState.rideVel = flightState.rideVel
|
||||
groundState.stamina = flightState.stamina
|
||||
|
||||
state.activeController = landController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
|
||||
state.timeTransitioned = entity.level().gameTime
|
||||
}
|
||||
else if (shouldTransitionToAir(state, entity, driver)) {
|
||||
//Pass the speed to the next state
|
||||
flightState.currSpeed = groundState.currSpeed
|
||||
flightState.rideVel = groundState.rideVel
|
||||
flightState.stamina = groundState.stamina
|
||||
|
||||
state.activeController = flightController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
state.timeTransitioned = entity.level().gameTime
|
||||
}
|
||||
}
|
||||
|
||||
override fun pose(entity: PokemonEntity): PoseType {
|
||||
return getActiveController(entity).poseProvider.select(entity)
|
||||
}
|
||||
|
||||
fun getActiveController(entity: PokemonEntity): RideController {
|
||||
val state = getState(entity, ::RunUpToFlightCompositeState)
|
||||
return state.activeController ?: let {
|
||||
val controller = if (entity.getCurrentPoseType() in PoseType.FLYING_POSES) {
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
flightController
|
||||
} else {
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
|
||||
landController
|
||||
}
|
||||
state.activeController = controller
|
||||
if (state.activeController != null) return state.activeController!!
|
||||
|
||||
if (entity.getCurrentPoseType() in PoseType.FLYING_POSES) {
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
state.activeController = flightController
|
||||
state.timeTransitioned = entity.level().gameTime
|
||||
controller
|
||||
return flightController
|
||||
}
|
||||
else {
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
|
||||
state.activeController = landController
|
||||
state.timeTransitioned = entity.level().gameTime
|
||||
return landController
|
||||
}
|
||||
}
|
||||
|
||||
override fun speed(
|
||||
entity: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
val state = getState(entity, ::RunUpToFlightCompositeState)
|
||||
if (state.activeController == flightController && entity.onGround() &&
|
||||
state.timeTransitioned + 20 < entity.level().gameTime) {
|
||||
|
||||
//Pass the speed to the next state
|
||||
val flightState = flightController.getState(entity, ::BirdAirState)
|
||||
val groundState = landController.getState(entity, ::GenericLandState)
|
||||
groundState.currSpeed = flightState.currSpeed
|
||||
groundState.rideVel = flightState.rideVel
|
||||
groundState.stamina = flightState.stamina
|
||||
|
||||
getState(entity, ::RunUpToFlightCompositeState).let {
|
||||
it.activeController = landController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
|
||||
it.timeTransitioned = entity.level().gameTime
|
||||
}
|
||||
}
|
||||
else if (state.activeController == landController && Minecraft.getInstance().options.keyJump.isDown &&
|
||||
state.timeTransitioned + 20 < entity.level().gameTime) {
|
||||
|
||||
//Pass the speed to the next state
|
||||
val flightState = flightController.getState( entity, ::BirdAirState )
|
||||
val groundState = landController.getState( entity, ::GenericLandState )
|
||||
flightState.currSpeed = groundState.currSpeed
|
||||
flightState.rideVel = groundState.rideVel
|
||||
flightState.stamina = groundState.stamina
|
||||
|
||||
getState(entity, ::RunUpToFlightCompositeState).let {
|
||||
it.activeController = flightController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
it.timeTransitioned = entity.level().gameTime
|
||||
}
|
||||
}
|
||||
|
||||
override fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
return getActiveController(entity).speed(entity, driver)
|
||||
}
|
||||
|
||||
@@ -142,9 +144,6 @@ class RunUpToFlightCompositeController : RideController {
|
||||
jumpStrength: Int
|
||||
): Vec3 {
|
||||
val controller = getActiveController(entity)
|
||||
val state = getState(entity, ::CompositeState)
|
||||
val isJumping = Minecraft.getInstance().options.keyJump.isDown
|
||||
|
||||
return controller.jumpForce(entity, driver, jumpStrength)
|
||||
}
|
||||
|
||||
@@ -212,4 +211,4 @@ class RunUpToFlightCompositeController : RideController {
|
||||
companion object {
|
||||
val KEY = cobblemonResource("composite/run_up_to_flight")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+42
-54
@@ -21,9 +21,7 @@ import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.resolveInt
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -34,7 +32,9 @@ import net.minecraft.world.phys.Vec3
|
||||
class RunUpToJetFlightCompositeController : RideController {
|
||||
override val key = KEY
|
||||
override val poseProvider = PoseProvider(PoseType.STAND)
|
||||
.with(PoseOption(PoseType.WALK) { it.entityData.get(PokemonEntity.MOVING) })
|
||||
.with(PoseOption(PoseType.WALK) {
|
||||
it.entityData.get(PokemonEntity.MOVING)
|
||||
})
|
||||
override val condition: (PokemonEntity) -> Boolean = { true }
|
||||
|
||||
var minimumSpeed: Expression = "0.5".asExpression()
|
||||
@@ -47,6 +47,44 @@ class RunUpToJetFlightCompositeController : RideController {
|
||||
var flightController: RideController = JetAirController()
|
||||
private set
|
||||
|
||||
fun shouldTransitionToGround(state: RunUpToFlightCompositeState, entity: PokemonEntity, driver: Player): Boolean {
|
||||
if (state.activeController != flightController) return false
|
||||
if (state.timeTransitioned + 20 >= entity.level().gameTime) return false
|
||||
return driver.isSprinting || entity.onGround()
|
||||
}
|
||||
|
||||
fun shouldTransitionToAir(state: RunUpToFlightCompositeState, entity: PokemonEntity, driver: Player, input: Vec3): Boolean {
|
||||
if (state.activeController != landController) return false
|
||||
if (state.timeTransitioned + 20 >= entity.level().gameTime) return false
|
||||
return driver.isSprinting && input.z > 0.5
|
||||
}
|
||||
|
||||
//TODO: This composite controller needs to have the jet lift off at a certain speed.
|
||||
//maybe just pressing shift or space? Unsure, will need to test to see what works best.
|
||||
override fun tick(entity: PokemonEntity, driver: Player, input: Vec3) {
|
||||
val state = getState(entity, ::RunUpToFlightCompositeState)
|
||||
val flightState = flightController.getState(entity, ::JetAirState)
|
||||
val groundState = landController.getState(entity, ::GenericLandState)
|
||||
if (shouldTransitionToGround(state, entity, driver)) {
|
||||
groundState.currSpeed = flightState.currSpeed
|
||||
groundState.stamina = flightState.stamina
|
||||
groundState.rideVel = flightState.rideVel
|
||||
|
||||
state.activeController = landController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
|
||||
state.timeTransitioned = entity.level().gameTime
|
||||
}
|
||||
else if (shouldTransitionToAir(state, entity, driver, input)) {
|
||||
flightState.currSpeed = groundState.currSpeed
|
||||
flightState.stamina = groundState.stamina
|
||||
flightState.rideVel = groundState.rideVel
|
||||
|
||||
state.activeController = flightController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
state.timeTransitioned = entity.level().gameTime
|
||||
}
|
||||
}
|
||||
|
||||
override fun pose(entity: PokemonEntity): PoseType {
|
||||
return getActiveController(entity).poseProvider.select(entity)
|
||||
}
|
||||
@@ -67,57 +105,7 @@ class RunUpToJetFlightCompositeController : RideController {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: This composite controller needs to have the jet lift off at a certain speed.
|
||||
//maybe just pressing shift or space? Unsure, will need to test to see what works best.
|
||||
override fun speed(
|
||||
entity: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
val state = getState(entity, ::RunUpToFlightCompositeState)
|
||||
if ((state.activeController == flightController && entity.onGround() &&
|
||||
state.timeTransitioned + 20 < entity.level().gameTime) ||
|
||||
(Minecraft.getInstance().options.keySprint.isDown && state.activeController == flightController &&
|
||||
state.timeTransitioned + 20 < entity.level().gameTime)) {
|
||||
|
||||
//Pass the data to the next state
|
||||
val flightState = flightController.getState(entity, ::JetAirState)
|
||||
val groundState = landController.getState(entity, ::GenericLandState)
|
||||
groundState.currSpeed = flightState.currSpeed
|
||||
groundState.stamina = flightState.stamina
|
||||
groundState.rideVel = flightState.rideVel
|
||||
|
||||
//Clear accumulated rotation input when transferring to ground input
|
||||
flightState.currMouseXForce = 0.0
|
||||
flightState.currMouseYForce = 0.0
|
||||
|
||||
getState(entity, ::RunUpToFlightCompositeState).let {
|
||||
it.activeController = landController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
it.timeTransitioned = entity.level().gameTime
|
||||
}
|
||||
}
|
||||
//These conditions should also be more graceful. As it stands though it feels better than jump and then
|
||||
//having to hit the ground
|
||||
else if(
|
||||
state.activeController == landController && entity.speed > 0.5 &&
|
||||
Minecraft.getInstance().options.keySprint.isDown() &&
|
||||
state.timeTransitioned + 20 < entity.level().gameTime
|
||||
)
|
||||
{
|
||||
//Pass the data to the next state
|
||||
val flightState = flightController.getState(entity, ::JetAirState)
|
||||
val groundState = landController.getState(entity, ::GenericLandState)
|
||||
flightState.currSpeed = groundState.currSpeed
|
||||
flightState.stamina = groundState.stamina
|
||||
flightState.rideVel = groundState.rideVel
|
||||
|
||||
getState(entity, ::RunUpToFlightCompositeState).let {
|
||||
it.activeController = flightController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
it.timeTransitioned = entity.level().gameTime
|
||||
}
|
||||
}
|
||||
|
||||
override fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
return getActiveController(entity).speed(entity, driver)
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -82,7 +82,7 @@ class VehicleLandController : RideController {
|
||||
@Transient
|
||||
override val key: ResourceLocation = KEY
|
||||
@Transient
|
||||
override val poseProvider: PoseProvider = PoseProvider(PoseType.STAND).with(PoseOption(PoseType.WALK) { it.deltaMovement.horizontalDistance() > 0.1 })
|
||||
override val poseProvider: PoseProvider = PoseProvider(PoseType.STAND).with(PoseOption(PoseType.WALK) { it.entityData.get(PokemonEntity.MOVING) })
|
||||
@Transient
|
||||
override val condition: (PokemonEntity) -> Boolean = { entity ->
|
||||
// Are there any blocks under the mon that aren't air or fluid
|
||||
@@ -191,4 +191,4 @@ class VehicleLandController : RideController {
|
||||
this.lookYawLimit = buffer.readString().asExpression()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,8 @@
|
||||
"PlayerAdvancementsMixin",
|
||||
"PlayerMixin",
|
||||
"PointedDripstoneBlockMixin",
|
||||
"ServerPlayerMixin",
|
||||
"ServerEntityMixin",
|
||||
"ShearsDispenserBehaviorMixin",
|
||||
"StructurePoolAccessor",
|
||||
"StructurePoolGeneratorMixin",
|
||||
@@ -56,8 +58,10 @@
|
||||
"accessor.AccessorEntity",
|
||||
"accessor.BiomeAccessor",
|
||||
"accessor.BoatEntityAccessor",
|
||||
"accessor.ChunkMapAccessor",
|
||||
"accessor.EntryListWidgetAccessor",
|
||||
"accessor.StatusEffectInstanceAccessor",
|
||||
"accessor.TrackedEntityAccessor",
|
||||
"entity.EntityMixin",
|
||||
"entity.TameableEntityMixin",
|
||||
"invoker.AdornRegisterInvoker",
|
||||
|
||||
Reference in New Issue
Block a user