Added solar systems support

Added configuration for breathing and gravity in other mods dimensions
Added configuration for groups world generation ratios in space
Added world border knockback with chat warnings
Added world border tolerance before entity kill
Fixed non-ship transitions from hyperspace
Fixed non-ship transitions when outside the overworld orbit
Improved /space and /debug command supported aliases
Removed chest teleportation from ship core
This commit is contained in:
LemADEC 2017-02-28 00:55:41 +01:00
parent e269118b1e
commit 369bbc746f
25 changed files with 1023 additions and 776 deletions

View file

@ -27,7 +27,7 @@ import net.minecraftforge.common.util.FakePlayerFactory;
import net.minecraftforge.event.world.BlockEvent;
public class CommonProxy {
public abstract class CommonProxy {
private static final WeakHashMap<GameProfile, WeakReference<EntityPlayer>> fakePlayers = new WeakHashMap<>(100);
void registerEntities() {

View file

@ -1,7 +1,7 @@
package cr0s.warpdrive;
import cr0s.warpdrive.config.Dictionary;
import cr0s.warpdrive.data.StarMapRegistry;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
@ -24,9 +24,10 @@ public class GravityManager {
public static double getGravityForEntity(Entity entity) {
if (WarpDrive.starMap.isLowGravity(entity.worldObj)) {
final double gravity = StarMapRegistry.getGravity(entity);
if (gravity < 1.0D) {
// Is entity in hyper-space?
boolean inHyperspace = WarpDrive.starMap.isInHyperspace(entity.worldObj);
boolean inHyperspace = gravity > 0.4D;
if (isEntityInGraviField(entity)) {
if (inHyperspace) {
@ -62,7 +63,8 @@ public class GravityManager {
}
public static double getItemGravity(EntityItem entity) {
if (WarpDrive.starMap.isLowGravity(entity.worldObj)) {
final double gravity = StarMapRegistry.getGravity(entity);
if (gravity < 1.0D) {
if (isEntityInGraviField(entity)) {
return SPACE_FIELD_ITEM_GRAVITY;
} else {
@ -74,7 +76,8 @@ public class GravityManager {
}
public static double getItemGravity2(EntityItem entity) {
if (WarpDrive.starMap.isLowGravity(entity.worldObj)) {
final double gravity = StarMapRegistry.getGravity(entity);
if (gravity < 1.0D) {
if (isEntityInGraviField(entity)) {
return SPACE_FIELD_ITEM_GRAVITY2;
} else {

View file

@ -11,6 +11,7 @@ import cr0s.warpdrive.block.TileEntityChunkLoader;
import cr0s.warpdrive.block.TileEntityLaser;
import cr0s.warpdrive.block.TileEntityLaserMedium;
import cr0s.warpdrive.block.atomic.BlockAcceleratorControlPoint;
import cr0s.warpdrive.block.atomic.BlockAcceleratorController;
import cr0s.warpdrive.block.atomic.BlockChiller;
import cr0s.warpdrive.block.atomic.BlockElectromagnetGlass;
import cr0s.warpdrive.block.atomic.BlockElectromagnetPlain;
@ -19,6 +20,7 @@ import cr0s.warpdrive.block.atomic.BlockParticlesInjector;
import cr0s.warpdrive.block.atomic.BlockVoidShellGlass;
import cr0s.warpdrive.block.atomic.BlockVoidShellPlain;
import cr0s.warpdrive.block.atomic.TileEntityAcceleratorControlPoint;
import cr0s.warpdrive.block.atomic.TileEntityAcceleratorController;
import cr0s.warpdrive.block.atomic.TileEntityParticlesInjector;
import cr0s.warpdrive.block.building.BlockShipScanner;
import cr0s.warpdrive.block.building.TileEntityShipScanner;
@ -95,6 +97,7 @@ import cr0s.warpdrive.damage.DamageShock;
import cr0s.warpdrive.damage.DamageTeleportation;
import cr0s.warpdrive.damage.DamageWarm;
import cr0s.warpdrive.data.CamerasRegistry;
import cr0s.warpdrive.data.CelestialObject;
import cr0s.warpdrive.data.CloakManager;
import cr0s.warpdrive.data.JumpgatesRegistry;
import cr0s.warpdrive.data.StarMapRegistry;
@ -624,10 +627,22 @@ public class WarpDrive implements LoadingCallback {
spaceBiome = (new BiomeSpace(WarpDriveConfig.G_SPACE_BIOME_ID)).setColor(0).setDisableRain().setBiomeName("Space");
BiomeDictionary.registerBiomeType(spaceBiome, BiomeDictionary.Type.DEAD, BiomeDictionary.Type.WASTELAND);
DimensionManager.registerProviderType(WarpDriveConfig.G_SPACE_PROVIDER_ID, SpaceWorldProvider.class, true);
DimensionManager.registerDimension(WarpDriveConfig.G_SPACE_DIMENSION_ID, WarpDriveConfig.G_SPACE_PROVIDER_ID);
DimensionManager.registerProviderType(WarpDriveConfig.G_HYPERSPACE_PROVIDER_ID, HyperSpaceWorldProvider.class, true);
DimensionManager.registerDimension(WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID, WarpDriveConfig.G_HYPERSPACE_PROVIDER_ID);
// only create dimensions if we own them
for (CelestialObject celestialObject : WarpDriveConfig.celestialObjects) {
if (celestialObject.isWarpDrive) {
if (celestialObject.isSpace()) {
DimensionManager.registerDimension(celestialObject.dimensionId, WarpDriveConfig.G_SPACE_PROVIDER_ID);
} else if (celestialObject.isHyperspace()) {
DimensionManager.registerDimension(celestialObject.dimensionId, WarpDriveConfig.G_HYPERSPACE_PROVIDER_ID);
} else {
WarpDrive.logger.error(String.format("Only space and hyperspace dimensions can be provided by WarpDrive. Dimension %d is not what of those.",
celestialObject.dimensionId));
}
}
}
if (FMLCommonHandler.instance().getEffectiveSide().isClient()) {
creativeTabWarpDrive.setBackgroundImageName("items.png");
@ -636,8 +651,12 @@ public class WarpDrive implements LoadingCallback {
@EventHandler
public void onFMLPostInitialization(FMLPostInitializationEvent event) {
DimensionManager.getWorld(WarpDriveConfig.G_SPACE_DIMENSION_ID);
DimensionManager.getWorld(WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID);
// load all owned dimensions at boot
for (CelestialObject celestialObject : WarpDriveConfig.celestialObjects) {
if (celestialObject.isWarpDrive) {
DimensionManager.getWorld(celestialObject.dimensionId);
}
}
WarpDriveConfig.onFMLPostInitialization();

View file

@ -42,7 +42,7 @@ public class TileEntityAirGenerator extends TileEntityAbstractEnergy {
}
// Air generator works only in space & hyperspace
if (WarpDrive.starMap.hasAtmosphere(worldObj)) {
if (WarpDrive.starMap.hasAtmosphere(worldObj, xCoord, zCoord)) {
if (getBlockMetadata() != 0) {
worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 2); // set disabled texture
}

View file

@ -435,7 +435,7 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
return 1.0D;
}
double attenuation;
if (WarpDrive.starMap.hasAtmosphere(worldObj)) {
if (WarpDrive.starMap.hasAtmosphere(worldObj, xCoord, zCoord)) {
attenuation = WarpDriveConfig.LASER_CANNON_ENERGY_ATTENUATION_PER_AIR_BLOCK;
} else {
attenuation = WarpDriveConfig.LASER_CANNON_ENERGY_ATTENUATION_PER_VOID_BLOCK;

View file

@ -87,7 +87,7 @@ public class TileEntityMiningLaser extends TileEntityAbstractMiner {
return;
}
boolean isOnPlanet = WarpDrive.starMap.isPlanet(worldObj);
boolean isOnPlanet = WarpDrive.starMap.hasAtmosphere(worldObj, xCoord, zCoord);
delayTicks--;
if (currentState == STATE_WARMUP) {

View file

@ -566,13 +566,13 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced {
@Callback
@Optional.Method(modid = "OpenComputers")
public Object[] isInSpace(Context context, Arguments arguments) {
return new Boolean[] { WarpDrive.starMap.isInSpace(worldObj) };
return new Boolean[] { WarpDrive.starMap.isInSpace(worldObj, xCoord, zCoord) };
}
@Callback
@Optional.Method(modid = "OpenComputers")
public Object[] isInHyperspace(Context context, Arguments arguments) {
return new Boolean[] { WarpDrive.starMap.isInHyperspace(worldObj) };
return new Boolean[] { WarpDrive.starMap.isInHyperspace(worldObj, xCoord, zCoord) };
}
@Callback
@ -792,82 +792,81 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced {
switch (methodName) {
case "dim_positive": // dim_positive (front, right, up)
return dim_positive(arguments);
case "dim_negative": // dim_negative (back, left, down)
return dim_negative(arguments);
case "mode": // mode (mode)
return mode(arguments);
case "distance": // distance (distance)
return distance(arguments);
case "direction": // direction (direction)
return direction(arguments);
case "getAttachedPlayers":
return getAttachedPlayers();
case "summon":
return summon(arguments);
case "summon_all":
setSummonAllFlag(true);
break;
case "position":
if (core == null) {
return null;
}
return new Object[] { core.xCoord, core.yCoord, core.zCoord };
case "energy":
if (core == null) {
return null;
}
return core.energy();
case "getEnergyRequired": // getEnergyRequired(distance)
return getEnergyRequired(arguments);
case "jump":
doJump();
break;
case "getShipSize":
return getShipSize();
case "beaconFrequency":
return beaconFrequency(arguments);
case "getOrientation":
if (core != null) {
return new Object[] { core.dx, 0, core.dz };
}
return null;
case "coreFrequency":
return shipName(arguments);
case "isInSpace":
return new Boolean[] { WarpDrive.starMap.isInSpace(worldObj) };
return new Boolean[] { WarpDrive.starMap.isInSpace(worldObj, xCoord, zCoord) };
case "isInHyperspace":
return new Boolean[] { WarpDrive.starMap.isInHyperspace(worldObj) };
return new Boolean[] { WarpDrive.starMap.isInHyperspace(worldObj, xCoord, zCoord) };
case "targetJumpgate":
return targetJumpgate(arguments);
case "isAttached": // isAttached
case "isAttached":
if (core != null) {
return new Object[] { core.controller != null };
}
break;
case "movement":
return movement(arguments);
case "rotationSteps":
return rotationSteps(arguments);

View file

@ -16,11 +16,9 @@ import java.util.List;
import java.util.UUID;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
@ -29,12 +27,10 @@ import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityChest;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MathHelper;
import net.minecraft.util.StatCollector;
import net.minecraft.util.Vec3;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.util.ForgeDirection;
@ -55,7 +51,7 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta
IDLE(0),
BASIC_JUMP(1), // 0-128
LONG_JUMP(2), // 0-12800
TELEPORT(3),
// TELEPORT(3),
BEACON_JUMP(4), // Jump ship by beacon
HYPERSPACE(5), // Jump to/from Hyperspace
GATE_JUMP(6); // Jump via jumpgate
@ -76,7 +72,6 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta
private boolean isCooldownReported = false;
protected int randomWarmupAddition = 0;
private int chestTeleportUpdateTicks = 0;
private final int registryUpdateInterval_ticks = 20 * WarpDriveConfig.STARMAP_REGISTRY_UPDATE_INTERVAL_SECONDS;
private int registryUpdateTicks = 0;
private int bootTicks = 20;
@ -209,22 +204,6 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta
}
switch (currentMode) {
case TELEPORT:
if (worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord)) {
if (isChestSummonMode()) {
chestTeleportUpdateTicks++;
if (chestTeleportUpdateTicks >= 20) {
summonPlayersByChestCode();
chestTeleportUpdateTicks = 0;
}
} else {
teleportPlayersToSpace();
}
} else {
chestTeleportUpdateTicks = 0;
}
break;
case BASIC_JUMP:
case LONG_JUMP:
case BEACON_JUMP:
@ -586,7 +565,8 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta
if ( (shipBack + shipFront) > WarpDriveConfig.SHIP_MAX_SIDE_SIZE
|| (shipLeft + shipRight) > WarpDriveConfig.SHIP_MAX_SIDE_SIZE
|| (shipDown + shipUp) > WarpDriveConfig.SHIP_MAX_SIDE_SIZE) {
reason.append("Ship is too big (max is " + WarpDriveConfig.SHIP_MAX_SIDE_SIZE + " per side)");
reason.append(String.format("Ship is too big (max is %d per side)",
WarpDriveConfig.SHIP_MAX_SIDE_SIZE));
return false;
}
@ -607,8 +587,9 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta
updateShipMassAndVolume();
if ( !isUnlimited
&& shipMass > WarpDriveConfig.SHIP_VOLUME_MAX_ON_PLANET_SURFACE
&& WarpDrive.starMap.isPlanet(worldObj) ) {
reason.append("Ship is too big for a planet (max is " + WarpDriveConfig.SHIP_VOLUME_MAX_ON_PLANET_SURFACE + " blocks)");
&& WarpDrive.starMap.isPlanet(worldObj, xCoord, zCoord) ) {
reason.append(String.format("Ship is too big for a planet (max is %d blocks)",
WarpDriveConfig.SHIP_VOLUME_MAX_ON_PLANET_SURFACE));
return false;
}
@ -712,10 +693,12 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta
if (percent > 80F) {
return true;
} else if (percent <= 0.001) {
reason.append("Ship is not inside a jumpgate. Jump rejected. Nearest jumpgate is " + jumpgate.toNiceString());
reason.append(String.format("Ship is not inside a jumpgate. Jump rejected. Nearest jumpgate is %s",
jumpgate.toNiceString()));
return false;
} else {
reason.append("Ship is only " + percent + "% inside a jumpgate. Sorry, we'll loose too much crew as is, jump rejected.");
reason.append(String.format("Ship is only %.1f%% inside a jumpgate. Sorry, we'll loose too much crew as is, jump rejected.",
percent));
return false;
}
}
@ -883,7 +866,7 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta
controller.getUp() + 1 + controller.getDown(),
controller.getRight() + 1 + controller.getLeft());
int maxDistance = WarpDriveConfig.SHIP_MAX_JUMP_DISTANCE;
if (WarpDrive.starMap.isInHyperspace(worldObj)) {
if (WarpDrive.starMap.isInHyperspace(worldObj, xCoord, zCoord)) {
maxDistance *= 100;
}
if (Math.abs(movement.x) - shipSize.x > maxDistance) {
@ -919,123 +902,6 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta
}
}
private void teleportPlayersToSpace() {
if (!WarpDrive.starMap.isInSpace(worldObj)) {
AxisAlignedBB axisalignedbb = AxisAlignedBB.getBoundingBox(xCoord - 2, yCoord - 1, zCoord - 2, xCoord + 2, yCoord + 4, zCoord + 2);
List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, axisalignedbb);
final int dimensionIdSpace = WarpDriveConfig.G_SPACE_DIMENSION_ID;
WorldServer spaceWorld = MinecraftServer.getServer().worldServerForDimension(dimensionIdSpace);
if (spaceWorld == null) {
String msg = "Unable to load Space dimension " + dimensionIdSpace + ", aborting teleportation.";
messageToAllPlayersOnShip(msg);
return;
}
for (Object o : list) {
if (!energy_consume(WarpDriveConfig.SHIP_TELEPORT_ENERGY_PER_ENTITY, false)) {
return;
}
Entity entity = (Entity) o;
int x = MathHelper.floor_double(entity.posX);
int z = MathHelper.floor_double(entity.posZ);
// int y = MathHelper.floor_double(entity.posY);
int newY;
for (newY = 254; newY > 0; newY--) {
if (spaceWorld.getBlock(x, newY, z).isAssociatedBlock(Blocks.wool)) {
break;
}
}
if (newY <= 0) {
newY = 254;
}
if (entity instanceof EntityPlayerMP) {
((EntityPlayerMP) entity).mcServer.getConfigurationManager().transferPlayerToDimension(((EntityPlayerMP) entity),
dimensionIdSpace,
new SpaceTeleporter(DimensionManager.getWorld(dimensionIdSpace), 0, x, 256, z));
if (spaceWorld.isAirBlock(x, newY, z)) {
spaceWorld.setBlock(x, newY, z, Blocks.stone, 0, 2);
spaceWorld.setBlock(x + 1, newY, z, Blocks.stone, 0, 2);
spaceWorld.setBlock(x - 1, newY, z, Blocks.stone, 0, 2);
spaceWorld.setBlock(x, newY, z + 1, Blocks.stone, 0, 2);
spaceWorld.setBlock(x, newY, z - 1, Blocks.stone, 0, 2);
spaceWorld.setBlock(x + 1, newY, z + 1, Blocks.stone, 0, 2);
spaceWorld.setBlock(x - 1, newY, z - 1, Blocks.stone, 0, 2);
spaceWorld.setBlock(x + 1, newY, z - 1, Blocks.stone, 0, 2);
spaceWorld.setBlock(x - 1, newY, z + 1, Blocks.stone, 0, 2);
}
((EntityPlayerMP) entity).setPositionAndUpdate(x + 0.5D, newY + 2.0D, z + 0.5D);
((EntityPlayerMP) entity).sendPlayerAbilities();
}
}
}
}
private void summonPlayersByChestCode() {
if (worldObj.getTileEntity(xCoord, yCoord + 1, zCoord) == null) {
return;
}
TileEntityChest chest = (TileEntityChest) worldObj.getTileEntity(xCoord, yCoord + 1, zCoord);
EntityPlayerMP player;
for (int i = 0; i < MinecraftServer.getServer().getConfigurationManager().playerEntityList.size(); i++) {
player = (EntityPlayerMP) MinecraftServer.getServer().getConfigurationManager().playerEntityList.get(i);
if (checkPlayerInventory(chest, player)) {
WarpDrive.logger.info(this + " Summoning " + player.getDisplayName());
summonPlayer(player, xCoord, yCoord + 2, zCoord);
}
}
}
private static boolean checkPlayerInventory(TileEntityChest chest, EntityPlayerMP player) {
Boolean result = false;
final int MIN_KEY_LENGTH = 5;
int keyLength = 0;
for (int index = 0; index < chest.getSizeInventory(); index++) {
ItemStack chestItem = chest.getStackInSlot(index);
ItemStack playerItem = player.inventory.getStackInSlot(9 + index);
if (chestItem == null) {
continue;
}
if (playerItem == null || chestItem != playerItem
|| chestItem.getItemDamage() != playerItem.getItemDamage()
|| chestItem.stackSize != playerItem.stackSize) {
return false;
} else {
result = true;
}
keyLength++;
}
if (keyLength < MIN_KEY_LENGTH) {
WarpDrive.logger.info("[ChestCode] Key is too short: " + keyLength + " < " + MIN_KEY_LENGTH);
return false;
}
return result;
}
private Boolean isChestSummonMode() {
TileEntity tileEntity = worldObj.getTileEntity(xCoord, yCoord + 1, zCoord);
if (tileEntity != null) {
return (tileEntity instanceof TileEntityChest);
}
return false;
}
private static boolean isOutsideBB(AxisAlignedBB axisalignedbb, int x, int y, int z) {
return axisalignedbb.minX > x || axisalignedbb.maxX < x
|| axisalignedbb.minY > y || axisalignedbb.maxY < y
@ -1051,9 +917,6 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta
public static int calculateRequiredEnergy(EnumShipCoreMode enumShipCoreMode, int shipVolume, int jumpDistance) {
switch (enumShipCoreMode) {
case TELEPORT:
return WarpDriveConfig.SHIP_TELEPORT_ENERGY_PER_ENTITY;
case BASIC_JUMP:
return (WarpDriveConfig.SHIP_NORMALJUMP_ENERGY_PER_BLOCK * shipVolume) + (WarpDriveConfig.SHIP_NORMALJUMP_ENERGY_PER_DISTANCE * jumpDistance);

View file

@ -134,7 +134,7 @@ public class BlockAir extends Block {
}
int concentration = world.getBlockMetadata(x, y, z);
boolean hasAtmosphere = WarpDrive.starMap.hasAtmosphere(world);
boolean hasAtmosphere = WarpDrive.starMap.hasAtmosphere(world, x, z);
// Remove air block to vacuum block
if (concentration <= 0 || hasAtmosphere) {
@ -394,7 +394,7 @@ public class BlockAir extends Block {
@Override
public void onBlockAdded(World world, int x, int y, int z) {
if (!WarpDrive.starMap.hasAtmosphere(world)) {
if (!WarpDrive.starMap.hasAtmosphere(world, x, z)) {
world.scheduleBlockUpdate(x, y, z, this, tickRate(world));
} else {
world.setBlockToAir(x, y, z);

View file

@ -112,7 +112,7 @@ public class BlockGas extends Block {
@Override
public void onBlockAdded(World world, int x, int y, int z) {
// Gas blocks are only allowed in space
if (WarpDrive.starMap.hasAtmosphere(world)) {
if (WarpDrive.starMap.hasAtmosphere(world, x, z)) {
world.setBlockToAir(x, y, z);
}
}

View file

@ -2,11 +2,12 @@ package cr0s.warpdrive.command;
import cr0s.warpdrive.Commons;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.StarMapRegistry;
import net.minecraft.block.Block;
import net.minecraft.command.CommandBase;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
@ -46,43 +47,15 @@ public class CommandDebug extends CommandBase
int dim, x, y, z, metadata;
int block;
String actions;
try
{
String par = params[0].toLowerCase();
switch (par) {
case "world":
case "overworld":
case "0":
dim = 0;
break;
case "nether":
case "thenether":
case "-1":
dim = -1;
break;
case "s":
case "space":
dim = WarpDriveConfig.G_SPACE_DIMENSION_ID;
break;
case "h":
case "hyper":
case "hyperspace":
dim = WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID;
break;
default:
dim = Integer.parseInt(par);
break;
}
try {
dim = StarMapRegistry.getDimensionId(params[0], (EntityPlayer) icommandsender);
x = Integer.parseInt(params[1]);
y = Integer.parseInt(params[2]);
z = Integer.parseInt(params[3]);
block = Integer.parseInt(params[4]);
metadata = Integer.parseInt(params[5]);
actions = params[6];
}
catch (Exception exception)
{
} catch (Exception exception) {
exception.printStackTrace();
Commons.addChatMessage(player, getCommandUsage(icommandsender));
return;

View file

@ -60,7 +60,7 @@ public class CommandGenerate extends CommandBase {
String structure = params[0];
// Reject command, if player is not in space
if (!WarpDrive.starMap.isInSpace(world) && (!"ship".equals(structure))) {
if (!WarpDrive.starMap.isInSpace(world, x, z) && (!"ship".equals(structure))) {
Commons.addChatMessage(commandSender, "* generate: this structure is only allowed in space!");
return;
}

View file

@ -2,7 +2,9 @@ package cr0s.warpdrive.command;
import cr0s.warpdrive.Commons;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.CelestialObject;
import cr0s.warpdrive.data.StarMapRegistry;
import cr0s.warpdrive.data.VectorI;
import cr0s.warpdrive.world.SpaceTeleporter;
import java.util.List;
@ -54,7 +56,7 @@ public class CommandSpace extends CommandBase {
if (entityPlayerMPs_found != null) {
entityPlayerMPs = entityPlayerMPs_found;
} else if (sender instanceof EntityPlayer) {
targetDimensionId = getDimensionId(params[0]);
targetDimensionId = StarMapRegistry.getDimensionId(params[0], (EntityPlayer) sender);
} else {
Commons.addChatMessage(sender, "/space: player not found '" + params[0] + "'");
return;
@ -68,7 +70,7 @@ public class CommandSpace extends CommandBase {
Commons.addChatMessage(sender, "/space: player not found '" + params[0] + "'");
return;
}
targetDimensionId = getDimensionId(params[1]);
targetDimensionId = StarMapRegistry.getDimensionId(params[1], entityPlayerMPs[0]);
} else {
Commons.addChatMessage(sender, "/space: too many arguments " + params.length);
@ -83,14 +85,54 @@ public class CommandSpace extends CommandBase {
for (EntityPlayerMP entityPlayerMP : entityPlayerMPs) {
// toggle between overworld and space if no dimension was provided
int newX = MathHelper.floor_double(entityPlayerMP.posX);
int newY = Math.min(255, Math.max(0, MathHelper.floor_double(entityPlayerMP.posY)));
int newZ = MathHelper.floor_double(entityPlayerMP.posZ);
if (targetDimensionId == Integer.MAX_VALUE) {
if (WarpDrive.starMap.isInSpace(entityPlayerMP.worldObj)) {
targetDimensionId = 0;
CelestialObject celestialObject = StarMapRegistry.getCelestialObject(entityPlayerMP.worldObj.provider.dimensionId, (int) entityPlayerMP.posX, (int) entityPlayerMP.posZ);
if (celestialObject.isSpace() || celestialObject.isHyperspace()) {
// in space or hyperspace => move to closest child
celestialObject = StarMapRegistry.getClosestChildCelestialObject(entityPlayerMP.worldObj.provider.dimensionId, (int) entityPlayerMP.posX, (int) entityPlayerMP.posZ);
if (celestialObject == null) {
targetDimensionId = 0;
} else {
targetDimensionId = celestialObject.dimensionId;
VectorI vEntry = celestialObject.getEntryOffset();
newX += vEntry.x;
newY += vEntry.y;
newZ += vEntry.z;
}
} else {
targetDimensionId = WarpDriveConfig.G_SPACE_DIMENSION_ID;
// on a planet => move to space
celestialObject = StarMapRegistry.getClosestParentCelestialObject(entityPlayerMP.worldObj.provider.dimensionId, (int) entityPlayerMP.posX, (int) entityPlayerMP.posZ);
if (celestialObject == null) {
targetDimensionId = 0;
} else {
VectorI vEntry = celestialObject.getEntryOffset();
newX -= vEntry.x;
newY -= vEntry.y;
newZ -= vEntry.z;
if (celestialObject.isSpace()) {
targetDimensionId = celestialObject.dimensionId;
} else {
targetDimensionId = celestialObject.parentDimensionId;
}
}
}
}
// get target celestial object
final CelestialObject celestialObject = StarMapRegistry.getCelestialObject(targetDimensionId, newX, newZ);
// force to center if we're outside the border
if ( celestialObject != null
&& celestialObject.getSquareDistanceOutsideBorder(targetDimensionId, newX, newZ) > 0 ) {
// outside
newX = celestialObject.dimensionCenterX;
newZ = celestialObject.dimensionCenterZ;
}
// get target world
WorldServer targetWorld = server.worldServerForDimension(targetDimensionId);
if (targetWorld == null) {
@ -107,9 +149,6 @@ public class CommandSpace extends CommandBase {
}
// find a good spot
int newX = MathHelper.floor_double(entityPlayerMP.posX);
int newY = Math.min(255, Math.max(0, MathHelper.floor_double(entityPlayerMP.posY)));
int newZ = MathHelper.floor_double(entityPlayerMP.posZ);
if ( (targetWorld.isAirBlock(newX, newY - 1, newZ) && !entityPlayerMP.capabilities.allowFlying)
|| !targetWorld.isAirBlock(newX, newY, newZ)
@ -158,25 +197,4 @@ public class CommandSpace extends CommandBase {
return null;
}
private int getDimensionId(String stringDimension) {
if (stringDimension.equalsIgnoreCase("overworld")) {
return 0;
} else if (stringDimension.equalsIgnoreCase("nether")) {
return -1;
} else if (stringDimension.equalsIgnoreCase("end") || stringDimension.equalsIgnoreCase("theend")) {
return 1;
} else if (stringDimension.equalsIgnoreCase("space")) {
return WarpDriveConfig.G_SPACE_DIMENSION_ID;
} else if (stringDimension.equalsIgnoreCase("hyper") || stringDimension.equalsIgnoreCase("hyperspace")) {
return WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID;
}
try {
return Integer.parseInt(stringDimension);
} catch(Exception exception) {
// exception.printStackTrace();
WarpDrive.logger.info("/space: invalid dimension '" + stringDimension + "', expecting integer or overworld/nether/end/theend/space/hyper/hyperspace");
}
return 0;
}
}

View file

@ -32,7 +32,7 @@ import cr0s.warpdrive.compat.CompatWarpDrive;
import cr0s.warpdrive.config.filler.FillerManager;
import cr0s.warpdrive.config.structures.StructureManager;
import cr0s.warpdrive.config.structures.StructureReference;
import cr0s.warpdrive.data.Planet;
import cr0s.warpdrive.data.CelestialObject;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
@ -99,10 +99,7 @@ public class WarpDriveConfig {
// General
public static int G_SPACE_BIOME_ID = 95;
public static int G_SPACE_PROVIDER_ID = 14;
public static int G_SPACE_DIMENSION_ID = -2;
public static int G_HYPERSPACE_PROVIDER_ID = 15;
public static int G_HYPERSPACE_DIMENSION_ID = -3;
public static int G_SPACE_WORLDBORDER_BLOCKS = 100000;
public static int G_ENTITY_SPHERE_GENERATOR_ID = 241;
public static int G_ENTITY_STAR_CORE_ID = 242;
public static int G_ENTITY_CAMERA_ID = 243;
@ -146,7 +143,7 @@ public class WarpDriveConfig {
public static boolean LOGGING_ACCELERATOR = false;
// Starmap
public static Planet[] PLANETS = null;
public static CelestialObject[] celestialObjects = null;
public static int STARMAP_REGISTRY_UPDATE_INTERVAL_SECONDS = 10;
// Space generator
@ -378,14 +375,8 @@ public class WarpDriveConfig {
config.get("general", "space_biome_id", G_SPACE_BIOME_ID, "Space biome ID").getInt());
G_SPACE_PROVIDER_ID = Commons.clamp(Integer.MIN_VALUE, Integer.MAX_VALUE,
config.get("general", "space_provider_id", G_SPACE_PROVIDER_ID, "Space dimension provider ID").getInt());
G_SPACE_DIMENSION_ID = Commons.clamp(Integer.MIN_VALUE, Integer.MAX_VALUE,
config.get("general", "space_dimension_id", G_SPACE_DIMENSION_ID, "Space dimension world ID").getInt());
G_HYPERSPACE_PROVIDER_ID = Commons.clamp(Integer.MIN_VALUE, Integer.MAX_VALUE,
config.get("general", "hyperspace_provider_id", G_HYPERSPACE_PROVIDER_ID, "Hyperspace dimension provider ID").getInt());
G_HYPERSPACE_DIMENSION_ID = Commons.clamp(Integer.MIN_VALUE, Integer.MAX_VALUE,
config.get("general", "hyperspace_dimension_id", G_HYPERSPACE_DIMENSION_ID, "Hyperspace dimension world ID").getInt());
G_SPACE_WORLDBORDER_BLOCKS = Commons.clamp(0, 3000000,
config.get("general", "space_worldborder_blocks", G_SPACE_WORLDBORDER_BLOCKS, "World border applied to hyperspace & space, set to 0 to disable it").getInt());
G_ENTITY_SPHERE_GENERATOR_ID = Commons.clamp(Integer.MIN_VALUE, Integer.MAX_VALUE,
config.get("general", "entity_sphere_generator_id", G_ENTITY_SPHERE_GENERATOR_ID, "Entity sphere generator ID").getInt());
@ -443,30 +434,80 @@ public class WarpDriveConfig {
LOGGING_FORCEFIELD_REGISTRY = config.get("logging", "enable_forcefield_registry_logs", LOGGING_FORCEFIELD_REGISTRY, "ForceField registry logs, enable it to dump forcefield registry updates").getBoolean(false);
LOGGING_ACCELERATOR = config.get("logging", "enable_accelerator_logs", LOGGING_ACCELERATOR, "Detailed accelerator logs to help debug the mod, enable it before reporting a bug").getBoolean(false);
// Planets
// Celestial objects
{
config.addCustomCategoryComment("planets",
"Planets are other dimensions connected through the Space dimension. Default is overworld with 100k radius.\n"
+ "Each planet orbit is square shaped and defined as a list of 7 integers (all measured in blocks).");
ConfigCategory categoryPlanets = config.getCategory("planets");
String[] planetsName = categoryPlanets.getValues().keySet().toArray(new String[0]);
if (planetsName.length == 0) {
planetsName = new String[] { "overworld" };
config.addCustomCategoryComment("celestial_objects",
"Celestial objects are generally planets. They can also be a solar system (space) or the all mighty hyperspace.\n"
+ "Each celestial object is defined with a list of 14 integers in the following exact order:\n"
+ "- dimensionId : this is the id of the dimension. 0 is the Overworld, -1 is the Nether, 1 is the End."
+ "- dimensionCenterX, dimensionCenterZ: those are the center coordinate of that dimension world border.\n"
+ " This is measured in blocks. For convenience, it's usually 0, 0\n"
+ "- radiusX, radiusZ: this is the world border radius, measured in blocks. The total size is twice that.\n"
+ " This is also the size of the orbit area in space, so don't go too big\n"
+ "- parentDimensionId: this is the id of the parent dimension. For planets, this is the space dimension id.\n"
+ "- parentCenterX, parentCenterZ: this is the center coordinates in the parent dimension. For a planet, it needs to be different than 0, 0.\n"
+ "- isWarpDrive: this is a boolean flag defining if WarpDrive provides this dimension or not.\n"
+ " Currently only Space and Hyperspace can be provided: use other mods to generate planet world.\n"
+ " Set this to 0 to use another mod Space dimension.\n"
+ "- moonRatio: this is the chance for a moon to generate in a chunk.\n"
+ "- asteroidRatio: this is the chance for a lone asteroid to generate in a chunk.\n"
+ "- asteroidFieldRatio: this is the chance for an asteroid field to generate in a chunk.\n"
+ " All 3 ratios work the same way: 100000 is 100% chance, 0 will disable it. Those only works in WarpDrive dimensions, they're ignored otherwise.\n"
+ "- gravity: this is the gravity simulation type. 0 is vanilla, 1 is space, 2 is hyperspace.\n"
+ "- isBreathable: this is a boolean flag defining if ambient atmosphere is breathable.\n"
+ "Hyperspace is a dimension which is its own parent. In other words, hyperspace.dimensionId = hyperspace.parentDimensionId. There can be only one.\n"
+ "A Space is a dimension with Hyperspace as its parent.\n"
+ "In theory, multiple planets can exists in the same minecraft world.");
final String commentDimension = "dimensionId, dimensionCenterX, dimensionCenterZ, radiusX, radiusZ,\n"
+ "parentDimensionId, parentCenterX, parentCenterZ, isWarpDrive,\n"
+ "moonRatio, asteroidRatio, asteroidFieldRatio, gravity, isBreathable";
ConfigCategory categoryDimensions = config.getCategory("celestial_objects");
String[] nameDimensions = categoryDimensions.getValues().keySet().toArray(new String[0]);
if (nameDimensions.length == 0) {
nameDimensions = new String[] { "overworld", "nether", "end", "space", "hyperspace" };
int[][] defaultDimensions = {
// id x z radiusX radiusZ id parentX parentZ W moon ast astF g air
{ 0, 0, 0, 10000, 10000, -2, 0, 0, 0, 0, 0, 0, 0, 1 },
{ -1, 0, 0, 2500, 2500, -2, 30000, -50000, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 1000, 1000, -2, -80000, 60000, 0, 0, 0, 0, 0, 1 },
{ -2, 0, 0, 100000, 100000, -3, 0, 0, 1, 125, 666, 166, 1, 0 },
{ -3, 0, 0, 100000, 100000, -3, 0, 0, 1, 0, 0, 0, 2, 0 }
};
for (int index = 0; index < nameDimensions.length; index++) {
config.get("celestial_objects", nameDimensions[index], defaultDimensions[index], commentDimension).getIntList();
}
}
int[] defaultPlanet = { 0, 0, 0, 100000, 100000, 0, 0 }; // 30000000 is Minecraft limit for SetBlock
PLANETS = new Planet[planetsName.length];
int[] intDefaultDimension = { 0, 0, 0, 10000, 10000, -2, 0, 0, 0, 0, 0, 0, 0, 1 }; // 30000000 is Minecraft limit for SetBlock
celestialObjects = new CelestialObject[nameDimensions.length];
int index = 0;
for (String name : planetsName) {
int[] planetInts = config.get("planets", name, defaultPlanet, "dimensionId, dimensionCenterX, dimensionCenterZ, radiusX, radiusZ, spaceCenterX, spaceCenterZ").getIntList();
if (planetInts.length != 7) {
WarpDrive.logger.warn("Invalid planet definition '" + name + "' (exactly 7 integers are expected), using default instead");
planetInts = defaultPlanet.clone();
for (String name : nameDimensions) {
int[] intDimension = config.get("celestial_objects", name, intDefaultDimension, commentDimension).getIntList();
if (intDimension.length != 14) {
WarpDrive.logger.warn("Invalid dimension definition '" + name + "' (exactly 8 integers are expected), using default instead");
intDimension = intDefaultDimension.clone();
}
Planet planet = new Planet(planetInts[0], planetInts[1], planetInts[2], planetInts[3], planetInts[4], planetInts[5], planetInts[6]);
WarpDrive.logger.info("Adding '" + name + "' as " + planet);
PLANETS[index] = planet;
CelestialObject celestialObject = new CelestialObject(intDimension[0], intDimension[1], intDimension[2], intDimension[3], intDimension[4],
intDimension[5], intDimension[6], intDimension[7]);
celestialObject.setSelfProvider(intDimension[8] != 0);
celestialObject.addGenerationRatio(intDimension[ 9] / 100000.0D, "moon");
celestialObject.addGenerationRatio(intDimension[10] / 100000.0D, "asteroid");
celestialObject.addGenerationRatio(intDimension[11] / 100000.0D, "asteroidField");
switch(intDimension[12]) {
case 0:
default:
celestialObject.setGravity(1.0D);
break;
case 1:
celestialObject.setGravity(0.3D);
break;
case 2:
celestialObject.setGravity(0.45D);
break;
}
celestialObject.setBreathable(intDimension[13] != 0);
WarpDrive.logger.info("Adding '" + name + "' as " + celestialObject);
celestialObjects[index] = celestialObject;
index++;
}
// FIXME: check planets aren't overlapping
@ -927,9 +968,10 @@ public class WarpDriveConfig {
public static void onFMLPostInitialization() {
// unpack default XML files if none are defined
File[] files = configDirectory.listFiles((file_notUsed, name) -> {
return name.endsWith(".xml");
});
File[] files = configDirectory.listFiles((file_notUsed, name) -> name.endsWith(".xml"));
if (files == null) {
throw new RuntimeException("Critical error accessing configuration directory, searching for *.xml files: " + configDirectory);
}
if (files.length == 0) {
for (String defaultXMLfilename : defaultXMLfilenames) {
unpackResourceToFolder(defaultXMLfilename, "config", configDirectory);

View file

@ -0,0 +1,271 @@
package cr0s.warpdrive.data;
import cr0s.warpdrive.WarpDrive;
import java.util.NavigableMap;
import java.util.Random;
import java.util.TreeMap;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
/**
* Celestial objects are area in space. They can be a planet or solar system (space dimension) or the all mighty hyperspace.
*
* @author LemADEC
*/
public class CelestialObject implements Cloneable {
public int dimensionId;
public int dimensionCenterX, dimensionCenterZ;
public int borderRadiusX, borderRadiusZ;
public int parentDimensionId;
public int parentCenterX, parentCenterZ;
public boolean isWarpDrive;
public double gravity;
public boolean isBreathable;
// @TODO replace with RandomCollection once we switch to XML
private final NavigableMap<Double, String> mapGenerationRatios = new TreeMap<>();
private double totalRatio;
public CelestialObject() {
this(0, 0, 0, 5000, 5000, -2, 0, 0);
}
public CelestialObject(final int parDimensionId, final int parDimensionCenterX, final int parDimensionCenterZ,
final int parBorderRadiusX, final int parBorderRadiusZ,
final int parParentDimensionId, final int parParentCenterX, final int parParentCenterZ) {
dimensionId = parDimensionId;
dimensionCenterX = parDimensionCenterX;
dimensionCenterZ = parDimensionCenterZ;
borderRadiusX = parBorderRadiusX;
borderRadiusZ = parBorderRadiusZ;
parentDimensionId = parParentDimensionId;
parentCenterX = parParentCenterX;
parentCenterZ = parParentCenterZ;
}
public CelestialObject(NBTTagCompound nbt) {
readFromNBT(nbt);
}
@SuppressWarnings("CloneDoesntCallSuperClone")
@Override
public CelestialObject clone() {
return new CelestialObject(dimensionId, dimensionCenterX, dimensionCenterZ, borderRadiusX, borderRadiusZ, parentDimensionId, parentCenterX, parentCenterZ);
}
public void setSelfProvider(final boolean isWarpDrive) {
this.isWarpDrive = isWarpDrive;
}
public void setGravity(final double gravity) {
this.gravity = gravity;
}
public void setBreathable(final boolean isBreathable) {
this.isBreathable = isBreathable;
}
public void addGenerationRatio(final double ratio, final String name) {
if (ratio <= 0 || ratio >= 1.0) {
WarpDrive.logger.warn("Ratio isn't in ]0, 1.0] bounds, skipping " + name + " with ratio " + ratio);
return;
}
if (mapGenerationRatios.containsValue(name)) {
WarpDrive.logger.warn("Object already has a ratio defined, skipping " + name + " with ratio " + ratio);
return;
}
if (totalRatio + ratio > 1.0) {
WarpDrive.logger.warn("Total ratio is greater than 1.0, skipping " + name + " with ratio " + ratio);
return;
}
totalRatio += ratio;
mapGenerationRatios.put(totalRatio, name);
}
public String getRandomGeneration(Random random) {
double value = random.nextDouble();
if (value >= totalRatio) {
return null;
}
return mapGenerationRatios.ceilingEntry(value).getValue();
}
public AxisAlignedBB getWorldBorderArea() {
return AxisAlignedBB.getBoundingBox(
(dimensionCenterX - borderRadiusX), 0, (dimensionCenterZ - borderRadiusZ),
(dimensionCenterX + borderRadiusX), 255, (dimensionCenterZ + borderRadiusZ) );
}
public AxisAlignedBB getAreaToReachParent() {
return AxisAlignedBB.getBoundingBox(
(dimensionCenterX - borderRadiusX), 250, (dimensionCenterZ - borderRadiusZ),
(dimensionCenterX + borderRadiusX), 255, (dimensionCenterZ + borderRadiusZ) );
}
public AxisAlignedBB getAreaInParent() {
return AxisAlignedBB.getBoundingBox(
(parentCenterX - borderRadiusX), 0, (parentCenterZ - borderRadiusZ),
(parentCenterX + borderRadiusX), 8, (parentCenterZ + borderRadiusZ) );
}
// offset vector when moving from parent to this dimension
public VectorI getEntryOffset() {
return new VectorI(dimensionCenterX - parentCenterX, 0, dimensionCenterZ - parentCenterZ);
}
public boolean isSpace() {
if (isHyperspace()) {
return false;
}
CelestialObject celestialObjectParent = StarMapRegistry.getCelestialObject(parentDimensionId, parentCenterX, parentCenterZ);
return celestialObjectParent != null && celestialObjectParent.isHyperspace();
}
public boolean isHyperspace() {
return parentDimensionId == dimensionId;
}
public boolean hasAtmosphere() {
return isBreathable && !isHyperspace() && !isSpace();
}
/**
* Compute distance from border to further point in an area.
* It's up to caller to verify if this celestial object is matched.
*
* @param aabb bounding box that should fit within border
* @return distance to transition borders, 0 if take off is possible
*/
public double getSquareDistanceOutsideBorder(final int dimensionId, final AxisAlignedBB aabb) {
if (dimensionId != this.dimensionId) {
return Double.POSITIVE_INFINITY;
}
final double rangeX = Math.max(Math.abs(aabb.minX - dimensionCenterX), Math.abs(aabb.maxX - dimensionCenterX));
final double rangeZ = Math.max(Math.abs(aabb.minZ - dimensionCenterZ), Math.abs(aabb.maxZ - dimensionCenterZ));
final double dX = rangeX - borderRadiusX;
final double dZ = rangeZ - borderRadiusZ;
if ((rangeX <= borderRadiusX) && (rangeZ <= borderRadiusZ)) {
return - (dX * dX + dZ * dZ);
}
return (dX * dX + dZ * dZ);
}
/**
* Compute distance to reach closest border, while inside the same dimension.
*
* @param dimensionId dimension id
* @param x coordinates inside the celestial object
* @param z coordinates inside the celestial object
* @return 'square' distance to the closest border,
* <=0 if we're inside, > 0 if we're outside,
* +INF if we're in the wrong dimension
*/
public double getSquareDistanceOutsideBorder(final int dimensionId, final double x, final double z) {
if (dimensionId != this.dimensionId) {
return Double.POSITIVE_INFINITY;
}
final double rangeX = Math.abs(x - dimensionCenterX);
final double rangeZ = Math.abs(z - dimensionCenterZ);
final double dX = rangeX - borderRadiusX;
final double dZ = rangeZ - borderRadiusZ;
if ( (rangeX <= borderRadiusX)
&& (rangeZ <= borderRadiusZ) ) {
// inside: both dX and dZ are negative, so the max is actually the closest to zero
final double dMax = Math.max(dX, dZ);
return - (dMax * dMax);
} else if ( (rangeX > borderRadiusX)
&& (rangeZ > borderRadiusZ) ) {
// outside in a diagonal
return (dX * dX + dZ * dZ);
}
// outside aligned: one is negative (inside), the other is positive (outside), so the max is the outside one
final double dMax = Math.max(dX, dZ);
return dMax * dMax;
}
/**
* Check if current space coordinates allow to enter this dimension atmosphere from space.
*
* @param dimensionId current position in parent dimension
* @param x current position in parent dimension
* @param z current position in parent dimension
* @return square distance to transition borders, 0 if we're in orbit of the object
*/
public double getSquareDistanceInParent(final int dimensionId, final double x, final double z) {
if (dimensionId != parentDimensionId) {
return Double.POSITIVE_INFINITY;
}
if ( (Math.abs(x - parentCenterX) <= borderRadiusX)
&& (Math.abs(z - parentCenterZ) <= borderRadiusZ) ) {
return 0.0D;
}
final double dx = Math.max(0.0D, Math.abs(x - parentCenterX) - borderRadiusX);
final double dz = Math.max(0.0D, Math.abs(z - parentCenterZ) - borderRadiusZ);
return dx * dx + dz * dz;
}
public void readFromNBT(NBTTagCompound tag) {
dimensionId = tag.getInteger("dimensionId");
dimensionCenterX = tag.getInteger("dimensionCenterX");
dimensionCenterZ = tag.getInteger("dimensionCenterZ");
borderRadiusX = tag.getInteger("borderSizeX");
borderRadiusZ = tag.getInteger("borderSizeZ");
parentDimensionId = tag.getInteger("parentDimensionId");
parentCenterX = tag.getInteger("parentCenterX");
parentCenterZ = tag.getInteger("parentCenterZ");
isWarpDrive = tag.getBoolean("isWarpDrive");
gravity = tag.getDouble("gravity");
isBreathable = tag.getBoolean("isBreathable");
// @TODO: mapGenerationRatios
}
public void writeToNBT(NBTTagCompound tag) {
tag.setInteger("dimensionId", dimensionId);
tag.setInteger("dimensionCenterX", dimensionCenterX);
tag.setInteger("dimensionCenterZ", dimensionCenterZ);
tag.setInteger("borderRadiusX", borderRadiusX);
tag.setInteger("borderRadiusZ", borderRadiusZ);
tag.setInteger("parentDimensionId", parentDimensionId);
tag.setInteger("parentCenterX", parentCenterX);
tag.setInteger("parentCenterZ", parentCenterZ);
tag.setBoolean("isWarpDrive", isWarpDrive);
tag.setDouble("gravity", gravity);
tag.setBoolean("isBreathable", isBreathable);
// @TODO: mapGenerationRatios
}
@Override
public int hashCode() {
return dimensionId << 16 + (dimensionCenterX >> 10) << 8 + (dimensionCenterZ >> 10);
}
@Override
public boolean equals(Object object) {
if (object instanceof CelestialObject) {
CelestialObject celestialObject = (CelestialObject) object;
return dimensionId == celestialObject.dimensionId
&& dimensionCenterX == celestialObject.dimensionCenterX
&& dimensionCenterZ == celestialObject.dimensionCenterZ
&& borderRadiusX == celestialObject.borderRadiusX
&& borderRadiusZ == celestialObject.borderRadiusZ
&& parentDimensionId == celestialObject.parentDimensionId
&& parentCenterX == celestialObject.parentCenterX
&& parentCenterZ == celestialObject.parentCenterZ;
}
return false;
}
@Override
public String toString() {
return "CelestialObject [Dimension " + dimensionId + " @ (" + dimensionCenterX + " " + dimensionCenterZ + ")"
+ " Border(" + borderRadiusX + " " + borderRadiusZ + ")"
+ " Parent(" + parentDimensionId + " @ (" + parentCenterX + " " + parentCenterZ + "))]"
+ " isWarpDrive + " + isWarpDrive + " gravity " + gravity + " isBreathable " + isBreathable;
}
}

View file

@ -1,8 +1,5 @@
package cr0s.warpdrive.data;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.WarpDriveConfig;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.WorldServer;
@ -55,24 +52,19 @@ public class GlobalPosition {
}
public VectorI getSpaceCoordinates() {
if (WarpDrive.starMap.isInSpace(dimensionId)) {
return new VectorI(x, y + 256, z);
CelestialObject celestialObject = StarMapRegistry.getCelestialObject(dimensionId, x, z);
if (celestialObject == null) {
// not a registered area
return null;
}
if (WarpDrive.starMap.isInHyperspace(dimensionId)) {
if (celestialObject.isHyperspace()) {
return new VectorI(x, y + 512, z);
}
for (Planet planet : WarpDriveConfig.PLANETS) {
if (planet.dimensionId == dimensionId) {
if ( (Math.abs(x - planet.dimensionCenterX) <= planet.borderSizeX)
&& (Math.abs(z - planet.dimensionCenterZ) <= planet.borderSizeZ)) {
return new VectorI(
x - planet.dimensionCenterX + planet.spaceCenterX,
y,
z - planet.dimensionCenterZ + planet.spaceCenterZ);
}
}
if (celestialObject.isSpace()) {
return new VectorI(x, y + 256, z);
}
return null;
VectorI vEntry = celestialObject.getEntryOffset();
return new VectorI(x - vEntry.x, y, z - vEntry.z);
}
public boolean equals(final TileEntity tileEntity) {

View file

@ -1,140 +0,0 @@
package cr0s.warpdrive.data;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
/**
* Transition planes between dimensions to land on a planet or take off from it to reach space.
*
* @author LemADEC
*/
public class Planet implements Cloneable {
public int dimensionId;
public int dimensionCenterX, dimensionCenterZ;
public int borderSizeX, borderSizeZ;
public int spaceCenterX, spaceCenterZ;
public Planet() {
this(0, 0, 0, 5000, 5000, 0, 0);
}
public Planet(int parDimensionId, int parDimensionCenterX, int parDimensionCenterZ, int parBorderSizeX, int parBorderSizeZ, int parSpaceCenterX, int parSpaceCenterZ) {
dimensionId = parDimensionId;
spaceCenterX = parSpaceCenterX;
spaceCenterZ = parSpaceCenterZ;
dimensionCenterX = parDimensionCenterX;
dimensionCenterZ = parDimensionCenterZ;
borderSizeX = parBorderSizeX;
borderSizeZ = parBorderSizeZ;
}
public Planet(NBTTagCompound nbt) {
readFromNBT(nbt);
}
/**
* Makes a new copy of this TransitionPlane. Prevents variable referencing problems.
*/
@SuppressWarnings("CloneDoesntCallSuperClone")
@Override
public Planet clone() {
return new Planet(dimensionId, dimensionCenterX, dimensionCenterZ, borderSizeX, borderSizeZ, spaceCenterX, spaceCenterZ);
}
/**
* Check if given bounding box is inside borders. It's up to caller to verify if this transition plane match current dimension.
*
* @param aabb bounding box that should fit within border
* @return distance to transition borders, 0 if take off is possible
*/
public int isInsideBorder(AxisAlignedBB aabb) {
double rangeX = Math.max(Math.abs(aabb.minX - dimensionCenterX), Math.abs(aabb.maxX - dimensionCenterX));
double rangeZ = Math.max(Math.abs(aabb.minZ - dimensionCenterZ), Math.abs(aabb.maxZ - dimensionCenterZ));
if ((rangeX <= borderSizeX) && (rangeZ <= borderSizeZ)) {
return 0;
}
return (int) Math.sqrt(
Math.pow(Math.max(0D, rangeX - borderSizeX), 2.0D)
+ Math.pow(Math.max(0D, rangeZ - borderSizeZ), 2.0D));
}
/**
* Check if current coordinates allow to take off from this dimension to reach space. It's up to caller to verify if this transition plane match current dimension.
*
* @param currentPosition current position in the planet/dimension
* @return distance to transition borders, 0 if take off is possible
*/
public int isValidToSpace(VectorI currentPosition) {
if ((Math.abs(currentPosition.x - dimensionCenterX) <= borderSizeX) && (Math.abs(currentPosition.z - dimensionCenterZ) <= borderSizeZ)) {
return 0;
}
return (int) Math.sqrt(
Math.pow(Math.max(0D, Math.abs(currentPosition.x - dimensionCenterX) - borderSizeX), 2.0D)
+ Math.pow(Math.max(0D, Math.abs(currentPosition.z - dimensionCenterZ) - borderSizeZ), 2.0D));
}
/**
* Check if current space coordinates allow to enter this dimension atmosphere from space. It's up to caller to verify if we're actually in space.
*
* @param currentPosition current position in space
* @return distance to transition borders, 0 if entry is possible
*/
public int isValidFromSpace(final VectorI currentPosition) {
return isValidFromSpace(currentPosition.x, currentPosition.z);
}
public int isValidFromSpace(final int x, final int z) {
if ((Math.abs(x - spaceCenterX) <= borderSizeX) && (Math.abs(z - spaceCenterZ) <= borderSizeZ)) {
return 0;
}
return (int) Math.sqrt( Math.pow(Math.max(0D, Math.abs(x - spaceCenterX) - borderSizeX), 2.0D)
+ Math.pow(Math.max(0D, Math.abs(z - spaceCenterZ) - borderSizeZ), 2.0D));
}
public void readFromNBT(NBTTagCompound tag) {
dimensionId = tag.getInteger("dimensionId");
dimensionCenterX = tag.getInteger("dimensionCenterX");
dimensionCenterZ = tag.getInteger("dimensionCenterZ");
borderSizeX = tag.getInteger("borderSizeX");
borderSizeZ = tag.getInteger("borderSizeZ");
spaceCenterX = tag.getInteger("spaceCenterX");
spaceCenterZ = tag.getInteger("spaceCenterZ");
}
public void writeToNBT(NBTTagCompound tag) {
tag.setInteger("dimensionId", dimensionId);
tag.setInteger("dimensionCenterX", dimensionCenterX);
tag.setInteger("dimensionCenterZ", dimensionCenterZ);
tag.setInteger("borderSizeX", borderSizeX);
tag.setInteger("borderSizeZ", borderSizeZ);
tag.setInteger("spaceCenterX", spaceCenterX);
tag.setInteger("spaceCenterZ", spaceCenterZ);
}
@Override
public int hashCode() {
return dimensionId << 16 + (dimensionCenterX >> 10) << 8 + (dimensionCenterZ >> 10);
}
@Override
public boolean equals(Object object) {
if (object instanceof Planet) {
Planet planet = (Planet) object;
return dimensionId == planet.dimensionId
&& dimensionCenterX == planet.dimensionCenterX
&& dimensionCenterZ == planet.dimensionCenterZ
&& borderSizeX == planet.borderSizeX
&& borderSizeZ == planet.borderSizeZ
&& spaceCenterX == planet.spaceCenterX
&& spaceCenterZ == planet.spaceCenterZ;
}
return false;
}
@Override
public String toString() {
return "Planet [Dimension " + dimensionId + "(" + dimensionCenterX + ", " + dimensionCenterZ + ")"
+ " Border(" + borderSizeX + ", " + borderSizeZ + ")"
+ " Space(" + spaceCenterX + ", " + spaceCenterZ + ")]";
}
}

View file

@ -15,6 +15,7 @@ import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.ChunkCoordIntPair;
@ -105,8 +106,126 @@ public class StarMapRegistry {
}
}
public static CelestialObject getCelestialObject(World world, final int x, final int z) {
return getCelestialObject(world.provider.dimensionId, x, z);
}
public static CelestialObject getCelestialObject(final int dimensionId, final int x, final int z) {
double distanceClosest = Double.POSITIVE_INFINITY;
CelestialObject celestialObjectClosest = null;
for (CelestialObject celestialObject : WarpDriveConfig.celestialObjects) {
if (dimensionId == celestialObject.dimensionId) {
final double distanceSquared = celestialObject.getSquareDistanceOutsideBorder(dimensionId, x, z);
if (distanceSquared <= 0) {
return celestialObject;
} else if (distanceClosest > distanceSquared) {
distanceClosest = distanceSquared;
celestialObjectClosest = celestialObject;
}
}
}
return celestialObjectClosest;
}
public static double getGravity(final Entity entity) {
final CelestialObject celestialObject = getCelestialObject(entity.worldObj, (int) entity.posX, (int) entity.posZ);
return celestialObject == null ? 1.0D : celestialObject.gravity;
}
public static CelestialObject getClosestParentCelestialObject(final int dimensionId, final int x, final int z) {
double closestPlanetDistance = Double.POSITIVE_INFINITY;
CelestialObject celestialObjectClosest = null;
for (CelestialObject celestialObject : WarpDriveConfig.celestialObjects) {
final double distanceSquared = celestialObject.getSquareDistanceOutsideBorder(dimensionId, x, z);
if (distanceSquared <= 0) {
return celestialObject;
} else if (closestPlanetDistance > distanceSquared) {
closestPlanetDistance = distanceSquared;
celestialObjectClosest = celestialObject;
}
}
return celestialObjectClosest;
}
public static CelestialObject getClosestChildCelestialObject(final int dimensionId, final int x, final int z) {
double closestPlanetDistance = Double.POSITIVE_INFINITY;
CelestialObject celestialObjectClosest = null;
for (CelestialObject celestialObject : WarpDriveConfig.celestialObjects) {
final double distanceSquared = celestialObject.getSquareDistanceInParent(dimensionId, x, z);
if (distanceSquared <= 0.0D) {
return celestialObject;
} else if (closestPlanetDistance > distanceSquared) {
closestPlanetDistance = distanceSquared;
celestialObjectClosest = celestialObject;
}
}
return celestialObjectClosest;
}
public static int getSpaceDimensionId(World world, final int x, final int z) {
CelestialObject celestialObject = getCelestialObject(world, x, z);
// already in space?
if (celestialObject.isSpace()) {
return celestialObject.dimensionId;
}
// coming from hyperspace?
if (celestialObject.isHyperspace()) {
celestialObject = getClosestChildCelestialObject(world.provider.dimensionId, x, z);
return celestialObject == null ? 0 : celestialObject.dimensionId;
}
// coming from a planet?
celestialObject = getClosestParentCelestialObject(world.provider.dimensionId, x, z);
return celestialObject == null ? 0 : (celestialObject.isSpace() ? celestialObject.dimensionId : celestialObject.parentDimensionId);
}
public static int getHyperspaceDimensionId(World world, final int x, final int z) {
CelestialObject celestialObject = getCelestialObject(world, x, z);
// already in hyperspace?
if (celestialObject.isHyperspace()) {
return celestialObject.dimensionId;
}
// coming from space?
if (celestialObject.isSpace()) {
return celestialObject.parentDimensionId;
}
// coming from a planet?
celestialObject = getClosestParentCelestialObject(world.provider.dimensionId, x, z);
if (celestialObject != null && !celestialObject.isHyperspace()) {
celestialObject = getClosestParentCelestialObject(world.provider.dimensionId, x, z);
}
return celestialObject == null ? 0 : celestialObject.parentDimensionId;
}
public static int getDimensionId(final String stringDimension, Entity entity) {
switch (stringDimension.toLowerCase()) {
case "world":
case "overworld":
case "0":
return 0;
case "nether":
case "thenether":
case "-1":
return -1;
case "s":
case "space":
return getSpaceDimensionId(entity.worldObj, (int) entity.posX, (int) entity.posZ);
case "h":
case "hyper":
case "hyperspace":
return getHyperspaceDimensionId(entity.worldObj, (int) entity.posX, (int) entity.posZ);
default:
try {
return Integer.parseInt(stringDimension);
} catch(Exception exception) {
// exception.printStackTrace();
WarpDrive.logger.info("Invalid dimension '" + stringDimension + "', expecting integer or overworld/nether/end/theend/space/hyper/hyperspace");
}
}
return 0;
}
public ArrayList<StarMapRegistryItem> radarScan(TileEntity tileEntity, final int radius) {
ArrayList<StarMapRegistryItem> res = new ArrayList<>(registry.size());
ArrayList<StarMapRegistryItem> starMapRegistryItems = new ArrayList<>(registry.size());
cleanup();
// printRegistry();
@ -121,40 +240,33 @@ public class StarMapRegistry {
if (distance2 <= radius2
&& (entry.isolationRate == 0.0D || tileEntity.getWorldObj().rand.nextDouble() >= entry.isolationRate)
&& (entry.getSpaceCoordinates() != null)) {
res.add(entry);
starMapRegistryItems.add(entry);
}
}
}
return res;
return starMapRegistryItems;
}
public boolean isInSpace(final int dimensionId) {
return dimensionId == WarpDriveConfig.G_SPACE_DIMENSION_ID;
public boolean isInSpace(final World world, final int x, final int z) {
CelestialObject celestialObject = getCelestialObject(world.provider.dimensionId, x, z);
return celestialObject != null && celestialObject.isSpace();
}
public boolean isInHyperspace(final int dimensionId) {
return dimensionId == WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID;
public boolean isInHyperspace(final World world, final int x, final int z) {
CelestialObject celestialObject = getCelestialObject(world.provider.dimensionId, x, z);
return celestialObject != null && celestialObject.isHyperspace();
}
public boolean isInSpace(final World world) {
return isInSpace(world.provider.dimensionId);
public boolean hasAtmosphere(final World world, final int x, final int z) {
CelestialObject celestialObject = getCelestialObject(world, x, z);
return celestialObject == null || celestialObject.hasAtmosphere();
}
public boolean isInHyperspace(final World world) {
return isInHyperspace(world.provider.dimensionId);
}
public boolean hasAtmosphere(final World world) {
return !isInSpace(world) && !isInHyperspace(world);
}
public boolean isPlanet(final World world) {
return !isInSpace(world) && !isInHyperspace(world);
}
public boolean isLowGravity(final World world) {
return isInSpace(world) || isInHyperspace(world);
public boolean isPlanet(final World world, final int x, final int z) {
CelestialObject celestialObject = getCelestialObject(world, x, z);
return celestialObject == null
|| (!celestialObject.isSpace() && !celestialObject.isHyperspace());
}
public void printRegistry(final String trigger) {

View file

@ -1,5 +1,6 @@
package cr0s.warpdrive.event;
import cr0s.warpdrive.CommonProxy;
import cr0s.warpdrive.LocalProfiler;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IBlockTransformer;
@ -7,10 +8,11 @@ import cr0s.warpdrive.api.ITransformation;
import cr0s.warpdrive.block.movement.TileEntityShipCore;
import cr0s.warpdrive.config.Dictionary;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.CelestialObject;
import cr0s.warpdrive.data.JumpBlock;
import cr0s.warpdrive.data.JumpShip;
import cr0s.warpdrive.data.MovingEntity;
import cr0s.warpdrive.data.Planet;
import cr0s.warpdrive.data.StarMapRegistry;
import cr0s.warpdrive.data.Transformation;
import cr0s.warpdrive.data.Vector3;
import cr0s.warpdrive.data.VectorI;
@ -274,7 +276,7 @@ public class JumpSequencer extends AbstractSequencer {
}
sourceWorldTicket = ForgeChunkManager.requestTicket(WarpDrive.instance, sourceWorld, Type.NORMAL);
if (sourceWorldTicket == null) {
reason.append("Chunkloading rejected in source world " + sourceWorld.getWorldInfo().getWorldName() + ". Aborting.");
reason.append(String.format("Chunkloading rejected in source world %s. Aborting.", sourceWorld.getWorldInfo().getWorldName()));
return false;
}
int x1 = ship.minX >> 4;
@ -286,7 +288,8 @@ public class JumpSequencer extends AbstractSequencer {
for (int z = z1; z <= z2; z++) {
chunkCount++;
if (chunkCount > sourceWorldTicket.getMaxChunkListDepth()) {
reason.append("Ship is extending over too many chunks in source world. Max is currently set to " + sourceWorldTicket.getMaxChunkListDepth() + " in forgeChunkLoading.cfg. Aborting.");
reason.append(String.format("Ship is extending over too many chunks in source world. Max is currently set to %d in forgeChunkLoading.cfg. Aborting.",
sourceWorldTicket.getMaxChunkListDepth()));
return false;
}
ForgeChunkManager.forceChunk(sourceWorldTicket, new ChunkCoordIntPair(x, z));
@ -302,7 +305,8 @@ public class JumpSequencer extends AbstractSequencer {
}
targetWorldTicket = ForgeChunkManager.requestTicket(WarpDrive.instance, targetWorld, Type.NORMAL);
if (targetWorldTicket == null) {
reason.append("Chunkloading rejected in target world " + sourceWorld.getWorldInfo().getWorldName() + ". Aborting.");
reason.append(String.format("Chunkloading rejected in target world %s. Aborting.",
sourceWorld.getWorldInfo().getWorldName()));
return false;
}
@ -317,7 +321,8 @@ public class JumpSequencer extends AbstractSequencer {
for (int z = z1; z <= z2; z++) {
chunkCount++;
if (chunkCount > targetWorldTicket.getMaxChunkListDepth()) {
reason.append("Ship is extending over too many chunks in target world. Max is currently set to " + targetWorldTicket.getMaxChunkListDepth() + " in forgeChunkLoading.cfg. Aborting.");
reason.append(String.format("Ship is extending over too many chunks in target world. Max is currently set to %d in forgeChunkLoading.cfg. Aborting.",
targetWorldTicket.getMaxChunkListDepth()));
return false;
}
ForgeChunkManager.forceChunk(targetWorldTicket, new ChunkCoordIntPair(x, z));
@ -451,8 +456,8 @@ public class JumpSequencer extends AbstractSequencer {
ship.writeToNBT(tagCompoundShip);
schematic.setTag("ship", tagCompoundShip);
writeNBTToFile(schematicFileName, schematic);
if (WarpDriveConfig.LOGGING_JUMP) {
// WarpDrive.logger.info(this + " Ship saved as " + schematicFileName);
if (WarpDriveConfig.LOGGING_JUMP && WarpDrive.isDev) {
WarpDrive.logger.info(this + " Ship saved as " + schematicFileName);
}
} catch (Exception exception) {
exception.printStackTrace();
@ -490,142 +495,30 @@ public class JumpSequencer extends AbstractSequencer {
StringBuilder reason = new StringBuilder();
boolean isInSpace = WarpDrive.starMap.isInSpace(sourceWorld);
boolean isInHyperSpace = WarpDrive.starMap.isInHyperspace(sourceWorld);
final CelestialObject celestialObjectSource = StarMapRegistry.getCelestialObject(
sourceWorld.provider.dimensionId, ship.coreX, ship.coreZ);
final boolean isInSpace = celestialObjectSource.isSpace();
final boolean isInHyperSpace = celestialObjectSource.isHyperspace();
boolean toSpace = (moveY > 0) && (ship.maxY + moveY > 255) && (!isInSpace) && (!isInHyperSpace);
boolean fromSpace = (moveY < 0) && (ship.minY + moveY < 0) && isInSpace;
final boolean toSpace = (moveY > 0) && (ship.maxY + moveY > 255) && (!isInSpace) && (!isInHyperSpace);
final boolean fromSpace = (moveY < 0) && (ship.minY + moveY < 0) && isInSpace;
betweenWorlds = fromSpace || toSpace || isHyperspaceJump;
if (isHyperspaceJump) {
if (isInHyperSpace) {
final int dimensionIdSpace = WarpDriveConfig.G_SPACE_DIMENSION_ID;
targetWorld = MinecraftServer.getServer().worldServerForDimension(dimensionIdSpace);
if (targetWorld == null) {
LocalProfiler.stop();
String msg = "Unable to load Space dimension " + dimensionIdSpace + ", aborting jump.";
ship.messageToAllPlayersOnShip(msg);
disable(msg);
return;
}
} else if (isInSpace) {
final int dimensionIdHyperspace = WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID;
targetWorld = MinecraftServer.getServer().worldServerForDimension(dimensionIdHyperspace);
if (targetWorld == null) {
LocalProfiler.stop();
String msg = "Unable to load Hyperspace dimension " + dimensionIdHyperspace + ", aborting jump.";
ship.messageToAllPlayersOnShip(msg);
disable(msg);
return;
}
} else {
String msg = "Unable to reach hyperspace from a planet";
disable(msg);
ship.messageToAllPlayersOnShip(msg);
{// compute targetWorld and movement vector (moveX, moveY, moveZ)
String message = computeTargetWorld(celestialObjectSource, isInSpace, isInHyperSpace, toSpace, fromSpace);
if (message != null) {
LocalProfiler.stop();
ship.messageToAllPlayersOnShip(message);
disable(message);
return;
}
} else if (toSpace) {
Boolean planetFound = false;
Boolean planetValid = false;
int closestPlanetDistance = Integer.MAX_VALUE;
Planet closestPlanet = null;
for (int indexPlanet = 0; (!planetValid) && indexPlanet < WarpDriveConfig.PLANETS.length; indexPlanet++) {
Planet planet = WarpDriveConfig.PLANETS[indexPlanet];
if (sourceWorld.provider.dimensionId == planet.dimensionId) {
planetFound = true;
int planetDistance = planet.isValidToSpace(new VectorI(ship.coreX, ship.coreY, ship.coreZ));
if (planetDistance == 0) {
planetValid = true;
moveX = planet.spaceCenterX - planet.dimensionCenterX;
moveZ = planet.spaceCenterZ - planet.dimensionCenterZ;
final int dimensionIdSpace = WarpDriveConfig.G_SPACE_DIMENSION_ID;
targetWorld = MinecraftServer.getServer().worldServerForDimension(dimensionIdSpace);
if (targetWorld == null) {
LocalProfiler.stop();
String msg = "Unable to load Space dimension " + dimensionIdSpace + ", aborting jump.";
ship.messageToAllPlayersOnShip(msg);
disable(msg);
return;
}
} else if (closestPlanetDistance > planetDistance) {
closestPlanetDistance = planetDistance;
closestPlanet = planet;
}
}
}
if (!planetFound) {
LocalProfiler.stop();
String msg = "Unable to reach space!\nThere's no planet defined for current dimension " + sourceWorld.provider.getDimensionName() + " ("
+ sourceWorld.provider.dimensionId + ")";
ship.messageToAllPlayersOnShip(msg);
disable(msg);
return;
}
if (!planetValid) {
LocalProfiler.stop();
assert(closestPlanet != null);
@SuppressWarnings("null") // Eclipse derp, don't remove
String msg = "Ship is outside planet border, unable to reach space!\nClosest transition plane is ~" + closestPlanetDistance + " m away ("
+ (closestPlanet.dimensionCenterX - closestPlanet.borderSizeX) + " 250 "
+ (closestPlanet.dimensionCenterZ - closestPlanet.borderSizeZ) + ") to ("
+ (closestPlanet.dimensionCenterX + closestPlanet.borderSizeX) + " 255 "
+ (closestPlanet.dimensionCenterZ + closestPlanet.borderSizeZ) + ")";
ship.messageToAllPlayersOnShip(msg);
disable(msg);
return;
}
} else if (fromSpace) {
Boolean planetFound = false;
int closestPlaneDistance = Integer.MAX_VALUE;
Planet closestTransitionPlane = null;
for (int indexPlanet = 0; (!planetFound) && indexPlanet < WarpDriveConfig.PLANETS.length; indexPlanet++) {
Planet planet = WarpDriveConfig.PLANETS[indexPlanet];
int planeDistance = planet.isValidFromSpace(new VectorI(ship.coreX, ship.coreY, ship.coreZ));
if (planeDistance == 0) {
planetFound = true;
moveX = planet.dimensionCenterX - planet.spaceCenterX;
moveZ = planet.dimensionCenterZ - planet.spaceCenterZ;
targetWorld = MinecraftServer.getServer().worldServerForDimension(planet.dimensionId);
if (targetWorld == null) {
LocalProfiler.stop();
String msg = "Undefined dimension " + planet.dimensionId + ", aborting jump. Check your server configuration!";
ship.messageToAllPlayersOnShip(msg);
disable(msg);
return;
}
} else if (closestPlaneDistance > planeDistance) {
closestPlaneDistance = planeDistance;
closestTransitionPlane = planet;
}
}
if (!planetFound) {
LocalProfiler.stop();
String msg;
if (closestTransitionPlane == null) {
msg = "No planet defined, unable to enter atmosphere!";
} else {
msg = "No planet in range, unable to enter atmosphere!\nClosest planet is " + closestPlaneDistance + " m away ("
+ (closestTransitionPlane.spaceCenterX - closestTransitionPlane.borderSizeX) + " 250 "
+ (closestTransitionPlane.spaceCenterZ - closestTransitionPlane.borderSizeZ) + ") to ("
+ (closestTransitionPlane.spaceCenterX + closestTransitionPlane.borderSizeX) + " 255 "
+ (closestTransitionPlane.spaceCenterZ + closestTransitionPlane.borderSizeZ) + ")";
}
ship.messageToAllPlayersOnShip(msg);
disable(msg);
return;
}
} else {
targetWorld = sourceWorld;
}
// Check mass constrains
if ( WarpDrive.starMap.isPlanet(sourceWorld)
|| WarpDrive.starMap.isPlanet(targetWorld) ) {
if ( WarpDrive.starMap.isPlanet(sourceWorld, ship.coreX, ship.coreZ)
|| WarpDrive.starMap.isPlanet(targetWorld, ship.coreX + moveX, ship.coreZ + moveZ) ) {
if (!ship.isUnlimited() && ship.actualMass > WarpDriveConfig.SHIP_VOLUME_MAX_ON_PLANET_SURFACE) {
LocalProfiler.stop();
String msg = "Ship is too big for a planet (max is " + WarpDriveConfig.SHIP_VOLUME_MAX_ON_PLANET_SURFACE + " blocks)";
ship.messageToAllPlayersOnShip(msg);
disable(msg);
@ -698,54 +591,26 @@ public class JumpSequencer extends AbstractSequencer {
}
// Check world border
if ( (targetWorld.provider.dimensionId == WarpDriveConfig.G_SPACE_DIMENSION_ID)
|| (targetWorld.provider.dimensionId == WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID)) {
if (WarpDriveConfig.G_SPACE_WORLDBORDER_BLOCKS > 0) {// Space world border is enabled
if ( Math.abs(aabbTarget.minX) > WarpDriveConfig.G_SPACE_WORLDBORDER_BLOCKS
|| Math.abs(aabbTarget.minZ) > WarpDriveConfig.G_SPACE_WORLDBORDER_BLOCKS
|| Math.abs(aabbTarget.maxX) > WarpDriveConfig.G_SPACE_WORLDBORDER_BLOCKS
|| Math.abs(aabbTarget.maxZ) > WarpDriveConfig.G_SPACE_WORLDBORDER_BLOCKS ) {
// cancel jump
String msg = "Space border reach, max is " + WarpDriveConfig.G_SPACE_WORLDBORDER_BLOCKS;
disable(msg);
ship.messageToAllPlayersOnShip(msg);
LocalProfiler.stop();
return;
}
CelestialObject celestialObjectTarget = StarMapRegistry.getCelestialObject(targetWorld.provider.dimensionId, (int) aabbTarget.minX, (int) aabbTarget.minZ);
if (celestialObjectTarget == null) {
if (WarpDriveConfig.LOGGING_JUMP) {
WarpDrive.logger.error(String.format("There's no world border defined for dimension %s (%d)",
targetWorld.provider.getDimensionName(), targetWorld.provider.dimensionId));
}
} else {
Boolean planetFound = false;
Boolean planetValid = false;
int closestPlanetDistance = Integer.MAX_VALUE;
Planet closestPlanet = null;
for (int indexPlanet = 0; (!planetValid) && indexPlanet < WarpDriveConfig.PLANETS.length; indexPlanet++) {
Planet planet = WarpDriveConfig.PLANETS[indexPlanet];
if (targetWorld.provider.dimensionId == planet.dimensionId) {
planetFound = true;
int planetDistance = planet.isInsideBorder(aabbTarget);
if (planetDistance == 0) {
planetValid = true;
} else if (closestPlanetDistance > planetDistance) {
closestPlanetDistance = planetDistance;
closestPlanet = planet;
}
}
}
if (!planetFound) {
if (WarpDriveConfig.LOGGING_JUMP) {
WarpDrive.logger.error("There's no world border defined for dimension " + targetWorld.provider.getDimensionName());
}
} else if (!planetValid) {
// are we in range?
final double distanceSquared = celestialObjectTarget.getSquareDistanceOutsideBorder(targetWorld.provider.dimensionId, aabbTarget);
if (distanceSquared > 0) {
AxisAlignedBB axisAlignedBB = celestialObjectTarget.getWorldBorderArea();
String message = String.format(
"Target ship position is outside planet border, unable to jump!\n"
+ "World borders are (%d %d %d) to (%d %d %d).",
(int) axisAlignedBB.minX, (int) axisAlignedBB.minY, (int) axisAlignedBB.minZ,
(int) axisAlignedBB.maxX, (int) axisAlignedBB.maxY, (int) axisAlignedBB.maxZ );
LocalProfiler.stop();
assert (closestPlanet != null);
String msg = "Target ship position is outside planet border, unable to jump!\nPlanet borders are ("
+ (closestPlanet.dimensionCenterX - closestPlanet.borderSizeX) + " 0 "
+ (closestPlanet.dimensionCenterZ - closestPlanet.borderSizeZ) + ") to ("
+ (closestPlanet.dimensionCenterX + closestPlanet.borderSizeX) + " 255 "
+ (closestPlanet.dimensionCenterZ + closestPlanet.borderSizeZ) + ")";
ship.messageToAllPlayersOnShip(msg);
disable(msg);
ship.messageToAllPlayersOnShip(message);
disable(message);
return;
}
}
@ -811,6 +676,120 @@ public class JumpSequencer extends AbstractSequencer {
}
}
private String computeTargetWorld(CelestialObject celestialObjectSource, boolean isInSpace, boolean isInHyperSpace, boolean toSpace, boolean fromSpace) {
if (isHyperspaceJump) {
if (isInHyperSpace) {
CelestialObject celestialObject = StarMapRegistry.getClosestChildCelestialObject(sourceWorld.provider.dimensionId, ship.coreX, ship.coreZ);
// anything defined?
if (celestialObject == null) {
return String.format("Unable to reach space from this location!\nThere's no celestial object defined for current dimension %s (%d).",
sourceWorld.provider.getDimensionName(), sourceWorld.provider.dimensionId);
}
// are we clear for transit?
final double distanceSquared = celestialObject.getSquareDistanceInParent(sourceWorld.provider.dimensionId, ship.coreX, ship.coreZ);
if (distanceSquared > 0.0D) {
AxisAlignedBB axisAlignedBB = celestialObject.getAreaInParent();
return String.format(
"Ship is outside any solar system, unable to reach space!\n"
+ "Closest transition area is ~%d m away (%d %d %d) to (%d %d %d).",
(int) Math.sqrt(distanceSquared),
(int) axisAlignedBB.minX, (int) axisAlignedBB.minY, (int) axisAlignedBB.minZ,
(int) axisAlignedBB.maxX, (int) axisAlignedBB.maxY, (int) axisAlignedBB.maxZ );
}
// is world available?
final int dimensionIdSpace = celestialObject.dimensionId;
targetWorld = MinecraftServer.getServer().worldServerForDimension(dimensionIdSpace);
if (targetWorld == null) {
return String.format("Unable to load Space dimension %d, aborting jump.",
dimensionIdSpace);
}
} else if (isInSpace) {
// (target world border is checked systematically after movement checks)
// is world available?
final int dimensionIdHyperspace = celestialObjectSource.parentDimensionId;
targetWorld = MinecraftServer.getServer().worldServerForDimension(dimensionIdHyperspace);
if (targetWorld == null) {
return String.format("Unable to load Hyperspace dimension %d, aborting jump.",
dimensionIdHyperspace);
}
} else {
return "Unable to reach hyperspace from a planet";
}
} else if (toSpace) {
CelestialObject celestialObject = StarMapRegistry.getClosestParentCelestialObject(sourceWorld.provider.dimensionId, ship.coreX, ship.coreZ);
// anything defined?
if (celestialObject == null) {
return String.format("Unable to reach space!\nThere's no planet defined for current dimension %s (%d).",
sourceWorld.provider.getDimensionName(), sourceWorld.provider.dimensionId);
}
// are we clear for transit?
final double distanceSquared = celestialObject.getSquareDistanceOutsideBorder(sourceWorld.provider.dimensionId, ship.coreX, ship.coreZ);
if (distanceSquared > 0) {
AxisAlignedBB axisAlignedBB = celestialObject.getAreaToReachParent();
return String.format(
"Ship is outside planet border, unable to reach space!\n"
+ "Closest transition area is ~%d m away (%d %d %d) to (%d %d %d).",
(int) Math.sqrt(distanceSquared),
(int) axisAlignedBB.minX, (int) axisAlignedBB.minY, (int) axisAlignedBB.minZ,
(int) axisAlignedBB.maxX, (int) axisAlignedBB.maxY, (int) axisAlignedBB.maxZ );
}
// is world available?
final int dimensionIdSpace = celestialObject.parentDimensionId;
targetWorld = MinecraftServer.getServer().worldServerForDimension(dimensionIdSpace);
if (targetWorld == null) {
return "Unable to load Space dimension " + dimensionIdSpace + ", aborting jump.";
}
// update movement vector
VectorI vEntry = celestialObject.getEntryOffset();
moveX = -vEntry.x;
moveZ = -vEntry.z;
} else if (fromSpace) {
CelestialObject celestialObject = StarMapRegistry.getClosestChildCelestialObject(sourceWorld.provider.dimensionId, ship.coreX, ship.coreZ);
// anything defined?
if (celestialObject == null) {
return "No planet exists in this dimension, there's nowhere to land!";
}
// are we in orbit?
final double distanceSquared = celestialObject.getSquareDistanceInParent(sourceWorld.provider.dimensionId, ship.coreX, ship.coreZ);
if (distanceSquared > 0.0D) {
AxisAlignedBB axisAlignedBB = celestialObject.getAreaInParent();
return String.format(
"No planet in range, unable to enter atmosphere!\n"
+ "Closest planet is %d m away (%d %d %d) to (%d %d %d).",
(int) Math.sqrt(distanceSquared),
(int) axisAlignedBB.minX, (int) axisAlignedBB.minY, (int) axisAlignedBB.minZ,
(int) axisAlignedBB.maxX, (int) axisAlignedBB.maxY, (int) axisAlignedBB.maxZ );
}
// validate world availability
targetWorld = MinecraftServer.getServer().worldServerForDimension(celestialObject.dimensionId);
if (targetWorld == null) {
return String.format("Sorry, we can't land here. Dimension %d isn't defined. It might be a decorative planet or a server misconfiguration",
celestialObject.dimensionId);
}
// update movement vector
VectorI vEntry = celestialObject.getEntryOffset();
moveX = vEntry.x;
moveZ = vEntry.z;
} else {
targetWorld = sourceWorld;
}
return null;
}
private void state_moveBlocks() {
LocalProfiler.start("Jump.moveBlocks");
int blocksToMove = Math.min(WarpDriveConfig.G_BLOCKS_PER_TICK, ship.jumpBlocks.length - actualIndexInShip);
@ -1263,7 +1242,7 @@ public class JumpSequencer extends AbstractSequencer {
}
}
if (blockSource != Blocks.air && WarpDrive.proxy.isBlockPlaceCanceled(null, coordCoreAtTarget.posX, coordCoreAtTarget.posY, coordCoreAtTarget.posZ,
if (blockSource != Blocks.air && CommonProxy.isBlockPlaceCanceled(null, coordCoreAtTarget.posX, coordCoreAtTarget.posY, coordCoreAtTarget.posZ,
targetWorld, coordTarget.posX, coordTarget.posY, coordTarget.posZ, blockSource, 0)) {
result.add(x, y, z,
coordTarget.posX,

View file

@ -1,10 +1,13 @@
package cr0s.warpdrive.event;
import cr0s.warpdrive.Commons;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IAirCanister;
import cr0s.warpdrive.api.IBreathingHelmet;
import cr0s.warpdrive.config.Dictionary;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.CelestialObject;
import cr0s.warpdrive.data.StarMapRegistry;
import cr0s.warpdrive.data.VectorI;
import cr0s.warpdrive.item.ItemEnergyWrapper;
import cr0s.warpdrive.world.SpaceTeleporter;
@ -23,6 +26,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.common.DimensionManager;
@ -35,6 +39,12 @@ public class LivingHandler {
private final HashMap<String, Integer> player_cloakTicks;
private static final int CLOAK_CHECK_TIMEOUT_TICKS = 100;
private static final int BORDER_WARNING_RANGE_BLOCKS_SQUARED = 20 * 20;
private static final int BORDER_BYPASS_RANGE_BLOCKS_SQUARED = 32 * 32;
private static final int BORDER_BYPASS_PULL_BACK_BLOCKS = 16;
private static final int BORDER_BYPASS_DAMAGES_PER_TICK = 9000;
private static final int AIR_BLOCK_TICKS = 20;
private static final int AIR_TANK_TICKS = 300;
private static final int AIR_DROWN_TICKS = 20;
@ -56,21 +66,70 @@ public class LivingHandler {
}
EntityLivingBase entity = event.entityLiving;
int x = MathHelper.floor_double(entity.posX);
int y = MathHelper.floor_double(entity.posY);
int z = MathHelper.floor_double(entity.posZ);
final int x = MathHelper.floor_double(entity.posX);
final int y = MathHelper.floor_double(entity.posY);
final int z = MathHelper.floor_double(entity.posZ);
// Instant kill if entity exceeds world's limit
if (WarpDriveConfig.G_SPACE_WORLDBORDER_BLOCKS > 0
&& (Math.abs(x) > WarpDriveConfig.G_SPACE_WORLDBORDER_BLOCKS || Math.abs(z) > WarpDriveConfig.G_SPACE_WORLDBORDER_BLOCKS)) {
CelestialObject celestialObject = StarMapRegistry.getCelestialObject(entity.worldObj, x, z);
if (celestialObject == null) {
// unregistered dimension => exit
return;
}
final double distanceSquared = celestialObject.getSquareDistanceOutsideBorder(entity.worldObj.provider.dimensionId, x, z);
if (distanceSquared <= 0.0D) {
// are we close to the border?
if ( Math.abs(distanceSquared) <= BORDER_WARNING_RANGE_BLOCKS_SQUARED
&& entity instanceof EntityPlayer
&& entity.ticksExisted % 40 == 0) {
Commons.addChatMessage((EntityPlayer) entity,
String.format("§cProximity alert: world border is only %d m away!",
(int) Math.sqrt(Math.abs(distanceSquared))));
}
} else {
if (entity instanceof EntityPlayerMP) {
if (((EntityPlayerMP) entity).capabilities.isCreativeMode) {
if (entity.ticksExisted % 100 == 0) {
Commons.addChatMessage((EntityPlayer) entity,
String.format("§cYou're %d m outside the world border...",
(int) Math.sqrt(Math.abs(distanceSquared))));
}
return;
}
}
entity.attackEntityFrom(DamageSource.outOfWorld, 9000);
return;
// pull back the entity
final double relativeX = entity.posX - celestialObject.dimensionCenterX;
final double relativeZ = entity.posZ - celestialObject.dimensionCenterZ;
final double newAbsoluteX = Math.min(Math.abs(relativeX), Math.max(0.0D, celestialObject.borderRadiusX - BORDER_BYPASS_PULL_BACK_BLOCKS));
final double newAbsoluteZ = Math.min(Math.abs(relativeZ), Math.max(0.0D, celestialObject.borderRadiusZ - BORDER_BYPASS_PULL_BACK_BLOCKS));
final double newEntityX = celestialObject.dimensionCenterX + Math.signum(relativeX) * newAbsoluteX;
final double newEntityY = entity.posY + 0.1D;
final double newEntityZ = celestialObject.dimensionCenterX + Math.signum(relativeZ) * newAbsoluteZ;
// entity.isAirBorne = true;
// @TODO: force client refresh of non-player entities
if (entity instanceof EntityPlayerMP) {
EntityPlayerMP player = (EntityPlayerMP) entity;
player.setPositionAndUpdate(newEntityX, newEntityY, newEntityZ);
} else {
entity.setPosition(newEntityX, newEntityY, newEntityZ);
}
// spam chat if it's a player
if (entity instanceof EntityPlayer && !entity.isDead && entity.deathTime <= 0) {
Commons.addChatMessage((EntityPlayer) entity,
String.format("§4You've reached the world border..."));
}
// delay damage for 'fast moving' players
if (distanceSquared < BORDER_BYPASS_RANGE_BLOCKS_SQUARED) {
// just set on fire
entity.setFire(1);
} else {
// full damage
entity.attackEntityFrom(DamageSource.outOfWorld, BORDER_BYPASS_DAMAGES_PER_TICK);
return;
}
}
if (entity instanceof EntityPlayerMP) {
updatePlayerCloakState(entity);
@ -87,76 +146,98 @@ public class LivingHandler {
}
// If entity is in vacuum, check and start consuming air cells
if (!WarpDrive.starMap.hasAtmosphere(entity.worldObj)) {
// find an air block
VectorI vAirBlock = null;
Block block;
for (VectorI vOffset : vAirOffsets) {
VectorI vPosition = new VectorI(x + vOffset.x, y + vOffset.y, z + vOffset.z);
block = entity.worldObj.getBlock(vPosition.x, vPosition.y, vPosition.z);
if (block.isAssociatedBlock(WarpDrive.blockAir)) {
vAirBlock = vPosition;
break;
if (!celestialObject.hasAtmosphere()) {
if (updateBreathing(entity, x, y, z)) return;
}
// If player falling down, teleport on earth
if (entity.posY < -10.0D) {
CelestialObject celestialObjectChild = StarMapRegistry.getClosestChildCelestialObject(
entity.worldObj.provider.dimensionId, x, z);
// are we actually in orbit?
if ( celestialObjectChild != null
&& !celestialObject.isHyperspace()
&& celestialObjectChild.getSquareDistanceInParent(entity.worldObj.provider.dimensionId, x, z) <= 0.0D ) {
WorldServer worldTarget = DimensionManager.getWorld(celestialObjectChild.dimensionId);
if (worldTarget != null) {
final int yTarget = worldTarget.getActualHeight() + 5;
if (entity instanceof EntityPlayerMP) {
EntityPlayerMP player = (EntityPlayerMP) entity;
player.mcServer.getConfigurationManager().transferPlayerToDimension(player, celestialObjectChild.dimensionId,
new SpaceTeleporter(worldTarget, 0, x, yTarget, z));
if (celestialObjectChild.hasAtmosphere()) {
player.setFire(30);
}
player.setPositionAndUpdate(entity.posX, yTarget, entity.posZ);
player.sendPlayerAbilities();
}
}
} else if (celestialObject.isHyperspace() || celestialObject.isSpace()) {
// player is in space or hyperspace, let's roll around
entity.setPositionAndUpdate(entity.posX, 260.0D, entity.posZ);
}
}
}
private boolean updateBreathing(EntityLivingBase entity, final int x, final int y, final int z) {
// find an air block
VectorI vAirBlock = null;
Block block;
for (VectorI vOffset : vAirOffsets) {
VectorI vPosition = new VectorI(x + vOffset.x, y + vOffset.y, z + vOffset.z);
block = entity.worldObj.getBlock(vPosition.x, vPosition.y, vPosition.z);
if (block.isAssociatedBlock(WarpDrive.blockAir)) {
vAirBlock = vPosition;
break;
}
}
final boolean notInVacuum = vAirBlock != null;
Integer air;
if (notInVacuum) {// No atmosphere with air blocks
air = entity_airBlock.get(entity.getEntityId());
if (air == null) {
entity_airBlock.put(entity.getEntityId(), AIR_BLOCK_TICKS);
} else if (air <= 1) {// time elapsed => consume air block
entity_airBlock.put(entity.getEntityId(), AIR_BLOCK_TICKS);
int metadata = entity.worldObj.getBlockMetadata(vAirBlock.x, vAirBlock.y, vAirBlock.z);
if (metadata > 0 && metadata < 15) {
entity.worldObj.setBlockMetadataWithNotify(vAirBlock.x, vAirBlock.y, vAirBlock.z, metadata - 1, 2);
}
} else {
entity_airBlock.put(entity.getEntityId(), air - 1);
}
boolean notInVacuum = vAirBlock != null;
Integer air;
if (notInVacuum) {// In space with air blocks
} else {// No atmosphere without air blocks
// Damage entity if in vacuum without protection
if (entity instanceof EntityPlayerMP) {
air = entity_airBlock.get(entity.getEntityId());
if (air == null) {
entity_airBlock.put(entity.getEntityId(), AIR_BLOCK_TICKS);
} else if (air <= 1) {// time elapsed => consume air block
entity_airBlock.put(entity.getEntityId(), AIR_BLOCK_TICKS);
int metadata = entity.worldObj.getBlockMetadata(vAirBlock.x, vAirBlock.y, vAirBlock.z);
if (metadata > 0 && metadata < 15) {
entity.worldObj.setBlockMetadataWithNotify(vAirBlock.x, vAirBlock.y, vAirBlock.z, metadata - 1, 2);
}
} else {
if (air != null && air > 0) {
entity_airBlock.put(entity.getEntityId(), air - 1);
return true;
}
} else {// In space without air blocks
// Damage entity if in vacuum without protection
if (entity instanceof EntityPlayerMP) {
air = entity_airBlock.get(entity.getEntityId());
if (air != null && air > 0) {
entity_airBlock.put(entity.getEntityId(), air - 1);
return;
}
EntityPlayerMP player = (EntityPlayerMP) entity;
String playerName = player.getCommandSenderName();
air = player_airTank.get(playerName);
boolean hasHelmet = false;
ItemStack helmetStack = player.getCurrentArmor(3);
if (helmetStack != null) {
Item itemHelmet = helmetStack.getItem();
if (itemHelmet instanceof IBreathingHelmet) {
IBreathingHelmet breathingHelmet = (IBreathingHelmet) itemHelmet;
int airTicks = breathingHelmet.ticksPerCanDamage();
if (breathingHelmet.canBreath(player)) {
hasHelmet = true;
if (air == null) {// new player in space => grace period
player_airTank.put(playerName, airTicks);
} else if (air <= 1) {
if (breathingHelmet.removeAir(player) || consumeAirCanister(player)) {
player_airTank.put(playerName, airTicks);
} else {
hasHelmet = false;
}
} else {
player_airTank.put(playerName, air - 1);
}
}
}
if (Dictionary.ITEMS_BREATHING_HELMET.contains(itemHelmet)) {
EntityPlayerMP player = (EntityPlayerMP) entity;
String playerName = player.getCommandSenderName();
air = player_airTank.get(playerName);
boolean hasHelmet = false;
ItemStack helmetStack = player.getCurrentArmor(3);
if (helmetStack != null) {
Item itemHelmet = helmetStack.getItem();
if (itemHelmet instanceof IBreathingHelmet) {
IBreathingHelmet breathingHelmet = (IBreathingHelmet) itemHelmet;
int airTicks = breathingHelmet.ticksPerCanDamage();
if (breathingHelmet.canBreath(player)) {
hasHelmet = true;
if (air == null) {// new player in space => grace period
player_airTank.put(playerName, AIR_TANK_TICKS);
player_airTank.put(playerName, airTicks);
} else if (air <= 1) {
if (consumeAirCanister(player)) {
player_airTank.put(playerName, AIR_TANK_TICKS);
if (breathingHelmet.removeAir(player) || consumeAirCanister(player)) {
player_airTank.put(playerName, airTicks);
} else {
hasHelmet = false;
}
@ -165,32 +246,39 @@ public class LivingHandler {
}
}
}
if (!hasHelmet) {
if (Dictionary.ITEMS_BREATHING_HELMET.contains(itemHelmet)) {
hasHelmet = true;
if (air == null) {// new player in space => grace period
player_airTank.put(playerName, AIR_TANK_TICKS);
} else if (air <= 1) {
player_airTank.put(playerName, AIR_DROWN_TICKS);
entity.attackEntityFrom(WarpDrive.damageAsphyxia, 2.0F);
if (consumeAirCanister(player)) {
player_airTank.put(playerName, AIR_TANK_TICKS);
} else {
hasHelmet = false;
}
} else {
player_airTank.put(playerName, air - 1);
}
}
// If player falling down, teleport on earth
if (entity.posY < -10.0D) {
player.mcServer.getConfigurationManager().transferPlayerToDimension(player, 0,
new SpaceTeleporter(DimensionManager.getWorld(WarpDriveConfig.G_SPACE_DIMENSION_ID), 0, x, 250, z));
player.setFire(30);
player.setPositionAndUpdate(entity.posX, 250.0D, entity.posZ);
player.sendPlayerAbilities();
}
} else {// (in space, no air block and not a player)
entity_airBlock.put(entity.getEntityId(), 0);
entity.attackEntityFrom(WarpDrive.damageAsphyxia, 2.0F);
}
if (!hasHelmet) {
if (air == null) {// new player in space => grace period
player_airTank.put(playerName, AIR_TANK_TICKS);
} else if (air <= 1) {
player_airTank.put(playerName, AIR_DROWN_TICKS);
entity.attackEntityFrom(WarpDrive.damageAsphyxia, 2.0F);
} else {
player_airTank.put(playerName, air - 1);
}
}
} else {// (in space, no air block and not a player)
entity_airBlock.put(entity.getEntityId(), 0);
entity.attackEntityFrom(WarpDrive.damageAsphyxia, 2.0F);
}
}
return false;
}
private void updatePlayerCloakState(EntityLivingBase entity) {

View file

@ -2,7 +2,7 @@ package cr0s.warpdrive.render;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.Planet;
import cr0s.warpdrive.data.CelestialObject;
import java.util.Random;
@ -30,9 +30,11 @@ public class RenderSpaceSky extends IRenderHandler {
}
private static final ResourceLocation[] texturePlanets = {
new ResourceLocation("warpdrive:textures/celestial/planet_green.png"),
new ResourceLocation("warpdrive:textures/celestial/planet_yellow.png"),
new ResourceLocation("warpdrive:textures/celestial/planet_red.png")
new ResourceLocation("warpdrive:textures/celestial/planet_icy.png"),
new ResourceLocation("warpdrive:textures/celestial/planet_magma.png"),
new ResourceLocation("warpdrive:textures/celestial/planet_metallic.png"),
new ResourceLocation("warpdrive:textures/celestial/planet_oceanic.png"),
new ResourceLocation("warpdrive:textures/celestial/planet_temperate.png")
};
private static final ResourceLocation textureStar = new ResourceLocation("warpdrive:textures/celestial/star_yellow.png");
@ -84,7 +86,9 @@ public class RenderSpaceSky extends IRenderHandler {
@Override
public void render(float partialTicks, WorldClient world, Minecraft mc) {
boolean isSpace = world.provider == null || WarpDrive.starMap.isInSpace(world);
final Vec3 playerCoordinates = mc.thePlayer.getPosition(partialTicks);
final boolean isSpace = world.provider == null
|| WarpDrive.starMap.isInSpace(world, (int) playerCoordinates.xCoord, (int) playerCoordinates.zCoord);
final Tessellator tessellator = Tessellator.instance;
@ -160,7 +164,7 @@ public class RenderSpaceSky extends IRenderHandler {
GL11.glPopMatrix();
}
// Planet
// CelestialObject
/*
{
GL11.glPushMatrix();
@ -187,9 +191,8 @@ public class RenderSpaceSky extends IRenderHandler {
/**/
// Planets
Vec3 playerCoordinates = mc.thePlayer.getPosition(partialTicks);
for(Planet planet : WarpDriveConfig.PLANETS) {
renderPlanet(tessellator, planet, isSpace, playerCoordinates);
for(CelestialObject celestialObject : WarpDriveConfig.celestialObjects) {
renderCelestialObject(tessellator, celestialObject, isSpace, mc.thePlayer.getEntityWorld().provider.dimensionId, playerCoordinates);
}
// final double playerAltitude = mc.thePlayer.getPosition(partialTicks).yCoord - world.getHorizon();
@ -256,11 +259,16 @@ public class RenderSpaceSky extends IRenderHandler {
static final double PLANET_FAR = 1786.0D;
static final double PLANET_APPROACHING = 512.0D;
static final double PLANET_ORBIT = 128.0D;
private static void renderPlanet(Tessellator tessellator, final Planet planet, final boolean isSpace, final Vec3 vec3Player) {
final double planetX = planet.spaceCenterX - vec3Player.xCoord;
final double planetZ = planet.spaceCenterZ - vec3Player.zCoord;
final double distanceToBorder = planet.isValidFromSpace((int) vec3Player.xCoord, (int) vec3Player.zCoord);
final double distanceToCenter = Math.sqrt(planetX * planetX + planetZ * planetZ);
private static void renderCelestialObject(Tessellator tessellator, final CelestialObject celestialObject, final boolean isSpace, final int dimensionId, final Vec3 vec3Player) {
// @TODO compute relative coordinates for rendering on celestialObject
if (dimensionId != celestialObject.parentDimensionId) {
return;
}
final double distanceToCenterX = celestialObject.parentCenterX - vec3Player.xCoord;
final double distanceToCenterZ = celestialObject.parentCenterZ - vec3Player.zCoord;
final double distanceToBorder = Math.sqrt(Math.max(0, celestialObject.getSquareDistanceInParent(dimensionId, vec3Player.xCoord, vec3Player.zCoord)));
final double distanceToCenter = Math.sqrt(distanceToCenterX * distanceToCenterX + distanceToCenterZ * distanceToCenterZ);
// transition values
// distance far approaching orbit
@ -273,33 +281,33 @@ public class RenderSpaceSky extends IRenderHandler {
final double transitionApproaching = (Math.max(PLANET_ORBIT, Math.min(PLANET_APPROACHING, distanceToBorder)) - PLANET_ORBIT) / (PLANET_APPROACHING - PLANET_ORBIT);
final double transitionOrbit = Math.max(0.0D, Math.min(PLANET_ORBIT, distanceToBorder)) / PLANET_ORBIT;
// relative position above planet
final double offsetX = (1.0 - transitionOrbit) * (planet.borderSizeX - planetX) / planet.borderSizeX;
final double offsetZ = (1.0 - transitionOrbit) * (planet.borderSizeZ - planetZ) / planet.borderSizeZ;
// relative position above celestialObject
final double offsetX = (1.0 - transitionOrbit) * (celestialObject.borderRadiusX - distanceToCenterX) / celestialObject.borderRadiusX;
final double offsetZ = (1.0 - transitionOrbit) * (celestialObject.borderRadiusZ - distanceToCenterZ) / celestialObject.borderRadiusZ;
// simulating a non-planar universe...
final double planetY_far = (planet.dimensionId + 99 % 100 - 50) * Math.log(distanceToCenter) / 4.0D;
final double planetY_far = (celestialObject.dimensionId + 99 % 100 - 50) * Math.log(distanceToCenter) / 4.0D;
final double planetY = planetY_far * transitionApproaching;
// render range is only used for Z-ordering
final double renderRange = 180.0D + 10.0D * (distanceToCenter / WarpDriveConfig.G_SPACE_WORLDBORDER_BLOCKS);
final double renderRange = 180.0D + 10.0D * (distanceToCenter / Math.max(celestialObject.borderRadiusX, celestialObject.borderRadiusZ));
// render size is 1 at space border range
// render size is 10 at approaching range
// render size is 90 at orbit range
// render size is min(1000, planet border) at orbit range
final double renderSize = 100.0D / 1000.0D * Math.min(1000.0D, Math.max(planet.borderSizeX, planet.borderSizeZ)) * (1.0D - transitionOrbit)
// render size is min(1000, celestialObject border) at orbit range
final double renderSize = 100.0D / 1000.0D * Math.min(1000.0D, Math.max(celestialObject.borderRadiusX, celestialObject.borderRadiusZ)) * (1.0D - transitionOrbit)
+ 50.0D * (transitionOrbit < 1.0D ? transitionOrbit : (1.0D - transitionApproaching))
+ 5.0D * (transitionApproaching < 1.0D ? transitionApproaching : (1.0D - transitionFar))
+ 1.0D * transitionFar;
// angles
@SuppressWarnings("SuspiciousNameCombination")
final double angleH = Math.atan2(planetX, planetZ);
final double angleH = Math.atan2(distanceToCenterX, distanceToCenterZ);
@SuppressWarnings("SuspiciousNameCombination")
final double angleV_far = Math.atan2(Math.sqrt(planetX * planetX + planetZ * planetZ), planetY);
final double angleV_far = Math.atan2(Math.sqrt(distanceToCenterX * distanceToCenterX + distanceToCenterZ * distanceToCenterZ), planetY);
final double angleV = Math.PI * (1.0D - transitionOrbit) + angleV_far * transitionOrbit;
final double angleS = 0.15D * planet.dimensionId * transitionApproaching; // + (world.getTotalWorldTime() + partialTicks) * Math.PI / 6000.0D;
final double angleS = 0.15D * celestialObject.dimensionId * transitionApproaching; // + (world.getTotalWorldTime() + partialTicks) * Math.PI / 6000.0D;
// pre-computations
final double sinH = Math.sin(angleH);
@ -311,7 +319,7 @@ public class RenderSpaceSky extends IRenderHandler {
GL11.glPushMatrix();
GL11.glColor4f(1.0F, 1.0F, 1.0F, isSpace ? 1.0F : 0.2F);
FMLClientHandler.instance().getClient().renderEngine.bindTexture(texturePlanets[Math.abs(planet.dimensionId) % 3]);
FMLClientHandler.instance().getClient().renderEngine.bindTexture(texturePlanets[Math.abs(celestialObject.dimensionId) % texturePlanets.length]);
tessellator.startDrawingQuads();
for (int indexVertex = 0; indexVertex < 4; indexVertex++) {
final double offset1 = ((indexVertex & 2) - 1) * renderSize;

View file

@ -1,7 +1,5 @@
package cr0s.warpdrive.world;
import cr0s.warpdrive.config.WarpDriveConfig;
import java.util.Random;
import net.minecraft.world.World;
@ -9,11 +7,10 @@ import net.minecraft.world.chunk.IChunkProvider;
import cpw.mods.fml.common.IWorldGenerator;
public class HyperSpaceWorldGenerator implements IWorldGenerator {
@Override
public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) {
if (world.provider.dimensionId != WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID) {
if (world.provider.dimensionId != 0) {
// ...
}
}

View file

@ -1,8 +1,7 @@
package cr0s.warpdrive.world;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.StarMapRegistry;
import cr0s.warpdrive.render.RenderBlank;
import cr0s.warpdrive.render.RenderSpaceSky;
@ -129,7 +128,11 @@ public class HyperSpaceWorldProvider extends WorldProvider {
@Override
public int getRespawnDimension(EntityPlayerMP player) {
return WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID;
if (player == null || player.worldObj == null) {
WarpDrive.logger.error("Invalid player passed to getRespawnDimension: " + player);
return 0;
}
return StarMapRegistry.getHyperspaceDimensionId(player.worldObj, (int) player.posX, (int) player.posZ);
}
@Override

View file

@ -8,6 +8,8 @@ import cr0s.warpdrive.config.structures.AbstractStructure;
import cr0s.warpdrive.config.structures.Orb.OrbShell;
import cr0s.warpdrive.config.structures.OrbInstance;
import cr0s.warpdrive.config.structures.StructureManager;
import cr0s.warpdrive.data.CelestialObject;
import cr0s.warpdrive.data.StarMapRegistry;
import java.util.Random;
@ -21,28 +23,42 @@ public class SpaceWorldGenerator implements IWorldGenerator {
@Override
public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) {
try {
if (!WarpDrive.starMap.isInSpace(world)) {
final int x = (chunkX * 16) + (5 - random.nextInt(10));
final int z = (chunkZ * 16) + (5 - random.nextInt(10));
CelestialObject celestialObject = StarMapRegistry.getCelestialObject(world, x, z);
if (celestialObject == null) {
// as observed on 1.7.10: during world transition, the generator from the previous world is still called
return;
}
int x = (chunkX * 16) + (5 - random.nextInt(10));
int z = (chunkZ * 16) + (5 - random.nextInt(10));
if (WarpDriveConfig.G_SPACE_WORLDBORDER_BLOCKS > 0 && (Math.abs(x) > WarpDriveConfig.G_SPACE_WORLDBORDER_BLOCKS || Math.abs(z) > WarpDriveConfig.G_SPACE_WORLDBORDER_BLOCKS)) {
if ( celestialObject.borderRadiusX > 0
&& ( Math.abs(x - celestialObject.dimensionCenterX) > celestialObject.borderRadiusX
|| Math.abs(z - celestialObject.dimensionCenterZ) > celestialObject.borderRadiusZ ) ) {
return;
}
int y = WarpDriveConfig.SPACE_GENERATOR_Y_MIN_CENTER + random.nextInt(WarpDriveConfig.SPACE_GENERATOR_Y_MAX_CENTER - WarpDriveConfig.SPACE_GENERATOR_Y_MIN_CENTER);
// Moon setup
if (random.nextInt(800) == 1) {
int y = WarpDriveConfig.SPACE_GENERATOR_Y_MIN_CENTER
+ random.nextInt(WarpDriveConfig.SPACE_GENERATOR_Y_MAX_CENTER - WarpDriveConfig.SPACE_GENERATOR_Y_MIN_CENTER);
String group = celestialObject.getRandomGeneration(random);
if (group == null) {
return;
}
switch (group) {
case "moon":
AbstractStructure moon = StructureManager.getStructure(world.rand, StructureManager.GROUP_MOONS, null);
moon.generate(world, world.rand, x, y, z);
break;
// Simple asteroids
} else if (random.nextInt(150) == 1) {
AbstractStructure moon = StructureManager.getStructure(world.rand, StructureManager.GROUP_ASTEROIDS, null);
moon.generate(world, world.rand, x, y, z);
case "asteroid":
AbstractStructure asteroid = StructureManager.getStructure(world.rand, StructureManager.GROUP_ASTEROIDS, null);
asteroid.generate(world, world.rand, x, y, z);
break;
// Random asteroid of block
} else if (random.nextInt(600) == 1) {// Asteroid field
case "asteroidField":
generateAsteroidField(world, x, y, z);
break;
default:
break;
}
} catch (Exception exception) {

View file

@ -1,7 +1,7 @@
package cr0s.warpdrive.world;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.data.StarMapRegistry;
import cr0s.warpdrive.render.RenderBlank;
import cr0s.warpdrive.render.RenderSpaceSky;
@ -128,7 +128,11 @@ public class SpaceWorldProvider extends WorldProvider {
@Override
public int getRespawnDimension(EntityPlayerMP player) {
return 0; // re-spawn on Earth
if (player == null || player.worldObj == null) {
WarpDrive.logger.error("Invalid player passed to getRespawnDimension: " + player);
return 0;
}
return StarMapRegistry.getSpaceDimensionId(player.worldObj, (int) player.posX, (int) player.posZ);
}
@Override