mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-17 10:24:23 +01:00
Fixed player-like disguises
This commit is contained in:
parent
85623bd1c0
commit
0e007b3611
10 changed files with 133 additions and 24 deletions
|
@ -7,10 +7,12 @@ import com.minelittlepony.unicopia.entity.player.dummy.DummyPlayerEntity;
|
|||
import com.minelittlepony.unicopia.entity.player.dummy.DummyServerPlayerEntity;
|
||||
import com.minelittlepony.unicopia.network.handler.ClientNetworkHandler;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.minecraft.MinecraftSessionService;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class InteractionManager {
|
||||
public static final int SOUND_EARS_RINGING = 0;
|
||||
|
@ -24,6 +26,14 @@ public class InteractionManager {
|
|||
return INSTANCE;
|
||||
}
|
||||
|
||||
public MinecraftSessionService getSessionService(World world) {
|
||||
if (world instanceof ServerWorld) {
|
||||
return ((ServerWorld)world).getServer().getSessionService();
|
||||
}
|
||||
|
||||
throw new NullPointerException("Cannot get session service");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the client network handler, or throws if called on the server.
|
||||
*/
|
||||
|
@ -60,9 +70,19 @@ public class InteractionManager {
|
|||
*/
|
||||
@NotNull
|
||||
public PlayerEntity createPlayer(Entity observer, GameProfile profile) {
|
||||
if (observer.world instanceof ServerWorld) {
|
||||
return new DummyServerPlayerEntity((ServerWorld)observer.world, profile);
|
||||
return createPlayer(observer.world, profile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Side-independent method to create a new player.
|
||||
*
|
||||
* Returns an implementation of PlayerEntity appropriate to the side being called on.
|
||||
*/
|
||||
@NotNull
|
||||
public PlayerEntity createPlayer(World world, GameProfile profile) {
|
||||
if (world instanceof ServerWorld) {
|
||||
return new DummyServerPlayerEntity((ServerWorld)world, profile);
|
||||
}
|
||||
return new DummyPlayerEntity(observer.world, profile);
|
||||
return new DummyPlayerEntity(world, profile);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import com.minelittlepony.unicopia.entity.player.dummy.DummyClientPlayerEntity;
|
|||
import com.minelittlepony.unicopia.network.handler.ClientNetworkHandler;
|
||||
import com.minelittlepony.unicopia.network.handler.ClientNetworkHandlerImpl;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.minecraft.MinecraftSessionService;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.sound.AggressiveBeeSoundInstance;
|
||||
|
@ -26,12 +27,18 @@ import net.minecraft.entity.LivingEntity;
|
|||
import net.minecraft.entity.passive.BeeEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.vehicle.AbstractMinecartEntity;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ClientInteractionManager extends InteractionManager {
|
||||
|
||||
private final ClientNetworkHandler handler = new ClientNetworkHandlerImpl();
|
||||
private final MinecraftClient client = MinecraftClient.getInstance();
|
||||
|
||||
@Override
|
||||
public MinecraftSessionService getSessionService(World world) {
|
||||
return MinecraftClient.getInstance().getSessionService();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ClientNetworkHandler getClientNetworkHandler() {
|
||||
|
@ -62,11 +69,11 @@ public class ClientInteractionManager extends InteractionManager {
|
|||
|
||||
@Override
|
||||
@NotNull
|
||||
public PlayerEntity createPlayer(Entity observer, GameProfile profile) {
|
||||
if (observer.world instanceof ClientWorld) {
|
||||
return new DummyClientPlayerEntity((ClientWorld)observer.world, profile);
|
||||
public PlayerEntity createPlayer(World world, GameProfile profile) {
|
||||
if (world instanceof ClientWorld) {
|
||||
return new DummyClientPlayerEntity((ClientWorld)world, profile);
|
||||
}
|
||||
return super.createPlayer(observer, profile);
|
||||
return super.createPlayer(world, profile);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package com.minelittlepony.unicopia.entity;
|
||||
|
||||
public interface CapeHolder {
|
||||
void callUpdateCapeAngles();
|
||||
}
|
|
@ -4,4 +4,13 @@ public interface Leaner {
|
|||
float getLeaningPitch();
|
||||
|
||||
void setLeaningPitch(float pitch);
|
||||
|
||||
float getLastLeaningPitch();
|
||||
|
||||
void setLastLeaningPitch(float pitch);
|
||||
|
||||
default void copyFrom(Leaner other) {
|
||||
setLeaningPitch(other.getLeaningPitch());
|
||||
setLastLeaningPitch(other.getLastLeaningPitch());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.entity.behaviour;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
@ -144,16 +145,20 @@ public class Disguise implements NbtSerialisable {
|
|||
public Entity getOrCreate(Caster<?> source) {
|
||||
if (entity == null && entityNbt != null) {
|
||||
NbtCompound nbt = entityNbt;
|
||||
entity = null;
|
||||
entityNbt = null;
|
||||
attachments.clear();
|
||||
|
||||
if ("player".equals(entityId)) {
|
||||
createPlayer(nbt, new GameProfile(
|
||||
nbt.getUuid("playerId"),
|
||||
nbt.getString("playerName")
|
||||
), source);
|
||||
nbt.containsUuid("playerId") ? nbt.getUuid("playerId") : UUID.randomUUID(),
|
||||
nbt.getString("playerName")
|
||||
), source);
|
||||
|
||||
SkullBlockEntity.loadProperties(new GameProfile(null, nbt.getString("playerName")), profile ->{ });
|
||||
SkullBlockEntity.loadProperties(new GameProfile(
|
||||
nbt.containsUuid("playerId") ? nbt.getUuid("playerId") : null,
|
||||
nbt.getString("playerName")
|
||||
), p -> createPlayer(nbt, p, source));
|
||||
} else {
|
||||
if (source.isClient()) {
|
||||
entity = EntityType.fromNbt(nbt).map(type -> type.create(source.getWorld())).orElse(null);
|
||||
|
@ -170,9 +175,9 @@ public class Disguise implements NbtSerialisable {
|
|||
return EntityBehaviour.forEntity(e).onCreate(e, this, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onEntityLoaded(source);
|
||||
onEntityLoaded(source);
|
||||
}
|
||||
}
|
||||
|
||||
return entity;
|
||||
|
@ -282,7 +287,14 @@ public class Disguise implements NbtSerialisable {
|
|||
public void fromNBT(NbtCompound compound) {
|
||||
String newId = compound.getString("entityId");
|
||||
|
||||
if (!newId.contentEquals(entityId)) {
|
||||
String newPlayerName = null;
|
||||
if (compound.contains("entity") && compound.getCompound("entity").contains("playerName")) {
|
||||
newPlayerName = compound.getCompound("entity").getString("playerName");
|
||||
}
|
||||
|
||||
String oldPlayerName = entity != null && entity instanceof PlayerEntity ? ((PlayerEntity)entity).getGameProfile().getName() : null;
|
||||
|
||||
if (!Objects.equals(newId, entityId) || !Objects.equals(newPlayerName, oldPlayerName)) {
|
||||
entityNbt = null;
|
||||
remove();
|
||||
}
|
||||
|
@ -320,7 +332,9 @@ public class Disguise implements NbtSerialisable {
|
|||
GameProfile profile = ((PlayerEntity)entity).getGameProfile();
|
||||
|
||||
entityNbt.putString("id", "player");
|
||||
entityNbt.putUuid("playerId", profile.getId());
|
||||
if (profile.getId() != null) {
|
||||
entityNbt.putUuid("playerId", profile.getId());
|
||||
}
|
||||
entityNbt.putString("playerName", profile.getName());
|
||||
|
||||
NbtCompound tag = new NbtCompound();
|
||||
|
|
|
@ -40,6 +40,11 @@ public class EntityBehaviour<T extends Entity> {
|
|||
private static final EntityBehaviour<Entity> DEFAULT = new EntityBehaviour<>();
|
||||
private static final Registry<EntityBehaviour<?>> REGISTRY = Registries.createSimple(new Identifier("unicopia", "entity_behaviour"));
|
||||
|
||||
/**
|
||||
* Equivalent of the entity#tick method. Called every tick to update th logic for a disguise.
|
||||
* <br>
|
||||
* We use this to add entity-specific behaviours.
|
||||
*/
|
||||
public void update(Caster<?> source, T entity, DisguiseSpell spell) {
|
||||
if (source instanceof Pony) {
|
||||
update((Pony)source, entity, spell);
|
||||
|
@ -151,14 +156,6 @@ public class EntityBehaviour<T extends Entity> {
|
|||
to.lastRenderZ = positionOffset.z + from.lastRenderZ;
|
||||
}
|
||||
|
||||
if (to instanceof PlayerEntity) {
|
||||
PlayerEntity l = (PlayerEntity)to;
|
||||
|
||||
l.capeX = positionOffset.x + l.getX();
|
||||
l.capeY = positionOffset.y + l.getY();
|
||||
l.capeZ = positionOffset.z + l.getZ();
|
||||
}
|
||||
|
||||
to.setVelocity(from.getVelocity());
|
||||
|
||||
to.setPitch(from.getPitch());
|
||||
|
@ -267,6 +264,7 @@ public class EntityBehaviour<T extends Entity> {
|
|||
}
|
||||
|
||||
static {
|
||||
register(PlayerBehaviour::new, EntityType.PLAYER);
|
||||
register(FallingBlockBehaviour::new, EntityType.FALLING_BLOCK);
|
||||
register(MobBehaviour::new, EntityType.RAVAGER, EntityType.IRON_GOLEM);
|
||||
register(HoppingBehaviour::new, EntityType.RABBIT, EntityType.SLIME, EntityType.MAGMA_CUBE);
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package com.minelittlepony.unicopia.entity.behaviour;
|
||||
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell;
|
||||
import com.minelittlepony.unicopia.entity.CapeHolder;
|
||||
import com.minelittlepony.unicopia.entity.Leaner;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
|
||||
public class PlayerBehaviour extends EntityBehaviour<PlayerEntity> {
|
||||
@Override
|
||||
public void update(Caster<?> source, PlayerEntity entity, DisguiseSpell spell) {
|
||||
if (source instanceof Pony) {
|
||||
PlayerEntity pFrom = ((Pony)source).getMaster();
|
||||
|
||||
entity.capeX = pFrom.capeX;
|
||||
entity.capeY = pFrom.capeY;
|
||||
entity.capeZ = pFrom.capeZ;
|
||||
entity.prevCapeX = pFrom.prevCapeX;
|
||||
entity.prevCapeY = pFrom.prevCapeY;
|
||||
entity.prevCapeZ = pFrom.prevCapeZ;
|
||||
} else {
|
||||
((CapeHolder)entity).callUpdateCapeAngles();
|
||||
}
|
||||
|
||||
if (source.getEntity().getPose() != entity.getPose()) {
|
||||
entity.setPose(source.getEntity().getPose());
|
||||
}
|
||||
if (source.getEntity().isSwimming() != entity.isSwimming()) {
|
||||
entity.setSwimming(source.getEntity().isSwimming());
|
||||
}
|
||||
if (source.getEntity() instanceof Leaner) {
|
||||
((Leaner)entity).copyFrom(((Leaner)source.getEntity()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import com.minelittlepony.unicopia.InteractionManager;
|
|||
import com.minelittlepony.unicopia.Owned;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
@ -22,6 +23,11 @@ public class DummyServerPlayerEntity extends ServerPlayerEntity implements Owned
|
|||
/*noop*/
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBlockCollision(BlockState state) {
|
||||
/*noop*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerEntity getMaster() {
|
||||
return owner;
|
||||
|
|
|
@ -75,6 +75,14 @@ abstract class MixinLivingEntity extends Entity implements PonyContainer<Equine<
|
|||
@Accessor("leaningPitch")
|
||||
public abstract void setLeaningPitch(float pitch);
|
||||
|
||||
@Override
|
||||
@Accessor("lastLeaningPitch")
|
||||
public abstract float getLastLeaningPitch();
|
||||
|
||||
@Override
|
||||
@Accessor("lastLeaningPitch")
|
||||
public abstract void setLastLeaningPitch(float pitch);
|
||||
|
||||
@Inject(method = "createLivingAttributes()Lnet/minecraft/entity/attribute/DefaultAttributeContainer$Builder;", at = @At("RETURN"))
|
||||
private static void onCreateAttributes(CallbackInfoReturnable<DefaultAttributeContainer.Builder> info) {
|
||||
Creature.registerAttributes(info.getReturnValue());
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package com.minelittlepony.unicopia.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.minelittlepony.unicopia.entity.PonyContainer;
|
||||
import com.minelittlepony.unicopia.entity.CapeHolder;
|
||||
import com.minelittlepony.unicopia.entity.Equine;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
|
@ -25,8 +27,11 @@ import net.minecraft.util.math.BlockPos;
|
|||
import net.minecraft.world.World;
|
||||
|
||||
@Mixin(PlayerEntity.class)
|
||||
abstract class MixinPlayerEntity extends LivingEntity implements PonyContainer<Pony> {
|
||||
abstract class MixinPlayerEntity extends LivingEntity implements PonyContainer<Pony>, CapeHolder {
|
||||
private MixinPlayerEntity() { super(null, null); }
|
||||
@Override
|
||||
@Invoker("updateCapeAngles")
|
||||
public abstract void callUpdateCapeAngles();
|
||||
|
||||
@Override
|
||||
public Equine<?> create() {
|
||||
|
|
Loading…
Reference in a new issue