use of org.valkyrienskies.mod.common.ships.ship_world.PhysicsObject in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.
the class MixinClientWorld method preGetCombinedLight.
@SideOnly(Side.CLIENT)
@Inject(method = "getCombinedLight(Lnet/minecraft/util/math/BlockPos;I)I", at = @At("HEAD"), cancellable = true)
private void preGetCombinedLight(BlockPos pos, int lightValue, CallbackInfoReturnable<Integer> callbackInfoReturnable) {
final World world = thisAsWorld;
try {
int i = world.getLightFromNeighborsFor(EnumSkyBlock.SKY, pos);
int j = world.getLightFromNeighborsFor(EnumSkyBlock.BLOCK, pos);
AxisAlignedBB lightBB = new AxisAlignedBB(pos.getX() - 2, pos.getY() - 2, pos.getZ() - 2, pos.getX() + 2, pos.getY() + 2, pos.getZ() + 2);
final List<PhysicsObject> physicsObjectList = ValkyrienUtils.getPhysObjWorld(world).getAllLoadedThreadSafe().stream().filter((physicsObject -> lightBB.intersects(physicsObject.getShipBB()))).collect(Collectors.toList());
final BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
for (final PhysicsObject physicsObject : physicsObjectList) {
final Vector3dc posInLocal = physicsObject.getShipTransformationManager().getRenderTransform().transformPositionNew(JOML.convertTo3d(pos).add(.5, .5, .5), TransformType.GLOBAL_TO_SUBSPACE);
final int minX = (int) Math.floor(posInLocal.x());
final int minY = (int) Math.floor(posInLocal.y());
final int minZ = (int) Math.floor(posInLocal.z());
int shipSkyLight = 0;
for (int x = minX; x <= minX + 1; x++) {
for (int y = minY; y <= minY + 1; y++) {
for (int z = minZ; z <= minZ + 1; z++) {
mutableBlockPos.setPos(x, y, z);
final IBlockState blockState = world.getBlockState(mutableBlockPos);
// Ignore the light of full blocks
if (blockState.isFullBlock()) {
continue;
}
final int localBlockLight = world.getLightFromNeighborsFor(EnumSkyBlock.BLOCK, mutableBlockPos);
final int localSkyLight = world.getLightFromNeighborsFor(EnumSkyBlock.SKY, mutableBlockPos);
j = Math.max(j, localBlockLight);
shipSkyLight = Math.max(shipSkyLight, localSkyLight);
}
}
}
if (i > shipSkyLight) {
i = shipSkyLight;
}
}
if (j < lightValue) {
j = lightValue;
}
callbackInfoReturnable.setReturnValue(i << 20 | j << 4);
} catch (Exception e) {
System.err.println("Something just went wrong here, getting default light value instead!");
e.printStackTrace();
}
}
use of org.valkyrienskies.mod.common.ships.ship_world.PhysicsObject in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.
the class EntityCollisionInjector method alterEntityMovement.
// Returns false if game should use default collision
@Nullable
public static IntermediateMovementVariableStorage alterEntityMovement(Entity entity, MoverType type, double dx, double dy, double dz) {
final double origDx = dx;
final double origDy = dy;
final double origDz = dz;
final double origPosX = entity.posX;
final double origPosY = entity.posY;
final double origPosZ = entity.posZ;
boolean isLiving = entity instanceof EntityLivingBase;
Vec3d velocity = new Vec3d(dx, dy, dz);
Polygon playerBeforeMove = new Polygon(entity.getEntityBoundingBox());
List<Polygon> colPolys = getCollidingPolygonsAndDoBlockCols(entity, velocity);
PhysicsObject worldBelow = null;
IDraggable draggable = EntityDraggable.getDraggableFromEntity(entity);
final EntityShipMovementData lastTickEntityShipMovementData = draggable.getEntityShipMovementData();
Vector3d total = new Vector3d();
// Used to reset the player position after collision processing, effectively
// using the player to integrate their velocity
double posOffestX = 0;
double posOffestY = 0;
double posOffestZ = 0;
// True IFF the player is on a ladder
boolean isPlayerOnLadder = false;
// region Ladder movement
if (entity instanceof EntityLivingBase) {
final EntityLivingBase base = (EntityLivingBase) entity;
final List<PhysicsObject> collidingShips = ((IHasShipManager) entity.getEntityWorld()).getManager().getPhysObjectsInAABB(base.getEntityBoundingBox());
final Iterable<Triple<PhysicsObject, BlockPos, IBlockState>> ladderCollisions = getLadderCollisions(base, collidingShips);
// For now, just ignore the y component. I may or may not use it later.
final float forward = ((EntityLivingBase) entity).moveForward;
final float strafe = ((EntityLivingBase) entity).moveStrafing;
final double f1 = Math.sin(Math.toRadians(entity.rotationYaw));
final double f2 = Math.cos(Math.toRadians(entity.rotationYaw));
final double intendedXVel = strafe * f2 - forward * f1;
final double intendedYVel = 0;
final double intendedZVel = forward * f2 + strafe * f1;
final Vector3dc originalVelocityDirection = new Vector3d(intendedXVel, intendedYVel, intendedZVel).normalize();
final World world = entity.world;
final Polygon playerPolygon = new Polygon(base.getEntityBoundingBox());
for (final Triple<PhysicsObject, BlockPos, IBlockState> ladderCollision : ladderCollisions) {
final IBlockState ladderState = ladderCollision.getRight();
EnumFacing ladderFacing = null;
// For now, we only support a few blocks
if (ladderState.getPropertyKeys().contains(BlockHorizontal.FACING)) {
ladderFacing = ladderState.getValue(BlockHorizontal.FACING);
}
// We need the EnumFacing of the ladder for the code to work. If we couldn't find it then just give up :/
if (ladderFacing != null) {
final Vector3d ladderNormal = JOML.convertDouble(ladderFacing.getDirectionVec());
final ShipTransform shipTransform = ladderCollision.getLeft().getShipTransform();
// Grow the ladder BB by a small margin (makes the ladder experience better imo)
final AxisAlignedBB ladderBB = ladderCollision.getRight().getBoundingBox(world, ladderCollision.getMiddle()).offset(ladderCollision.getMiddle()).grow(.4);
final Polygon ladderPoly = new Polygon(ladderBB, shipTransform.getSubspaceToGlobal());
// Determine if the player is actually colliding with the ladder
final PhysPolygonCollider collider = new PhysPolygonCollider(playerPolygon, ladderPoly, ladderCollision.getLeft().getShipTransformationManager().normals);
collider.processData();
shipTransform.transformDirection(ladderNormal, TransformType.SUBSPACE_TO_GLOBAL);
// Don't use "floor ladders"
final boolean isLadderFacingDown = ladderNormal.y > .8;
if (isLadderFacingDown) {
continue;
}
// If the ladder is facing up, then let the player use them like monkey bars
final boolean isLadderFacingUp = ladderNormal.y < -.8;
// Whether or not the player is actually colliding with a ladder, since it is close to one we give the player ladder movement.
dx = MathHelper.clamp(dx, -.15, .15);
dz = MathHelper.clamp(dz, -.15, .15);
base.fallDistance = 0;
if (!isLadderFacingUp) {
// Use ladders like normal
if (dy < -.15) {
dy = -.15;
}
final boolean isPlayerGoingTowardsLadder = originalVelocityDirection.dot(ladderNormal) < -.1;
final boolean isPlayerSneakingOnLadder = base.isSneaking() && base instanceof EntityPlayer;
if (isPlayerSneakingOnLadder && dy < 0) {
dy = 0;
}
if (!collider.seperated && isPlayerGoingTowardsLadder) {
dy = .2;
}
} else {
// Use ladders like monkey bars
dy = .2;
}
worldBelow = ladderCollision.getLeft();
isPlayerOnLadder = true;
break;
}
}
}
// endregion
final Vector3dc velVec = new Vector3d(dx, dy, dz);
for (Polygon poly : colPolys) {
if (poly instanceof ShipPolygon) {
ShipPolygon shipPoly = (ShipPolygon) poly;
try {
EntityPolygonCollider fast = new EntityPolygonCollider(playerBeforeMove, shipPoly, shipPoly.normals, velVec.add(total, new Vector3d()));
if (!fast.arePolygonsSeparated()) {
// fastCollisions.add(fast);
worldBelow = shipPoly.shipFrom;
Vector3d response = fast.getCollisions()[fast.getMinDistanceIndex()].getResponse();
// TODO: Add more potential yResponses
double stepSquared = entity.stepHeight * entity.stepHeight;
// Do not do stair stepping if the player is on a ladder.
boolean isStep = isLiving && entity.onGround && !isPlayerOnLadder;
if (response.y >= 0 && VSMath.canStandOnNormal(fast.getCollisionAxes()[fast.getMinDistanceIndex()])) {
Vector3d slowButStopped = new Vector3d(0, -fast.getCollisions()[fast.getMinDistanceIndex()].getCollisionPenetrationDistance() / fast.getCollisionAxes()[fast.getMinDistanceIndex()].y(), 0);
response = slowButStopped;
}
if (isStep) {
EntityLivingBase living = (EntityLivingBase) entity;
if (Math.abs(living.moveForward) > .01 || Math.abs(living.moveStrafing) > .01) {
for (int i = 3; i < 6; i++) {
Vector3d tempResponse = fast.getCollisions()[i].getResponse();
if (tempResponse.y > 0 && VSMath.canStandOnNormal(fast.getCollisions()[i].getCollisionNormal()) && tempResponse.lengthSquared() < stepSquared) {
if (tempResponse.lengthSquared() < .1) {
// Too small to be a real step, let it through
response = tempResponse;
} else {
// System.out.println("Try Stepping!");
AxisAlignedBB axisalignedbb = entity.getEntityBoundingBox().offset(tempResponse.x, tempResponse.y, tempResponse.z);
// Don't allow the player to step if the step will put them in another polygon.
boolean collidesWithAnything = false;
{
final AxisAlignedBB newEntityBBShrunk = axisalignedbb.shrink(.15);
final Polygon newEntityBBShrunkPolygon = new Polygon(newEntityBBShrunk);
for (Polygon potentialStepCollision : colPolys) {
if (potentialStepCollision == poly) {
// Don't run this on ourself
continue;
}
if (potentialStepCollision.getEnclosedAABB().intersects(newEntityBBShrunk)) {
// Finer check
ShipPolygon potentialStepCollisionShipPoly = (ShipPolygon) potentialStepCollision;
final EntityPolygonCollider checkIfStepCollidesWithBlock = new EntityPolygonCollider(newEntityBBShrunkPolygon, potentialStepCollisionShipPoly, potentialStepCollisionShipPoly.normals, new Vector3d());
checkIfStepCollidesWithBlock.processData();
if (!checkIfStepCollidesWithBlock.arePolygonsSeparated()) {
collidesWithAnything = true;
break;
}
}
}
}
if (!collidesWithAnything) {
entity.setEntityBoundingBox(axisalignedbb);
// I think this correct, but it may create more problems than it solves
response.zero();
entity.resetPositionToBB();
}
}
}
}
}
}
// total.add(response);
if (Math.abs(response.x) > .01D) {
total.x += response.x;
}
if (Math.abs(response.y) > .01D) {
total.y += response.y;
}
if (Math.abs(response.z) > .01D) {
total.z += response.z;
}
entity.posX += response.x;
entity.posY += response.y;
entity.posZ += response.z;
posOffestX += response.x;
posOffestY += response.y;
posOffestZ += response.z;
AxisAlignedBB axisalignedbb = entity.getEntityBoundingBox().offset(response.x, response.y, response.z);
entity.setEntityBoundingBox(axisalignedbb);
entity.resetPositionToBB();
}
} catch (Exception e) {
// Do nothing
}
}
}
AxisAlignedBB axisalignedbb = entity.getEntityBoundingBox().offset(-posOffestX, -posOffestY, -posOffestZ);
entity.setEntityBoundingBox(axisalignedbb);
entity.resetPositionToBB();
// We are on the ship that we are riding
if (entity.ridingEntity instanceof EntityMountable) {
final EntityMountable entityMountable = (EntityMountable) entity.ridingEntity;
if (entityMountable.getReferencePosOptional().isPresent()) {
final Optional<PhysicsObject> physicsObjectOptional = ValkyrienUtils.getPhysoManagingBlock(entity.world, entityMountable.getReferencePosOptional().get());
if (physicsObjectOptional.isPresent()) {
worldBelow = physicsObjectOptional.get();
}
}
}
if (worldBelow == null) {
return null;
}
dx += total.x;
dy += total.y;
dz += total.z;
boolean alreadyOnGround = entity.onGround && (dy == origDy) && origDy < 0;
Vector3d original = new Vector3d(origDx, origDy, origDz);
Vector3d newMov = new Vector3d(dx - origDx, dy - origDy, dz - origDz);
entity.collidedHorizontally = original.dot(newMov) < 0;
entity.collidedVertically = isDifSignificant(dy, origDy);
entity.onGround = entity.collidedVertically && origDy < 0 || alreadyOnGround;
entity.collided = entity.collidedHorizontally || entity.collidedVertically;
// entity.resetPositionToBB();
double motionYBefore = entity.motionY;
float oldFallDistance = entity.fallDistance;
Vector3d dxyz = new Vector3d(dx, dy, dz);
;
Vector3d origDxyz = new Vector3d(origDx, origDy, origDz);
Vector3d origPosXyz = new Vector3d(origPosX, origPosY, origPosZ);
return new IntermediateMovementVariableStorage(dxyz, origDxyz, origPosXyz, alreadyOnGround, motionYBefore, oldFallDistance, worldBelow.getShipData());
}
use of org.valkyrienskies.mod.common.ships.ship_world.PhysicsObject in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.
the class EntityCollisionInjector method getCollidingPolygonsAndDoBlockCols.
/*
* This method generates an arrayList of Polygons that the player is colliding
* with
*/
public static ArrayList<Polygon> getCollidingPolygonsAndDoBlockCols(Entity entity, Vec3d velocity) {
ArrayList<Polygon> collisions = new ArrayList<Polygon>();
AxisAlignedBB entityBB = entity.getEntityBoundingBox().offset(velocity.x, velocity.y, velocity.z).expand(1, 1, 1);
List<PhysicsObject> ships = ((IHasShipManager) entity.getEntityWorld()).getManager().getPhysObjectsInAABB(entityBB);
// and the Player
for (PhysicsObject wrapper : ships) {
try {
Polygon playerInLocal = new Polygon(entityBB, wrapper.getShipTransformationManager().getCurrentTickTransform(), TransformType.GLOBAL_TO_SUBSPACE);
AxisAlignedBB bb = playerInLocal.getEnclosedAABB();
if ((bb.maxX - bb.minX) * (bb.maxZ - bb.minZ) > 9898989) {
// This is too big, something went wrong here
break;
}
List<AxisAlignedBB> collidingBBs = entity.world.getCollisionBoxes(entity, bb);
// TODO: Fix the performance of this!
if (entity.world.isRemote || entity instanceof EntityPlayer) {
VSMath.mergeAABBList(collidingBBs);
}
for (AxisAlignedBB inLocal : collidingBBs) {
ShipPolygon poly = new ShipPolygon(inLocal, wrapper.getShipTransformationManager().getCurrentTickTransform(), TransformType.SUBSPACE_TO_GLOBAL, wrapper.getShipTransformationManager().normals, wrapper);
collisions.add(poly);
}
} catch (Exception e) {
e.printStackTrace();
}
}
for (PhysicsObject wrapper : ships) {
double posX = entity.posX;
double posY = entity.posY;
double posZ = entity.posZ;
Vector3d entityPos = new Vector3d(posX, posY, posZ);
wrapper.getShipTransformationManager().getCurrentTickTransform().transformPosition(entityPos, TransformType.GLOBAL_TO_SUBSPACE);
setEntityPositionAndUpdateBB(entity, entityPos.x, entityPos.y, entityPos.z);
int entityChunkX = MathHelper.floor(entity.posX / 16.0D);
int entityChunkZ = MathHelper.floor(entity.posZ / 16.0D);
if (wrapper.getChunkClaim().containsChunk(entityChunkX, entityChunkZ)) {
Chunk chunkIn = wrapper.getChunkAt(entityChunkX, entityChunkZ);
int chunkYIndex = MathHelper.floor(entity.posY / 16.0D);
if (chunkYIndex < 0) {
chunkYIndex = 0;
}
if (chunkYIndex >= chunkIn.entityLists.length) {
chunkYIndex = chunkIn.entityLists.length - 1;
}
chunkIn.entityLists[chunkYIndex].add(entity);
entity.doBlockCollisions();
chunkIn.entityLists[chunkYIndex].remove(entity);
}
setEntityPositionAndUpdateBB(entity, posX, posY, posZ);
}
return collisions;
}
use of org.valkyrienskies.mod.common.ships.ship_world.PhysicsObject in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.
the class ItemShipTracker method onItemUse.
@Override
public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
if (!worldIn.isRemote) {
final ItemStack heldItemStack = player.getHeldItem(hand);
final NBTTagCompound stackTagCompound;
if (heldItemStack.hasTagCompound()) {
stackTagCompound = heldItemStack.stackTagCompound;
} else {
stackTagCompound = new NBTTagCompound();
}
final Optional<PhysicsObject> shipObjectOptional = ValkyrienUtils.getPhysoManagingBlock(worldIn, pos);
if (shipObjectOptional.isPresent()) {
final PhysicsObject shipObject = shipObjectOptional.get();
stackTagCompound.setString(NBT_DATA_KEY, shipObject.getUuid().toString());
heldItemStack.setTagCompound(stackTagCompound);
heldItemStack.setStackDisplayName(shipObject.getName() + " tracker");
player.sendMessage(new TextComponentString(String.format("Now tracking ship %s.", shipObject.getName())));
return EnumActionResult.SUCCESS;
}
}
return EnumActionResult.PASS;
}
use of org.valkyrienskies.mod.common.ships.ship_world.PhysicsObject in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.
the class EntityMountable method onUpdate.
@Override
public void onUpdate() {
if (this.firstUpdate) {
updateSharedNBT();
}
super.onUpdate();
// Check that this entity isn't broken.
if (mountPos == null) {
throw new IllegalStateException("Mounting position not present!");
}
if (mountPosSpace == null) {
throw new IllegalStateException("Mounting space type not present!");
}
if (!getEntityWorld().isRemote && !this.isBeingRidden()) {
this.setDead();
}
// Now update the position of this mounting entity.
Vec3d entityPos = mountPos;
if (mountPosSpace == CoordinateSpaceType.SUBSPACE_COORDINATES) {
if (referencePos == null) {
throw new IllegalStateException("Mounting reference position for ship not present!");
}
Optional<PhysicsObject> mountedOnto = getMountedShip();
if (mountedOnto.isPresent()) {
entityPos = mountedOnto.get().transformVector(entityPos, TransformType.SUBSPACE_TO_GLOBAL);
} else {
new IllegalStateException("Couldn't access ship with reference coordinates " + referencePos).printStackTrace();
return;
}
}
setPosition(entityPos.x, entityPos.y, entityPos.z);
}
Aggregations