Skip to content

Commit

Permalink
Fixed long-distance travel (Part 2)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sollace committed Jan 26, 2019
1 parent 42b856a commit 1ed677e
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ public void setAffinity(SpellAffinity affinity) {
@Override
public void setEffect(IMagicEffect effect) {
effectDelegate.set(effect);

effect.onPlaced(this);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ default EntitySpell castContainedSpell(World world, BlockPos pos, ItemStack stac
EntitySpell spell = new EntitySpell(world);

spell.setAffinity(getAffinity(stack));
spell.setEffect(effect);
spell.setLocationAndAngles(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 0, 0);
spell.setEffect(effect);

world.spawnEntity(spell);

return spell;
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/minelittlepony/unicopia/spell/ICaster.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.spell;

import java.util.Random;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.stream.Stream;

Expand Down Expand Up @@ -33,6 +34,10 @@ default Entity getEntity() {
return getOwner();
}

default UUID getUniqueId() {
return getEntity().getUniqueID();
}

default World getWorld() {
return getEntity().getEntityWorld();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ public interface IMagicEffect extends InbtSerialisable, ILevelled {
*/
boolean getDead();

/**
* Called when first attached to a gem.
*/
default void onPlaced(ICaster<?> caster) {

}

/**
* Called every tick when attached to a player.
*
Expand Down
196 changes: 136 additions & 60 deletions src/main/java/com/minelittlepony/unicopia/spell/SpellPortal.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.Locale;
import java.util.Optional;
import java.util.UUID;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
Expand All @@ -12,6 +13,7 @@
import com.minelittlepony.unicopia.entity.IMagicals;
import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable;
import com.minelittlepony.util.shape.IShape;
import com.minelittlepony.util.shape.Sphere;

Expand All @@ -25,6 +27,7 @@
import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundCategory;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;

public class SpellPortal extends AbstractSpell implements IUseAction {

Expand All @@ -35,10 +38,6 @@ public class SpellPortal extends AbstractSpell implements IUseAction {
private static final AxisAlignedBB TELEPORT_BOUNDS_VERT = new AxisAlignedBB(-1, -0.5, -1, 1, 0.5, 1);
private static final AxisAlignedBB TELEPORT_BOUNDS = new AxisAlignedBB(-0.5, -0.5, -0.5, 0.5, 3, 0.5);

private static final AxisAlignedBB DESTINATION_BOUNDS = new AxisAlignedBB(0, 0, 0, 1.5F, 1.5F, 1.5F);

private int cooldown = 0;

@Nullable
private SpellPortal sibling = null;

Expand All @@ -50,6 +49,14 @@ public class SpellPortal extends AbstractSpell implements IUseAction {

private EnumFacing.Axis axis = EnumFacing.Axis.Y;

@Nullable
private UUID casterId;

private World world;

@Nullable
private UUID destinationId;

@Override
public String getName() {
return "portal";
Expand All @@ -64,8 +71,22 @@ public int getTint() {
public void setDead() {
super.setDead();

if (sibling != null && !sibling.getDead()) {
sibling.setDead();
sibling = null;
destinationId = null;
destinationPos = null;

getDestinationPortal().ifPresent(IMagicEffect::setDead);
}

@Override
public void onPlaced(ICaster<?> caster) {
world = caster.getWorld();
casterId = caster.getUniqueId();
position = caster.getOrigin();

if (sibling != null) {
sibling.destinationId = casterId;
sibling.destinationPos = position;
}
}

Expand All @@ -78,7 +99,7 @@ public SpellCastResult onUse(ItemStack stack, SpellAffinity affinity, EntityPlay

IMagicEffect other = prop.getEffect();
if (other instanceof SpellPortal && other != this && !other.getDead()) {
((SpellPortal)other).notifyMatched(this);
((SpellPortal)other).getActualInstance().setDestinationPortal(this);

if (!world.isRemote) {
prop.setEffect(null);
Expand All @@ -97,11 +118,14 @@ public SpellCastResult onUse(ItemStack stack, SpellAffinity affinity, EntityPlay
return SpellCastResult.NONE;
}

public void notifyMatched(SpellPortal other) {
if (sibling == null) {
public void setDestinationPortal(SpellPortal other) {
if (!getDestinationPortal().isPresent()) {
sibling = other;
other.sibling = this;

destinationId = other.casterId;
other.destinationId = casterId;

sibling.destinationPos = position;
destinationPos = sibling.position;
}
Expand All @@ -115,11 +139,10 @@ public boolean updateOnPerson(ICaster<?> caster) {
@Override
public boolean update(ICaster<?> source, int level) {
if (!source.getWorld().isRemote) {
getDestinationPortal(source.getWorld()).ifPresent(dest -> {
if (!dest.getDead()) {
teleportNear(source, level);
}
});
getDestinationPortal().ifPresent(dest ->
source.getWorld().getEntitiesWithinAABB(Entity.class, getTeleportBounds().offset(source.getOrigin())).stream()
.filter(this::canTeleport)
.forEach(i -> teleportEntity(source, dest, i)));
}

return true;
Expand Down Expand Up @@ -154,58 +177,107 @@ public AxisAlignedBB getTeleportBounds() {
return TELEPORT_BOUNDS;
}

private boolean teleportNear(ICaster<?> source, int level) {
return source.getWorld().getEntitiesWithinAABB(Entity.class, getTeleportBounds().offset(source.getOrigin())).stream().filter(i -> {
if (!(i instanceof IMagicals) && i.timeUntilPortal == 0) {
EnumFacing.Axis xi = i.getHorizontalFacing().getAxis();
protected boolean canTeleport(Entity i) {
return !(i instanceof IMagicals) && i.timeUntilPortal == 0;
}

protected void teleportEntity(ICaster<?> source, SpellPortal dest, Entity i) {
EnumFacing.Axis xi = i.getHorizontalFacing().getAxis();

if (axis != EnumFacing.Axis.Y && xi != axis) {
return false;
}
if (axis != EnumFacing.Axis.Y && xi != axis) {
return;
}

EnumFacing offset = i.getHorizontalFacing();
EnumFacing offset = i.getHorizontalFacing();

double destX = destinationPos.getX() + (i.posX - source.getOrigin().getX());
double destY = destinationPos.getY() + (i.posY - source.getOrigin().getY());
double destZ = destinationPos.getZ() + (i.posZ - source.getOrigin().getZ());
double destX = dest.position.getX() + (i.posX - source.getOrigin().getX());
double destY = dest.position.getY() + (i.posY - source.getOrigin().getY());
double destZ = dest.position.getZ() + (i.posZ - source.getOrigin().getZ());

if (axis != EnumFacing.Axis.Y) {
destX += offset.getXOffset();
destY++;
destZ += offset.getZOffset();
if (axis != EnumFacing.Axis.Y) {
destX += offset.getXOffset();
destY++;
destZ += offset.getZOffset();
}

i.timeUntilPortal = i.getPortalCooldown();

i.getEntityWorld().playSound(null, i.getPosition(), SoundEvents.BLOCK_END_PORTAL_FRAME_FILL, SoundCategory.PLAYERS, 1, 1);

if (dest.axis != axis) {
if (xi != dest.axis) {
i.setPositionAndRotation(i.posX, i.posY, i.posZ, i.rotationYaw + 90, i.rotationPitch);
}
}

i.setPositionAndUpdate(destX, destY, destZ);
i.getEntityWorld().playSound(null, i.getPosition(), SoundEvents.BLOCK_END_PORTAL_FRAME_FILL, SoundCategory.PLAYERS, 1, 1);
}

/**
* Converts a possibly dead portal effect into a live one by forcing the owner entity to load.
*/
protected SpellPortal getActualInstance() {
if (world instanceof WorldServer) {
Entity i = ((WorldServer)world).getEntityFromUuid(casterId);

if (i == null) {
world.getChunk(position);
i = ((WorldServer)world).getEntityFromUuid(casterId);
}

if (i instanceof EntitySpell) {
IMagicEffect effect = ((EntitySpell) i).getEffect();

if (effect instanceof SpellPortal) {
return (SpellPortal)effect;
}
}
}

return this;
}

/**
* Gets or loads the destination portal.
*/
public Optional<SpellPortal> getDestinationPortal() {

i.timeUntilPortal = i.getPortalCooldown();
if (getDead()) {
return Optional.empty();
}

i.getEntityWorld().playSound(null, i.getPosition(), SoundEvents.BLOCK_END_PORTAL_FRAME_FILL, SoundCategory.PLAYERS, 1, 1);
Entity i = null;

if (destinationId != null) {
i = ((WorldServer)world).getEntityFromUuid(destinationId);

if (i == null && destinationPos != null) {
world.getChunk(destinationPos);
i = ((WorldServer)world).getEntityFromUuid(destinationId);

if (sibling.axis != axis) {
if (i == null) {
setDead();

if (xi != sibling.axis) {
i.setPositionAndRotation(i.posX, i.posY, i.posZ, i.rotationYaw + 90, i.rotationPitch);
}
return Optional.empty();
}
}
}

i.setPositionAndUpdate(destX, destY, destZ);
i.getEntityWorld().playSound(null, i.getPosition(), SoundEvents.BLOCK_END_PORTAL_FRAME_FILL, SoundCategory.PLAYERS, 1, 1);
if (i instanceof EntitySpell) {
IMagicEffect effect = ((EntitySpell) i).getEffect();

return true;
if (effect instanceof SpellPortal) {
sibling = (SpellPortal)effect;
}
}

return false;
}).count() > 0;
}
if (sibling != null && sibling.getDead()) {
setDead();
}

public Optional<SpellPortal> getDestinationPortal(World w) {
if (sibling == null && destinationPos != null) {
w.getBlockLightOpacity(destinationPos);
w.getEntitiesWithinAABB(EntitySpell.class, DESTINATION_BOUNDS.offset(destinationPos)).stream()
.filter(i -> i.getEffect() instanceof SpellPortal)
.map(i -> (SpellPortal)i.getEffect())
.findFirst()
.ifPresent(s -> sibling = s);
if (sibling != null && destinationPos == null) {
destinationPos = sibling.position;
}

return Optional.ofNullable(sibling);
Expand All @@ -214,13 +286,15 @@ public Optional<SpellPortal> getDestinationPortal(World w) {
@Override
public void writeToNBT(NBTTagCompound compound) {
if (destinationPos != null) {
NBTTagCompound dest = new NBTTagCompound();
compound.setTag("destination", InbtSerialisable.writeBlockPos(destinationPos));
}

dest.setInteger("X", destinationPos.getX());
dest.setInteger("Y", destinationPos.getY());
dest.setInteger("Z", destinationPos.getZ());
if (casterId != null) {
compound.setUniqueId("casterId", casterId);
}

compound.setTag("destination", dest);
if (destinationId != null) {
compound.setUniqueId("destinationId", destinationId);
}

compound.setString("axis", axis.getName2());
Expand All @@ -229,13 +303,15 @@ public void writeToNBT(NBTTagCompound compound) {
@Override
public void readFromNBT(NBTTagCompound compound) {
if (compound.hasKey("destination")) {
NBTTagCompound dest = compound.getCompoundTag("destination");
destinationPos = InbtSerialisable.readBlockPos(compound.getCompoundTag("destination"));
}

if (compound.hasUniqueId("casterId")) {
casterId = compound.getUniqueId("casterId");
}

destinationPos = new BlockPos(
dest.getInteger("X"),
dest.getInteger("Y"),
dest.getInteger("Z")
);
if (compound.hasUniqueId("destinationId")) {
destinationId = compound.getUniqueId("destinationId");
}

if (compound.hasKey("axis")) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.util.serialisation;

import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.math.BlockPos;

public interface InbtSerialisable {
/**
Expand All @@ -26,4 +27,22 @@ default NBTTagCompound toNBT() {
writeToNBT(compound);
return compound;
}

static NBTTagCompound writeBlockPos(BlockPos pos) {
NBTTagCompound dest = new NBTTagCompound();

dest.setInteger("X", pos.getX());
dest.setInteger("Y", pos.getY());
dest.setInteger("Z", pos.getZ());

return dest;
}

static BlockPos readBlockPos(NBTTagCompound compound) {
return new BlockPos(
compound.getInteger("X"),
compound.getInteger("Y"),
compound.getInteger("Z")
);
}
}

0 comments on commit 1ed677e

Please sign in to comment.