Added transporter containment and scanner (wip)
Refactored MovingEntity to support transporter Added ITransporterCore API
This commit is contained in:
parent
07b23d9de7
commit
7a567a8722
23 changed files with 2044 additions and 1075 deletions
|
@ -71,11 +71,13 @@ import cr0s.warpdrive.block.hull.ItemBlockHullSlab;
|
|||
import cr0s.warpdrive.block.movement.BlockLift;
|
||||
import cr0s.warpdrive.block.movement.BlockShipController;
|
||||
import cr0s.warpdrive.block.movement.BlockShipCore;
|
||||
import cr0s.warpdrive.block.movement.BlockTransporter;
|
||||
import cr0s.warpdrive.block.movement.BlockTransporterCore;
|
||||
import cr0s.warpdrive.block.movement.BlockTransporterContainment;
|
||||
import cr0s.warpdrive.block.movement.BlockTransporterScanner;
|
||||
import cr0s.warpdrive.block.movement.TileEntityLift;
|
||||
import cr0s.warpdrive.block.movement.TileEntityShipController;
|
||||
import cr0s.warpdrive.block.movement.TileEntityShipCore;
|
||||
import cr0s.warpdrive.block.movement.TileEntityTransporter;
|
||||
import cr0s.warpdrive.block.movement.TileEntityTransporterCore;
|
||||
import cr0s.warpdrive.block.breathing.BlockAir;
|
||||
import cr0s.warpdrive.block.passive.BlockBedrockGlass;
|
||||
import cr0s.warpdrive.block.passive.BlockDecorative;
|
||||
|
@ -206,7 +208,9 @@ public class WarpDrive {
|
|||
public static Block blockShipScanner;
|
||||
public static Block blockCloakingCore;
|
||||
public static Block blockCloakingCoil;
|
||||
public static Block blockTransporter;
|
||||
public static Block blockTransporterCore;
|
||||
public static Block blockTransporterContainment;
|
||||
public static Block blockTransporterScanner;
|
||||
public static Block blockIC2reactorLaserMonitor;
|
||||
public static Block blockEnanReactorCore;
|
||||
public static Block blockEnanReactorLaser;
|
||||
|
@ -464,11 +468,21 @@ public class WarpDrive {
|
|||
|
||||
GameRegistry.registerBlock(blockCloakingCoil, ItemBlockAbstractBase.class, "blockCloakingCoil");
|
||||
|
||||
// TRANSPORTER
|
||||
blockTransporter = new BlockTransporter();
|
||||
// TRANSPORTER CORE
|
||||
blockTransporterCore = new BlockTransporterCore();
|
||||
|
||||
GameRegistry.registerBlock(blockTransporter, ItemBlockAbstractBase.class, "blockTransporter");
|
||||
GameRegistry.registerTileEntity(TileEntityTransporter.class, MODID + ":blockTransporter");
|
||||
GameRegistry.registerBlock(blockTransporterCore, ItemBlockAbstractBase.class, "blockTransporterCore");
|
||||
GameRegistry.registerTileEntity(TileEntityTransporterCore.class, MODID + ":blockTransporterCore");
|
||||
|
||||
// TRANSPORTER CONTAINMENT
|
||||
blockTransporterContainment = new BlockTransporterContainment();
|
||||
|
||||
GameRegistry.registerBlock(blockTransporterContainment, ItemBlockAbstractBase.class, "blockTransporterContainment");
|
||||
|
||||
// TRANSPORTER SCANNER
|
||||
blockTransporterScanner = new BlockTransporterScanner();
|
||||
|
||||
GameRegistry.registerBlock(blockTransporterScanner, ItemBlockAbstractBase.class, "blockTransporterScanner");
|
||||
|
||||
// IC2 REACTOR LASER MONITOR
|
||||
if (WarpDriveConfig.isIndustrialCraft2Loaded) {
|
||||
|
@ -850,7 +864,8 @@ public class WarpDrive {
|
|||
mapping.remap(Item.getItemFromBlock(blockTransportBeacon));
|
||||
break;
|
||||
case "WarpDrive:transporter":
|
||||
mapping.remap(Item.getItemFromBlock(blockTransporter));
|
||||
case "WarpDrive:blockTransporter":
|
||||
mapping.remap(Item.getItemFromBlock(blockTransporterCore));
|
||||
break;
|
||||
case "WarpDrive:warpCore":
|
||||
mapping.remap(Item.getItemFromBlock(blockShipCore));
|
||||
|
@ -944,7 +959,8 @@ public class WarpDrive {
|
|||
mapping.remap(blockTransportBeacon);
|
||||
break;
|
||||
case "WarpDrive:transporter":
|
||||
mapping.remap(blockTransporter);
|
||||
case "WarpDrive:blockTransporter":
|
||||
mapping.remap(blockTransporterCore);
|
||||
break;
|
||||
case "WarpDrive:warpCore":
|
||||
mapping.remap(blockShipCore);
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package cr0s.warpdrive.api.computer;
|
||||
|
||||
import cr0s.warpdrive.api.IBeamFrequency;
|
||||
|
||||
public interface ITransporterCore extends IEnergy, IBeamFrequency {
|
||||
|
||||
Object[] transporterName(final Object[] arguments);
|
||||
|
||||
Object[] enable(final Object[] arguments);
|
||||
|
||||
Object[] state();
|
||||
|
||||
Object[] remoteLocation(final Object[] arguments);
|
||||
|
||||
Object[] lock(final Object[] arguments);
|
||||
|
||||
Object[] energyFactor(final Object[] arguments);
|
||||
|
||||
Object[] getLockStrength();
|
||||
|
||||
Object[] getEnergyRequired();
|
||||
|
||||
Object[] energize(final Object[] arguments);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package cr0s.warpdrive.block.movement;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import cr0s.warpdrive.block.BlockAbstractBase;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IIconRegister;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
public class BlockTransporterContainment extends BlockAbstractBase {
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
private IIcon[] iconBuffer;
|
||||
|
||||
public BlockTransporterContainment() {
|
||||
super(Material.iron);
|
||||
setBlockName("warpdrive.movement.transporter_containment");
|
||||
setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public void registerBlockIcons(final IIconRegister iconRegister) {
|
||||
iconBuffer = new IIcon[3];
|
||||
// Solid textures
|
||||
iconBuffer[0] = iconRegister.registerIcon("warpdrive:movement/transporter_containment-bottom");
|
||||
iconBuffer[1] = iconRegister.registerIcon("warpdrive:movement/transporter_containment-top");
|
||||
iconBuffer[2] = iconRegister.registerIcon("warpdrive:movement/transporter_containment-side");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpaqueCube() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNormalCube() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideSolid(final IBlockAccess blockAccess, final int x, final int y, final int z, final ForgeDirection side) {
|
||||
return side == ForgeDirection.DOWN;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public IIcon getIcon(int side, int metadata) {
|
||||
if (side == 0 || side == 1) {
|
||||
return iconBuffer[side];
|
||||
}
|
||||
|
||||
return iconBuffer[2];
|
||||
}
|
||||
}
|
|
@ -13,40 +13,40 @@ import net.minecraft.world.World;
|
|||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockTransporter extends BlockAbstractContainer {
|
||||
public class BlockTransporterCore extends BlockAbstractContainer {
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
private IIcon[] iconBuffer;
|
||||
|
||||
public BlockTransporter() {
|
||||
public BlockTransporterCore() {
|
||||
super(Material.iron);
|
||||
setBlockName("warpdrive.movement.Transporter");
|
||||
setBlockName("warpdrive.movement.transporter_core");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createNewTileEntity(final World world, final int metadata) {
|
||||
return new TileEntityTransporter();
|
||||
return new TileEntityTransporterCore();
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public void registerBlockIcons(final IIconRegister iconRegister) {
|
||||
iconBuffer = new IIcon[4];
|
||||
// Solid textures
|
||||
iconBuffer[0] = iconRegister.registerIcon("warpdrive:movement/transporter-bottom");
|
||||
iconBuffer[1] = iconRegister.registerIcon("warpdrive:movement/transporter-top");
|
||||
iconBuffer[2] = iconRegister.registerIcon("warpdrive:movement/transporter-side_inactive");
|
||||
iconBuffer[3] = iconRegister.registerIcon("warpdrive:movement/transporter-side_active");
|
||||
iconBuffer = new IIcon[5];
|
||||
iconBuffer[0] = iconRegister.registerIcon("warpdrive:movement/transporter_core-bottom_top");
|
||||
iconBuffer[1] = iconRegister.registerIcon("warpdrive:movement/transporter_core-side_invalid");
|
||||
iconBuffer[2] = iconRegister.registerIcon("warpdrive:movement/transporter_core-side_offline");
|
||||
iconBuffer[3] = iconRegister.registerIcon("warpdrive:movement/transporter_core-side_low_power");
|
||||
iconBuffer[4] = iconRegister.registerIcon("warpdrive:movement/transporter_core-side_online");
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public IIcon getIcon(int side, int metadata) {
|
||||
if (side == 0 || side == 1) {
|
||||
return iconBuffer[side];
|
||||
return iconBuffer[0];
|
||||
}
|
||||
|
||||
return iconBuffer[metadata == 0 ? 2 : 3];
|
||||
return iconBuffer[(metadata % 4) + 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,8 +58,8 @@ public class BlockTransporter extends BlockAbstractContainer {
|
|||
|
||||
if (entityPlayer.getHeldItem() == null) {
|
||||
final TileEntity tileEntity = world.getTileEntity(x, y, z);
|
||||
if (tileEntity instanceof TileEntityTransporter) {
|
||||
Commons.addChatMessage(entityPlayer, ((TileEntityTransporter) tileEntity).getStatus());
|
||||
if (tileEntity instanceof TileEntityTransporterCore) {
|
||||
Commons.addChatMessage(entityPlayer, ((TileEntityTransporterCore) tileEntity).getStatus());
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package cr0s.warpdrive.block.movement;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import cr0s.warpdrive.block.BlockAbstractBase;
|
||||
import cr0s.warpdrive.data.VectorI;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IIconRegister;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
public class BlockTransporterScanner extends BlockAbstractBase {
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
private IIcon[] iconBuffer;
|
||||
|
||||
public BlockTransporterScanner() {
|
||||
super(Material.iron);
|
||||
setBlockName("warpdrive.movement.transporter_scanner");
|
||||
setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
|
||||
setLightOpacity(255);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public void registerBlockIcons(final IIconRegister iconRegister) {
|
||||
iconBuffer = new IIcon[4];
|
||||
// Solid textures
|
||||
iconBuffer[0] = iconRegister.registerIcon("warpdrive:movement/transporter_scanner-bottom");
|
||||
iconBuffer[1] = iconRegister.registerIcon("warpdrive:movement/transporter_scanner-side");
|
||||
iconBuffer[2] = iconRegister.registerIcon("warpdrive:movement/transporter_scanner-top_offline");
|
||||
iconBuffer[3] = iconRegister.registerIcon("warpdrive:movement/transporter_scanner-top_online");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpaqueCube() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNormalCube() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideSolid(final IBlockAccess blockAccess, final int x, final int y, final int z, final ForgeDirection side) {
|
||||
return side == ForgeDirection.DOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightValue(final IBlockAccess blockAccess, final int x, final int y, final int z) {
|
||||
final int metadata = blockAccess.getBlockMetadata(x, y, z);
|
||||
return metadata == 0 ? 0 : 6;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public IIcon getIcon(int side, int metadata) {
|
||||
if (side == 0) {
|
||||
return iconBuffer[0];
|
||||
}
|
||||
if (side != 1) {
|
||||
return iconBuffer[1];
|
||||
}
|
||||
|
||||
return iconBuffer[metadata == 0 ? 2 : 3];
|
||||
}
|
||||
|
||||
public boolean isValid(final World worldObj, final VectorI vScanner) {
|
||||
boolean isScannerPosition = true;
|
||||
for (int x = vScanner.x - 1; x <= vScanner.x + 1; x++) {
|
||||
for (int z = vScanner.z - 1; z <= vScanner.z + 1; z++) {
|
||||
// check base block is containment or scanner in checker pattern
|
||||
final Block blockBase = worldObj.getBlock(x, vScanner.y, z);
|
||||
if ( !(blockBase instanceof BlockTransporterContainment)
|
||||
&& (!isScannerPosition || !(blockBase instanceof BlockTransporterScanner)) ) {
|
||||
return false;
|
||||
}
|
||||
isScannerPosition = !isScannerPosition;
|
||||
|
||||
// check 2 above blocks are air
|
||||
if (!worldObj.isAirBlock(x, vScanner.y + 1, z)) {
|
||||
return false;
|
||||
}
|
||||
if (!worldObj.isAirBlock(x, vScanner.y + 2, z)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,893 +0,0 @@
|
|||
package cr0s.warpdrive.block.movement;
|
||||
|
||||
import cr0s.warpdrive.Commons;
|
||||
import cr0s.warpdrive.WarpDrive;
|
||||
import cr0s.warpdrive.api.IBeamFrequency;
|
||||
import cr0s.warpdrive.block.TileEntityAbstractEnergy;
|
||||
import cr0s.warpdrive.block.forcefield.BlockForceField;
|
||||
import cr0s.warpdrive.block.forcefield.TileEntityForceField;
|
||||
import cr0s.warpdrive.block.passive.BlockTransportBeacon;
|
||||
import cr0s.warpdrive.config.Dictionary;
|
||||
import cr0s.warpdrive.config.WarpDriveConfig;
|
||||
import cr0s.warpdrive.data.EnumComponentType;
|
||||
import cr0s.warpdrive.data.EnumTransporterState;
|
||||
import cr0s.warpdrive.data.ForceFieldSetup;
|
||||
import cr0s.warpdrive.data.Vector3;
|
||||
import cr0s.warpdrive.data.VectorI;
|
||||
import cr0s.warpdrive.network.PacketHandler;
|
||||
import dan200.computercraft.api.lua.ILuaContext;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import li.cil.oc.api.machine.Arguments;
|
||||
import li.cil.oc.api.machine.Callback;
|
||||
import li.cil.oc.api.machine.Context;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.particle.EntityFX;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.potion.Potion;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.StatCollector;
|
||||
|
||||
import cpw.mods.fml.common.Optional;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
public class TileEntityTransporter extends TileEntityAbstractEnergy implements IBeamFrequency {
|
||||
|
||||
// persistent properties
|
||||
private int beamFrequency = -1;
|
||||
private boolean isEnabled = true;
|
||||
private boolean isLockRequested = false;
|
||||
private boolean isEnergizeRequested = false;
|
||||
private VectorI vSource_relative = new VectorI();
|
||||
private VectorI vDestination_relative = new VectorI();
|
||||
private double energyFactor = 1.0D;
|
||||
private double lockStrengthActual = 0.0D;
|
||||
private int tickCooldown = 0;
|
||||
private EnumTransporterState transporterState = EnumTransporterState.DISABLED;
|
||||
|
||||
// computed properties
|
||||
private boolean isConnected = false;
|
||||
private int energyCostForTransfer = 0;
|
||||
private double lockStrengthOptimal = -1.0D;
|
||||
private double lockStrengthSpeed = 0.0D;
|
||||
private boolean isJammed = false;
|
||||
private VectorI vSource_absolute = new VectorI();
|
||||
private VectorI vDestination_absolute = new VectorI();
|
||||
private WeakReference<Entity> weakEntity = null;
|
||||
private Vector3 v3EntityPosition = null;
|
||||
private int tickEnergizing = 0;
|
||||
|
||||
public TileEntityTransporter() {
|
||||
super();
|
||||
|
||||
IC2_sinkTier = 2;
|
||||
IC2_sourceTier = 2;
|
||||
|
||||
peripheralName = "warpdriveTransporter";
|
||||
addMethods(new String[] {
|
||||
"beamFrequency",
|
||||
"enable",
|
||||
"source",
|
||||
"destination",
|
||||
"lock",
|
||||
"energyFactor",
|
||||
"getLockStrength",
|
||||
"getEnergyRequired",
|
||||
"energize",
|
||||
"upgrades"
|
||||
});
|
||||
|
||||
setUpgradeMaxCount(EnumComponentType.ENDER_CRYSTAL, WarpDriveConfig.TRANSPORTER_RANGE_UPGRADE_MAX_QUANTITY);
|
||||
setUpgradeMaxCount(EnumComponentType.CAPACITIVE_CRYSTAL, WarpDriveConfig.TRANSPORTER_ENERGY_STORED_UPGRADE_MAX_QUANTITY);
|
||||
setUpgradeMaxCount(EnumComponentType.EMERALD_CRYSTAL, WarpDriveConfig.TRANSPORTER_LOCKING_UPGRADE_MAX_QUANTITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFirstUpdateTick() {
|
||||
super.onFirstUpdateTick();
|
||||
updateParameters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEntity() {
|
||||
super.updateEntity();
|
||||
|
||||
if (worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
|
||||
// frequency status
|
||||
isConnected = beamFrequency > 0 && beamFrequency <= IBeamFrequency.BEAM_FREQUENCY_MAX;
|
||||
|
||||
// always cooldown
|
||||
if (tickCooldown > 0) {
|
||||
tickCooldown--;
|
||||
} else {
|
||||
tickCooldown = 0;
|
||||
}
|
||||
|
||||
// consume power and apply general lock strength increase and decay
|
||||
boolean isPowered;
|
||||
if (!isEnabled) {
|
||||
transporterState = EnumTransporterState.DISABLED;
|
||||
isPowered = false;
|
||||
// (lock strength is cleared in state machine)
|
||||
} else {
|
||||
// energy consumption
|
||||
final int energyRequired = getEnergyRequired(transporterState);
|
||||
if (energyRequired > 0) {
|
||||
isPowered = energy_consume(energyRequired, false);
|
||||
if (!isPowered) {
|
||||
transporterState = EnumTransporterState.IDLE;
|
||||
}
|
||||
} else {
|
||||
isPowered = true;
|
||||
}
|
||||
|
||||
// lock strength always decays
|
||||
lockStrengthActual = Math.max(0.0D, lockStrengthActual * WarpDriveConfig.TRANSPORTER_LOCKING_STRENGTH_FACTOR_PER_TICK);
|
||||
|
||||
// lock strength is capped at optimal, increasing when powered
|
||||
// a slight overshoot is added to force convergence
|
||||
if ( isPowered
|
||||
&& ( transporterState == EnumTransporterState.ACQUIRING
|
||||
|| transporterState == EnumTransporterState.ENERGIZING ) ) {
|
||||
final double overshoot = 0.01D;
|
||||
lockStrengthActual = Math.min(lockStrengthOptimal,
|
||||
lockStrengthActual + lockStrengthSpeed * (lockStrengthOptimal - lockStrengthActual + overshoot));
|
||||
}
|
||||
}
|
||||
|
||||
// state feedback
|
||||
final boolean isActive = isEnabled && isConnected && isPowered;
|
||||
updateMetadata(isActive ? 1 : 0);
|
||||
if (isActive && isLockRequested && isJammed) {
|
||||
PacketHandler.sendSpawnParticlePacket(worldObj, "jammed", (byte) 5, new Vector3(this).translate(0.5F),
|
||||
new Vector3(0.0D, 0.0D, 0.0D),
|
||||
1.0F, 1.0F, 1.0F,
|
||||
1.0F, 1.0F, 1.0F,
|
||||
32);
|
||||
}
|
||||
|
||||
// execute state transitions
|
||||
switch (transporterState) {
|
||||
case DISABLED:
|
||||
isLockRequested = false;
|
||||
isEnergizeRequested = false;
|
||||
lockStrengthActual = 0.0D;
|
||||
if (isActive) {
|
||||
transporterState = EnumTransporterState.IDLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case IDLE:
|
||||
if (isLockRequested) {
|
||||
// initial validation before starting acquisition
|
||||
updateParameters();
|
||||
|
||||
if (!isJammed) {
|
||||
transporterState = EnumTransporterState.ACQUIRING;
|
||||
} else {
|
||||
tickCooldown = WarpDriveConfig.TRANSPORTER_JAMMED_COOLDOWN_TICKS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ACQUIRING:
|
||||
if (!isLockRequested) {
|
||||
transporterState = EnumTransporterState.IDLE;
|
||||
|
||||
} else if (isEnergizeRequested) {
|
||||
// final validation in case environment has changed
|
||||
updateParameters();
|
||||
|
||||
if (isJammed) {
|
||||
tickCooldown += WarpDriveConfig.TRANSPORTER_JAMMED_COOLDOWN_TICKS;
|
||||
transporterState = EnumTransporterState.IDLE;
|
||||
} else {
|
||||
// reset entity to grab
|
||||
weakEntity = null;
|
||||
v3EntityPosition = null;
|
||||
|
||||
// consume energy
|
||||
final int energyRequired = getEnergyRequired(transporterState);
|
||||
if (energy_consume(energyRequired, false)) {
|
||||
tickEnergizing = WarpDriveConfig.TRANSPORTER_TRANSFER_WARMUP_TICKS;
|
||||
transporterState = EnumTransporterState.ENERGIZING;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ENERGIZING:
|
||||
// get entity
|
||||
updateEntityToTransfer();
|
||||
if (weakEntity == null) {
|
||||
transporterState = EnumTransporterState.ACQUIRING;
|
||||
isEnergizeRequested = false;
|
||||
tickCooldown = WarpDriveConfig.TRANSPORTER_TRANSFER_COOLDOWN_TICKS;
|
||||
lockStrengthActual = Math.max(0.0D, lockStrengthActual - WarpDriveConfig.TRANSPORTER_TRANSFER_LOCKING_LOST);
|
||||
break;
|
||||
}
|
||||
final Entity entity = weakEntity.get();
|
||||
if (entity == null) {
|
||||
// bad state
|
||||
WarpDrive.logger.info(String.format("%s Entity went missing, retrying next tick...",
|
||||
this));
|
||||
break;
|
||||
}
|
||||
|
||||
// warm-up
|
||||
if (tickEnergizing > 0) {
|
||||
tickEnergizing--;
|
||||
break;
|
||||
}
|
||||
|
||||
// check lock strength
|
||||
if ( lockStrengthActual < 1.0D
|
||||
&& worldObj.rand.nextDouble() > lockStrengthActual ) {
|
||||
if (WarpDriveConfig.LOGGING_TRANSPORTER) {
|
||||
WarpDrive.logger.info(String.format("%s Insufficient lock strength %.3f", this, lockStrengthActual));
|
||||
}
|
||||
applyTeleportationDamages(false, entity, lockStrengthActual);
|
||||
tickCooldown = WarpDriveConfig.TRANSPORTER_TRANSFER_COOLDOWN_TICKS;
|
||||
break;
|
||||
}
|
||||
|
||||
// teleport
|
||||
final Vector3 v3Target = new Vector3(
|
||||
vDestination_absolute.x + entity.posX - vSource_absolute.x,
|
||||
vDestination_absolute.y + entity.posY - vSource_absolute.y,
|
||||
vDestination_absolute.z + entity.posZ - vSource_absolute.z);
|
||||
if (WarpDriveConfig.LOGGING_TRANSPORTER) {
|
||||
WarpDrive.logger.info(String.format("%s Teleporting entity %s to %s",
|
||||
this, entity, v3Target));
|
||||
}
|
||||
Commons.moveEntity(entity, worldObj, v3Target);
|
||||
applyTeleportationDamages(false, entity, lockStrengthActual);
|
||||
tickCooldown = WarpDriveConfig.TRANSPORTER_TRANSFER_COOLDOWN_TICKS;
|
||||
lockStrengthActual = Math.max(0.0D, lockStrengthActual - WarpDriveConfig.TRANSPORTER_TRANSFER_LOCKING_LOST);
|
||||
break;
|
||||
|
||||
default:
|
||||
transporterState = EnumTransporterState.DISABLED;
|
||||
break;
|
||||
}
|
||||
|
||||
// client effects
|
||||
if ( lockStrengthActual > 0.0F
|
||||
|| tickEnergizing > 0
|
||||
|| tickCooldown > 0 ) {
|
||||
final Entity entity = weakEntity == null ? null : weakEntity.get();
|
||||
PacketHandler.sendTransporterEffectPacket(worldObj, vSource_absolute, vDestination_absolute, lockStrengthActual,
|
||||
entity, v3EntityPosition,
|
||||
tickEnergizing, tickCooldown, 64);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusHeader() {
|
||||
return super.getStatusHeader()
|
||||
+ "\n" + StatCollector.translateToLocalFormatted("warpdrive.transporter.status",
|
||||
vSource_absolute.x, vSource_absolute.y, vSource_absolute.z,
|
||||
vDestination_absolute.x, vDestination_absolute.y, vDestination_absolute.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeamFrequency() {
|
||||
return beamFrequency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeamFrequency(final int beamFrequency) {
|
||||
this.beamFrequency = beamFrequency;
|
||||
}
|
||||
|
||||
private class FocusValues {
|
||||
public int countRangeUpgrades;
|
||||
public double strength;
|
||||
public double speed;
|
||||
}
|
||||
|
||||
private void updateParameters() {
|
||||
isJammed = false;
|
||||
|
||||
// check connection
|
||||
if (!isConnected) {
|
||||
isJammed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// check minimum range
|
||||
if (vSource_relative.subtract(vDestination_relative).getMagnitudeSquared() < 2) {
|
||||
isJammed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// compute absolute coordinates
|
||||
vSource_absolute = new VectorI(this).translate(EnumFacing.UP).translate(vSource_relative);
|
||||
vDestination_absolute = new VectorI(this).translate(EnumFacing.UP).translate(vDestination_relative);
|
||||
|
||||
// compute range as max distance between transporter, source and destination
|
||||
final int rangeSource2 = vSource_relative.getMagnitudeSquared();
|
||||
final int rangeDestination2 = vDestination_relative.getMagnitudeSquared();
|
||||
final int rangeDelta2 = vSource_relative.subtract(vDestination_relative).getMagnitudeSquared();
|
||||
final int rangeActual = (int) Math.ceil(Math.sqrt(Math.max(rangeSource2, Math.max(rangeDestination2, rangeDelta2))));
|
||||
|
||||
// compute energy cost from range
|
||||
energyCostForTransfer = (int) Math.ceil(Math.max(0, Commons.interpolate(
|
||||
0,
|
||||
WarpDriveConfig.TRANSPORTER_TRANSFER_ENERGY_AT_MIN_RANGE,
|
||||
WarpDriveConfig.TRANSPORTER_RANGE_BASE_BLOCKS,
|
||||
WarpDriveConfig.TRANSPORTER_TRANSFER_ENERGY_AT_MAX_RANGE,
|
||||
rangeActual)));
|
||||
|
||||
// compute focalization bonuses
|
||||
final FocusValues focusValuesSource = getFocusValueAtCoordinates(vSource_absolute);
|
||||
final FocusValues focusValuesDestination = getFocusValueAtCoordinates(vDestination_absolute);
|
||||
final double focusBoost = energyFactor
|
||||
* WarpDriveConfig.TRANSPORTER_LOCKING_STRENGTH_BONUS_AT_MAX_ENERGY_FACTOR
|
||||
/ WarpDriveConfig.TRANSPORTER_TRANSFER_ENERGY_FACTOR_MAX;
|
||||
lockStrengthOptimal = (focusValuesSource.strength + focusValuesDestination.strength) / 2.0D + focusBoost;
|
||||
lockStrengthSpeed = (focusValuesSource.speed + focusValuesDestination.speed) / 2.0D
|
||||
/ WarpDriveConfig.TRANSPORTER_LOCKING_SPEED_OPTIMAL_TICKS;
|
||||
|
||||
final int rangeMax = WarpDriveConfig.TRANSPORTER_RANGE_BASE_BLOCKS
|
||||
+ WarpDriveConfig.TRANSPORTER_RANGE_UPGRADE_BLOCKS * focusValuesSource.countRangeUpgrades
|
||||
+ WarpDriveConfig.TRANSPORTER_RANGE_UPGRADE_BLOCKS * focusValuesDestination.countRangeUpgrades;
|
||||
|
||||
if (WarpDriveConfig.LOGGING_TRANSPORTER) {
|
||||
WarpDrive.logger.info(String.format("Transporter parameters at (%d %d %d) are range (actual %d max %d) lockStrength (optimal %.3f speed %.3f)",
|
||||
xCoord, yCoord, zCoord,
|
||||
rangeActual, rangeMax,
|
||||
lockStrengthOptimal, lockStrengthSpeed));
|
||||
}
|
||||
|
||||
if (rangeActual > rangeMax) {
|
||||
isJammed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
isJammed |= isJammedTrajectory(vSource_absolute);
|
||||
isJammed |= isJammedTrajectory(vDestination_absolute);
|
||||
}
|
||||
|
||||
private FocusValues getFocusValueAtCoordinates(final VectorI vAbsolute) {
|
||||
// scan the area
|
||||
int countBeacons = 0;
|
||||
int countTransporters = 0;
|
||||
int sumRangeUpgrades = 0;
|
||||
int sumFocusUpgrades = 0;
|
||||
|
||||
final int xMin = vAbsolute.x - WarpDriveConfig.TRANSPORTER_FOCUS_SEARCH_RADIUS_BLOCKS;
|
||||
final int xMax = vAbsolute.x + WarpDriveConfig.TRANSPORTER_FOCUS_SEARCH_RADIUS_BLOCKS;
|
||||
final int yMin = vAbsolute.y - WarpDriveConfig.TRANSPORTER_FOCUS_SEARCH_RADIUS_BLOCKS;
|
||||
final int yMax = vAbsolute.y + WarpDriveConfig.TRANSPORTER_FOCUS_SEARCH_RADIUS_BLOCKS;
|
||||
final int zMin = vAbsolute.z - WarpDriveConfig.TRANSPORTER_FOCUS_SEARCH_RADIUS_BLOCKS;
|
||||
final int zMax = vAbsolute.z + WarpDriveConfig.TRANSPORTER_FOCUS_SEARCH_RADIUS_BLOCKS;
|
||||
|
||||
for (int x = xMin; x <= xMax; x++) {
|
||||
for (int y = yMin; y <= yMax; y++) {
|
||||
if (y < 0 || y > 254) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int z = zMin; z <= zMax; z++) {
|
||||
final Block block = worldObj.getBlock(x, y, z);
|
||||
if (block instanceof BlockTransportBeacon) {
|
||||
// count active beacons
|
||||
final boolean isActive = worldObj.getBlockMetadata(x, y, z) == 0;
|
||||
if (isActive) {
|
||||
countBeacons++;
|
||||
}
|
||||
|
||||
} else if (block instanceof BlockTransporter) {
|
||||
// count active transporters
|
||||
final TileEntity tileEntity = worldObj.getTileEntity(x, y, z);
|
||||
if (tileEntity instanceof TileEntityTransporter) {
|
||||
countTransporters++;
|
||||
// remember upgrades
|
||||
sumRangeUpgrades += ((TileEntityTransporter) tileEntity).getUpgradeCount(EnumComponentType.ENDER_CRYSTAL);
|
||||
sumFocusUpgrades += ((TileEntityTransporter) tileEntity).getUpgradeCount(EnumComponentType.EMERALD_CRYSTAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compute values
|
||||
final FocusValues result = new FocusValues();
|
||||
if (countTransporters > 0) {
|
||||
final int countFocusUpgrades = sumFocusUpgrades / countTransporters;
|
||||
result.countRangeUpgrades = sumRangeUpgrades / countTransporters;
|
||||
result.speed = WarpDriveConfig.TRANSPORTER_LOCKING_SPEED_AT_TRANSPORTER + countFocusUpgrades * WarpDriveConfig.TRANSPORTER_LOCKING_STRENGTH_UPGRADE;
|
||||
result.strength = WarpDriveConfig.TRANSPORTER_LOCKING_STRENGTH_AT_TRANSPORTER + countFocusUpgrades * WarpDriveConfig.TRANSPORTER_LOCKING_SPEED_UPGRADE;
|
||||
} else if (countBeacons > 0) {
|
||||
result.countRangeUpgrades = 0;
|
||||
result.speed = WarpDriveConfig.TRANSPORTER_LOCKING_SPEED_AT_FOCUS;
|
||||
result.strength = WarpDriveConfig.TRANSPORTER_LOCKING_STRENGTH_AT_FOCUS;
|
||||
} else {
|
||||
result.countRangeUpgrades = 0;
|
||||
result.speed = WarpDriveConfig.TRANSPORTER_LOCKING_SPEED_IN_WILDERNESS;
|
||||
result.strength = WarpDriveConfig.TRANSPORTER_LOCKING_STRENGTH_IN_WILDERNESS;
|
||||
}
|
||||
|
||||
if (WarpDriveConfig.LOGGING_TRANSPORTER) {
|
||||
WarpDrive.logger.info(String.format("Transporter getFocusValueAtCoordinates %s gives range %d speed %.3f strength %.3f",
|
||||
vAbsolute, result.countRangeUpgrades, result.speed, result.strength));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isJammedTrajectory(final VectorI vAbsolute) {
|
||||
final VectorI vPath = vAbsolute.clone().translateBack(new VectorI(this));
|
||||
final int length = (int) Math.ceil(3 * Math.sqrt(vPath.getMagnitudeSquared()));
|
||||
final Vector3 v3Delta = new Vector3(vPath.x / (double) length, vPath.y / (double) length, vPath.z / (double) length);
|
||||
|
||||
// scan along given trajectory
|
||||
final Vector3 v3Current = new Vector3(this).translate(0.5D);
|
||||
final VectorI vCurrent = new VectorI(this);
|
||||
final VectorI vPrevious = vCurrent.clone();
|
||||
for (int step = 0; step < length; step++) {
|
||||
v3Current.translate(v3Delta);
|
||||
vCurrent.x = (int) Math.round(v3Current.x);
|
||||
vCurrent.y = (int) Math.round(v3Current.y);
|
||||
vCurrent.z = (int) Math.round(v3Current.z);
|
||||
// skip repeating coordinates
|
||||
if (vCurrent.equals(vPrevious)) {
|
||||
continue;
|
||||
}
|
||||
if (isJammedCoordinate(vCurrent)) return true;
|
||||
|
||||
// remember this coordinates
|
||||
vPrevious.x = vCurrent.x;
|
||||
vPrevious.y = vCurrent.y;
|
||||
vPrevious.z = vCurrent.z;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private boolean isJammedCoordinate(final VectorI vCurrent) {
|
||||
// check block blacklist for blinking
|
||||
final Block block = vCurrent.getBlock(worldObj);
|
||||
if (Dictionary.BLOCKS_NOBLINK.contains(block)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// allow passing through force fields with same beam frequency
|
||||
if (block instanceof BlockForceField) {
|
||||
final TileEntity tileEntity = vCurrent.getTileEntity(worldObj);
|
||||
if (tileEntity instanceof TileEntityForceField) {
|
||||
final ForceFieldSetup forceFieldSetup = ((TileEntityForceField) tileEntity).getForceFieldSetup();
|
||||
if (forceFieldSetup == null) {
|
||||
// projector not loaded yet, consider it jammed by default
|
||||
WarpDrive.logger.warn(String.format("%s projector not loaded at %s", this, tileEntity));
|
||||
return true;
|
||||
}
|
||||
if (forceFieldSetup.beamFrequency != beamFrequency) {
|
||||
// jammed by invalid beam frequency
|
||||
if (WarpDriveConfig.LOGGING_TRANSPORTER) {
|
||||
WarpDrive.logger.info(String.format("%s signal jammed by %s", this, tileEntity));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int getEnergyRequired(final EnumTransporterState transporterState) {
|
||||
switch (transporterState) {
|
||||
case DISABLED:
|
||||
return 0;
|
||||
|
||||
case IDLE:
|
||||
return 0;
|
||||
|
||||
case ACQUIRING:
|
||||
return (int) Math.ceil(WarpDriveConfig.TRANSPORTER_ACQUIRING_ENERGY_FACTOR * energyCostForTransfer * energyFactor);
|
||||
|
||||
case ENERGIZING:
|
||||
return (int) Math.ceil(energyCostForTransfer * energyFactor);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void applyTeleportationDamages(final boolean isPreTeleportation, final Entity entity, final double strength) {
|
||||
// skip invulnerable
|
||||
if ( entity.isDead
|
||||
|| entity.isEntityInvulnerable() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add bonus if transport was successful
|
||||
final double strengthToUse = isPreTeleportation ? strength : Math.random() * WarpDriveConfig.TRANSPORTER_TRANSFER_SUCCESS_LOCK_BONUS + strength;
|
||||
|
||||
final double strengthSafe = 0.95D;
|
||||
final double strengthMaxDamage = 0.65D;
|
||||
final double strengthNoDamage = 0.10D;
|
||||
if (strengthToUse > strengthSafe) {
|
||||
return;
|
||||
}
|
||||
final double damageNormalized = (strengthSafe - strengthToUse) / (strengthSafe - strengthMaxDamage);
|
||||
final double damageMax = isPreTeleportation ? WarpDriveConfig.TRANSPORTER_TRANSFER_FAILURE_MAX_DAMAGE : WarpDriveConfig.TRANSPORTER_TRANSFER_SUCCESS_MAX_DAMAGE ;
|
||||
// final double damageAmount = Commons.clamp(1.0D, 1000.0D, Math.pow(10.0D, 10.0D * damageNormalized));
|
||||
final double damageAmount = Commons.clamp(1.0D, 1000.0D, damageMax * damageNormalized);
|
||||
|
||||
if (WarpDriveConfig.LOGGING_TRANSPORTER) {
|
||||
WarpDrive.logger.info(String.format("%s Applying teleportation damages %s transport with %.3f strength, %.2f damage towards %s",
|
||||
this,
|
||||
isPreTeleportation ? "pre" : "post",
|
||||
strengthToUse,
|
||||
damageAmount,
|
||||
entity));
|
||||
}
|
||||
|
||||
if (entity instanceof EntityLivingBase) {
|
||||
entity.attackEntityFrom(WarpDrive.damageTeleportation, (float) damageAmount);
|
||||
final boolean isCreative = (entity instanceof EntityPlayer) && ((EntityPlayer) entity).capabilities.isCreativeMode;
|
||||
if (!isCreative) {
|
||||
if (isPreTeleportation) {
|
||||
// add 1s nausea
|
||||
((EntityLivingBase) entity).addPotionEffect(new PotionEffect(Potion.confusion.id, 20, 0, true));
|
||||
} else {
|
||||
// add 5s poison
|
||||
((EntityLivingBase) entity).addPotionEffect(new PotionEffect(Potion.poison.id, 5 * 20, 0, true));
|
||||
}
|
||||
}
|
||||
} else if (strengthToUse > strengthNoDamage) {
|
||||
// add lava blade at location
|
||||
final VectorI vPosition = new VectorI(entity);
|
||||
if (worldObj.isAirBlock(vPosition.x, vPosition.y, vPosition.z)) {
|
||||
worldObj.setBlock(vPosition.x, vPosition.y, vPosition.z, Blocks.flowing_lava, 6, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateEntityToTransfer() {
|
||||
// validate existing entity
|
||||
if (weakEntity != null) {
|
||||
final Entity entity = weakEntity.get();
|
||||
if ( entity == null
|
||||
|| entity.isDead ) {
|
||||
// no longer valid => search a new one, no energy lost
|
||||
weakEntity = null;
|
||||
v3EntityPosition = null;
|
||||
|
||||
} else {
|
||||
final double tolerance2 = WarpDriveConfig.TRANSPORTER_ENTITY_MOVEMENT_TOLERANCE_BLOCKS
|
||||
* WarpDriveConfig.TRANSPORTER_ENTITY_MOVEMENT_TOLERANCE_BLOCKS;
|
||||
final double distance2 = v3EntityPosition.distanceTo_square(entity);
|
||||
if (distance2 > tolerance2) {
|
||||
// entity moved too much => damage existing one, grab another, lose energy
|
||||
final double strength = Math.sqrt(distance2) / Math.sqrt(tolerance2) / 2.0D;
|
||||
applyTeleportationDamages(true, entity, strength);
|
||||
weakEntity = null;
|
||||
v3EntityPosition = null;
|
||||
transporterState = EnumTransporterState.ACQUIRING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// grab another entity on first tick or if bad things happened
|
||||
if (weakEntity == null) {
|
||||
final Entity entityClosest = getClosestEntityAtSource();
|
||||
if (entityClosest == null) {
|
||||
return;
|
||||
}
|
||||
weakEntity = new WeakReference<>(entityClosest);
|
||||
v3EntityPosition = new Vector3(entityClosest);
|
||||
}
|
||||
}
|
||||
|
||||
private Entity getClosestEntityAtSource() {
|
||||
final AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(
|
||||
vSource_absolute.x - WarpDriveConfig.TRANSPORTER_ENTITY_GRAB_RADIUS_BLOCKS,
|
||||
vSource_absolute.y - 1.0D,
|
||||
vSource_absolute.z - WarpDriveConfig.TRANSPORTER_ENTITY_GRAB_RADIUS_BLOCKS,
|
||||
vSource_absolute.x + WarpDriveConfig.TRANSPORTER_ENTITY_GRAB_RADIUS_BLOCKS + 1.0D,
|
||||
vSource_absolute.y + 2.0D,
|
||||
vSource_absolute.z + WarpDriveConfig.TRANSPORTER_ENTITY_GRAB_RADIUS_BLOCKS + 1.0D);
|
||||
|
||||
Entity entityClosest = null;
|
||||
double rangeClosest2 = Integer.MAX_VALUE;
|
||||
|
||||
final List entities = worldObj.getEntitiesWithinAABBExcludingEntity(null, aabb);
|
||||
for (final Object object : entities) {
|
||||
if (!(object instanceof Entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final Entity entity = (Entity) object;
|
||||
|
||||
// skip particle effects
|
||||
if (entity instanceof EntityFX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip blacklisted ids
|
||||
final String entityId = EntityList.getEntityString(entity);
|
||||
if (Dictionary.ENTITIES_LEFTBEHIND.contains(entityId)) {
|
||||
if (WarpDriveConfig.LOGGING_TRANSPORTER) {
|
||||
WarpDrive.logger.info(String.format("Entity is not valid for transportation (id %s) %s",
|
||||
entityId, entity));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// keep closest one
|
||||
final double range2 = vSource_absolute.distance2To(entity);
|
||||
if (range2 < rangeClosest2) {
|
||||
rangeClosest2 = range2;
|
||||
entityClosest = (Entity) object;
|
||||
}
|
||||
}
|
||||
|
||||
return entityClosest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int energy_getMaxStorage() {
|
||||
final int energyUpgrades = getUpgradeCount(EnumComponentType.CAPACITIVE_CRYSTAL);
|
||||
return WarpDriveConfig.TRANSPORTER_MAX_ENERGY_STORED + energyUpgrades * WarpDriveConfig.TRANSPORTER_ENERGY_STORED_UPGRADE_BONUS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean energy_canInput(final ForgeDirection from) {
|
||||
return from != ForgeDirection.UP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final NBTTagCompound tagCompound) {
|
||||
super.writeToNBT(tagCompound);
|
||||
|
||||
tagCompound.setInteger(IBeamFrequency.BEAM_FREQUENCY_TAG, beamFrequency);
|
||||
tagCompound.setBoolean("isEnabled", isEnabled);
|
||||
tagCompound.setBoolean("isLockRequested", isLockRequested);
|
||||
tagCompound.setBoolean("isEnergizeRequested", isEnergizeRequested);
|
||||
|
||||
tagCompound.setTag("source", vSource_relative.writeToNBT(new NBTTagCompound()));
|
||||
tagCompound.setTag("destination", vDestination_relative.writeToNBT(new NBTTagCompound()));
|
||||
tagCompound.setDouble("energyFactor", energyFactor);
|
||||
tagCompound.setDouble("lockStrengthActual", lockStrengthActual);
|
||||
tagCompound.setInteger("tickCooldown", tickCooldown);
|
||||
|
||||
tagCompound.setString("state", transporterState.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final NBTTagCompound tagCompound) {
|
||||
super.readFromNBT(tagCompound);
|
||||
|
||||
beamFrequency = tagCompound.getInteger(IBeamFrequency.BEAM_FREQUENCY_TAG);
|
||||
isEnabled = tagCompound.getBoolean("isEnabled");
|
||||
isLockRequested = tagCompound.getBoolean("isLockRequested");
|
||||
isEnergizeRequested = tagCompound.getBoolean("isEnergizeRequested");
|
||||
|
||||
final NBTBase tagSource = tagCompound.getTag("source");
|
||||
if (tagSource instanceof NBTTagCompound) {
|
||||
vSource_relative.readFromNBT((NBTTagCompound) tagSource);
|
||||
}
|
||||
|
||||
final NBTBase tagDestination = tagCompound.getTag("destination");
|
||||
if (tagDestination instanceof NBTTagCompound) {
|
||||
vDestination_relative.readFromNBT((NBTTagCompound) tagDestination);
|
||||
}
|
||||
|
||||
energyFactor = tagCompound.getDouble("energyFactor");
|
||||
lockStrengthActual = tagCompound.getDouble("lockStrengthActual");
|
||||
tickCooldown = tagCompound.getInteger("tickCooldown");
|
||||
|
||||
try {
|
||||
transporterState = EnumTransporterState.valueOf(tagCompound.getString("state"));
|
||||
} catch (IllegalArgumentException exception) {
|
||||
transporterState = EnumTransporterState.DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
// Common OC/CC methods
|
||||
public Boolean[] enable(Object[] arguments) {
|
||||
if (arguments.length == 1) {
|
||||
isEnabled = Commons.toBool(arguments[0]);
|
||||
markDirty();
|
||||
}
|
||||
return new Boolean[] { isEnabled };
|
||||
}
|
||||
|
||||
public Integer[] source(final Object[] arguments) {
|
||||
final VectorI vNew = getVectorI(vSource_relative, arguments);
|
||||
if (!vNew.equals(vSource_relative)) {
|
||||
isLockRequested = false;
|
||||
isEnergizeRequested = false;
|
||||
vSource_relative = vNew;
|
||||
}
|
||||
return new Integer[] { vSource_relative.x, vSource_relative.y, vSource_relative.z };
|
||||
}
|
||||
|
||||
public Integer[] destination(final Object[] arguments) {
|
||||
final VectorI vNew = getVectorI(vDestination_relative, arguments);
|
||||
if (!vNew.equals(vDestination_relative)) {
|
||||
isLockRequested = false;
|
||||
isEnergizeRequested = false;
|
||||
vDestination_relative = vNew;
|
||||
}
|
||||
return new Integer[] { vDestination_relative.x, vDestination_relative.y, vDestination_relative.z };
|
||||
}
|
||||
|
||||
private VectorI getVectorI(final VectorI vDefault, final Object[] arguments) {
|
||||
final VectorI vResult = vDefault.clone();
|
||||
|
||||
try {
|
||||
if (arguments.length == 3) {
|
||||
vResult.x = Commons.toInt(arguments[0]);
|
||||
vResult.y = Commons.toInt(arguments[1]);
|
||||
vResult.z = Commons.toInt(arguments[2]);
|
||||
} else if (arguments.length == 1) {
|
||||
vResult.x = 0;
|
||||
vResult.y = 0;
|
||||
vResult.z = 0;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// ignore
|
||||
}
|
||||
return vResult;
|
||||
}
|
||||
|
||||
private Boolean[] lock(final Object[] arguments) {
|
||||
if (arguments.length == 1) {
|
||||
isLockRequested = Commons.toBool(arguments[0]);
|
||||
markDirty();
|
||||
}
|
||||
return new Boolean[] { isLockRequested };
|
||||
}
|
||||
|
||||
private Double[] energyFactor(final Object[] arguments) {
|
||||
try {
|
||||
if (arguments.length >= 1) {
|
||||
energyFactor = Commons.clamp(1, WarpDriveConfig.TRANSPORTER_TRANSFER_ENERGY_FACTOR_MAX, Commons.toDouble(arguments[0]));
|
||||
}
|
||||
} catch (NumberFormatException exception) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return new Double[] { energyFactor };
|
||||
}
|
||||
|
||||
private Double[] getLockStrength() {
|
||||
return new Double[] { lockStrengthActual };
|
||||
}
|
||||
|
||||
private Integer[] getEnergyRequired() {
|
||||
return new Integer[] { getEnergyRequired(EnumTransporterState.ENERGIZING) };
|
||||
}
|
||||
|
||||
private Boolean[] energize(final Object[] arguments) {
|
||||
if (arguments.length == 1) {
|
||||
isEnergizeRequested = Commons.toBool(arguments[0]);
|
||||
markDirty();
|
||||
}
|
||||
return new Boolean[] { isEnergizeRequested };
|
||||
}
|
||||
|
||||
// OpenComputers callback methods
|
||||
@Callback
|
||||
@Optional.Method(modid = "OpenComputers")
|
||||
public Object[] beamFrequency(Context context, Arguments arguments) {
|
||||
if (arguments.count() == 1) {
|
||||
setBeamFrequency(arguments.checkInteger(0));
|
||||
}
|
||||
return new Integer[] { beamFrequency };
|
||||
}
|
||||
|
||||
@Callback
|
||||
@Optional.Method(modid = "OpenComputers")
|
||||
public Object[] enable(Context context, Arguments arguments) {
|
||||
return enable(argumentsOCtoCC(arguments));
|
||||
}
|
||||
|
||||
@Callback
|
||||
@Optional.Method(modid = "OpenComputers")
|
||||
public Object[] source(Context context, Arguments arguments) {
|
||||
return source(argumentsOCtoCC(arguments));
|
||||
}
|
||||
|
||||
@Callback
|
||||
@Optional.Method(modid = "OpenComputers")
|
||||
public Object[] destination(Context context, Arguments arguments) {
|
||||
return destination(argumentsOCtoCC(arguments));
|
||||
}
|
||||
|
||||
@Callback
|
||||
@Optional.Method(modid = "OpenComputers")
|
||||
public Object[] lock(Context context, Arguments arguments) {
|
||||
return lock(argumentsOCtoCC(arguments));
|
||||
}
|
||||
|
||||
@Callback
|
||||
@Optional.Method(modid = "OpenComputers")
|
||||
public Object[] energyFactor(Context context, Arguments arguments) {
|
||||
return energyFactor(argumentsOCtoCC(arguments));
|
||||
}
|
||||
|
||||
@Callback
|
||||
@Optional.Method(modid = "OpenComputers")
|
||||
public Object[] getLockStrength(Context context, Arguments arguments) {
|
||||
return getLockStrength();
|
||||
}
|
||||
|
||||
@Callback
|
||||
@Optional.Method(modid = "OpenComputers")
|
||||
public Object[] getEnergyRequired(Context context, Arguments arguments) {
|
||||
return getEnergyRequired();
|
||||
}
|
||||
|
||||
@Callback
|
||||
@Optional.Method(modid = "OpenComputers")
|
||||
public Object[] energize(Context context, Arguments arguments) {
|
||||
return energize(argumentsOCtoCC(arguments));
|
||||
}
|
||||
|
||||
// ComputerCraft IPeripheral methods
|
||||
@Override
|
||||
@Optional.Method(modid = "ComputerCraft")
|
||||
public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) {
|
||||
final String methodName = getMethodName(method);
|
||||
|
||||
switch (methodName) {
|
||||
case "beamFrequency":
|
||||
if (arguments.length == 1) {
|
||||
setBeamFrequency(Commons.toInt(arguments[0]));
|
||||
}
|
||||
return new Integer[] { beamFrequency };
|
||||
|
||||
case "enable":
|
||||
return enable(arguments);
|
||||
|
||||
case "source":
|
||||
return source(arguments);
|
||||
|
||||
case "destination":
|
||||
return destination(arguments);
|
||||
|
||||
case "lock":
|
||||
return lock(arguments);
|
||||
|
||||
case "energyFactor":
|
||||
return energyFactor(arguments);
|
||||
|
||||
case "getLockStrength":
|
||||
return getLockStrength();
|
||||
|
||||
case "getEnergyRequired":
|
||||
return getEnergyRequired();
|
||||
|
||||
case "energize":
|
||||
return energize(arguments);
|
||||
}
|
||||
|
||||
return super.callMethod(computer, context, method, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s Beam \'%d\' @ %s (%d %d %d)",
|
||||
getClass().getSimpleName(),
|
||||
beamFrequency,
|
||||
worldObj == null ? "~NULL~" : worldObj.provider.getDimensionName(),
|
||||
xCoord, yCoord, zCoord);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -174,7 +174,7 @@ public class Recipes {
|
|||
'p', ItemComponent.getItemStack(EnumComponentType.POWER_INTERFACE)));
|
||||
|
||||
// Transporter
|
||||
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(WarpDrive.blockTransporter), false, "iii", "ptc", "iii",
|
||||
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(WarpDrive.blockTransporterCore), false, "iii", "ptc", "iii",
|
||||
'i', Items.iron_ingot,
|
||||
't', ItemComponent.getItemStack(EnumComponentType.ENDER_CRYSTAL),
|
||||
'c', ItemComponent.getItemStack(EnumComponentType.COMPUTER_INTERFACE),
|
||||
|
@ -348,7 +348,7 @@ public class Recipes {
|
|||
'w', "logWood",
|
||||
'm', WarpDrive.blockMiningLaser }));
|
||||
|
||||
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(WarpDrive.blockTransporter), false, new Object[] { "ece", "imi", "iei",
|
||||
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(WarpDrive.blockTransporterCore), false, new Object[] { "ece", "imi", "iei",
|
||||
'e', Items.ender_pearl,
|
||||
'c', circuit,
|
||||
'i', ironPlate,
|
||||
|
@ -491,7 +491,7 @@ public class Recipes {
|
|||
'm', WarpDrive.blockMiningLaser,
|
||||
's', WarpDriveConfig.getModItemStack("IC2", "itemToolChainsaw", -1) }));
|
||||
|
||||
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(WarpDrive.blockTransporter), false, new Object[] { "aea", "ctc", "ama",
|
||||
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(WarpDrive.blockTransporterCore), false, new Object[] { "aea", "ctc", "ama",
|
||||
'a', advancedAlloy,
|
||||
'e', Items.ender_pearl,
|
||||
'c', "circuitAdvanced",
|
||||
|
@ -1269,15 +1269,25 @@ public class Recipes {
|
|||
'a', Items.diamond_axe,
|
||||
'g', "paneGlassColorless"));
|
||||
|
||||
// Transporter is non-functional => no recipe
|
||||
/*
|
||||
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(WarpDrive.blockTransporter), false, "aea", "ctc", "ama",
|
||||
'a', advancedAlloy,
|
||||
'e', Items.ender_pearl,
|
||||
'c', "circuitAdvanced",
|
||||
'm', advancedMachine,
|
||||
't', WarpDriveConfig.getModItemStack("IC2", "blockMachine2", 0) )); // Teleporter
|
||||
/**/
|
||||
// Transporter containment is 1 HV Machine casing, 2 Ender crystal, gives 2
|
||||
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(WarpDrive.blockTransporterContainment, 2), false, " e ", " m ", " e ",
|
||||
'm', itemStackMachineCasings[2],
|
||||
'e', ItemComponent.getItemStack(EnumComponentType.ENDER_CRYSTAL)));
|
||||
|
||||
// Transporter core is 1 HV Machine casing, 1 Emerald crystal, 1 Capacitive crystal, 1 Diamond crystal, 1 Power interface, 1 Computer interface
|
||||
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(WarpDrive.blockTransporterCore), false, " E ", "pmd", " c ",
|
||||
'm', itemStackMachineCasings[2],
|
||||
'c', ItemComponent.getItemStack(EnumComponentType.COMPUTER_INTERFACE),
|
||||
'd', ItemComponent.getItemStack(EnumComponentType.DIAMOND_CRYSTAL),
|
||||
'E', ItemComponent.getItemStack(EnumComponentType.EMERALD_CRYSTAL),
|
||||
'p', ItemComponent.getItemStack(EnumComponentType.POWER_INTERFACE)));
|
||||
|
||||
// Transporter scanner is 1 HV Machine casing, 1 Emerald crystal, 3 Capacitive crystal, 2 Ender crystal
|
||||
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(WarpDrive.blockTransporterScanner), false, " E ", "eme", "CCC",
|
||||
'm', itemStackMachineCasings[2],
|
||||
'e', ItemComponent.getItemStack(EnumComponentType.ENDER_CRYSTAL),
|
||||
'E', ItemComponent.getItemStack(EnumComponentType.EMERALD_CRYSTAL),
|
||||
'C', ItemComponent.getItemStack(EnumComponentType.CAPACITIVE_CRYSTAL)));
|
||||
|
||||
// IC2 needs to be loaded for the following 2 recipes
|
||||
if (WarpDriveConfig.isIndustrialCraft2Loaded) {
|
||||
|
@ -1358,7 +1368,7 @@ public class Recipes {
|
|||
't', oreEmeraldOrTitaniumPlate,
|
||||
'i', oreEmeraldOrReinforcedIridiumPlate,
|
||||
'c', itemStackGoldIngotOrCoil,
|
||||
'm', itemStackMachineCasings[3] ));
|
||||
'm', itemStackMachineCasings[3] ));
|
||||
|
||||
// Enantiomorphic reactor core is 1 EV Machine casing, 4 Capacitive crystal, 1 Computer interface, 1 Power interface, 2 Lenses
|
||||
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(WarpDrive.blockEnanReactorCore), false, "CpC", "lml", "CcC",
|
||||
|
|
|
@ -359,6 +359,10 @@ public class WarpDriveConfig {
|
|||
public static int TRANSPORTER_MAX_ENERGY_STORED = 2000000;
|
||||
public static int TRANSPORTER_ENERGY_STORED_UPGRADE_BONUS = TRANSPORTER_MAX_ENERGY_STORED / 2;
|
||||
public static int TRANSPORTER_ENERGY_STORED_UPGRADE_MAX_QUANTITY = 8;
|
||||
public static int TRANSPORTER_UPDATE_PARAMETERS_TICKS = 1 * 20;
|
||||
public static int TRANSPORTER_SCANNER_GRAB_XZ_BLOCKS = 8;
|
||||
public static int TRANSPORTER_SCANNER_GRAB_Y_BELOW_BLOCKS = 3;
|
||||
public static int TRANSPORTER_SCANNER_GRAB_Y_ABOVE_BLOCKS = 1;
|
||||
public static int TRANSPORTER_RANGE_BASE_BLOCKS = 128;
|
||||
public static int TRANSPORTER_RANGE_UPGRADE_BLOCKS = 16;
|
||||
public static int TRANSPORTER_RANGE_UPGRADE_MAX_QUANTITY = 8;
|
||||
|
@ -372,12 +376,11 @@ public class WarpDriveConfig {
|
|||
public static int TRANSPORTER_TRANSFER_SUCCESS_MAX_DAMAGE = 100;
|
||||
public static double TRANSPORTER_TRANSFER_LOCKING_LOST = 0.5D;
|
||||
public static int TRANSPORTER_TRANSFER_WARMUP_TICKS = 3 * 20;
|
||||
public static int TRANSPORTER_TRANSFER_RELEASE_TICKS = 2 * 20;
|
||||
public static int TRANSPORTER_TRANSFER_COOLDOWN_TICKS = 10 * 20;
|
||||
public static double TRANSPORTER_ENTITY_MOVEMENT_TOLERANCE_BLOCKS = 1.0D;
|
||||
public static int TRANSPORTER_ENTITY_GRAB_RADIUS_BLOCKS = 2;
|
||||
public static int TRANSPORTER_FOCUS_SEARCH_RADIUS_BLOCKS = 2;
|
||||
public static double TRANSPORTER_LOCKING_STRENGTH_FACTOR_PER_TICK = 0.999D; // natural decay
|
||||
public static double TRANSPORTER_LOCKING_STRENGTH_FACTOR_PER_TICK = Math.pow(0.01D, 1.0D / 300.0D); // natural decay down to 1% over 300 ticks
|
||||
public static double TRANSPORTER_LOCKING_STRENGTH_IN_WILDERNESS = 0.25D;
|
||||
public static double TRANSPORTER_LOCKING_STRENGTH_AT_FOCUS = 0.5D;
|
||||
public static double TRANSPORTER_LOCKING_STRENGTH_AT_TRANSPORTER = 1.0D;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cr0s.warpdrive.data;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.ChunkCoordIntPair;
|
||||
|
@ -19,12 +20,19 @@ public class GlobalPosition {
|
|||
this.z = z;
|
||||
}
|
||||
|
||||
public GlobalPosition(TileEntity tileEntity) {
|
||||
public GlobalPosition(final TileEntity tileEntity) {
|
||||
this(tileEntity.getWorldObj().provider.dimensionId, tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord);
|
||||
}
|
||||
|
||||
public GlobalPosition(final Entity entity) {
|
||||
this(entity.worldObj.provider.dimensionId,
|
||||
(int) Math.floor(entity.posX),
|
||||
(int) Math.floor(entity.posY),
|
||||
(int) Math.floor(entity.posZ));
|
||||
}
|
||||
|
||||
public WorldServer getWorldServerIfLoaded() {
|
||||
WorldServer world = DimensionManager.getWorld(dimensionId);
|
||||
final WorldServer world = DimensionManager.getWorld(dimensionId);
|
||||
// skip unloaded worlds
|
||||
if (world == null) {
|
||||
return null;
|
||||
|
@ -52,11 +60,29 @@ public class GlobalPosition {
|
|||
return getWorldServerIfLoaded() != null;
|
||||
}
|
||||
|
||||
public CelestialObject getCelestialObject(final boolean isRemote) {
|
||||
return CelestialObjectManager.get(isRemote, dimensionId, x, z);
|
||||
}
|
||||
|
||||
public Vector3 getUniversalCoordinates(final boolean isRemote) {
|
||||
CelestialObject celestialObject = CelestialObjectManager.get(isRemote, dimensionId, x, z);
|
||||
final CelestialObject celestialObject = CelestialObjectManager.get(isRemote, dimensionId, x, z);
|
||||
return StarMapRegistry.getUniversalCoordinates(celestialObject, x, y, z);
|
||||
}
|
||||
|
||||
public VectorI getVectorI() {
|
||||
return new VectorI(x, y, z);
|
||||
}
|
||||
|
||||
public double distance2To(final Entity entity) {
|
||||
if (entity.worldObj.provider.dimensionId != dimensionId) {
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
final double newX = entity.posX - x;
|
||||
final double newY = entity.posY - y;
|
||||
final double newZ = entity.posZ - z;
|
||||
return newX * newX + newY * newY + newZ * newZ;
|
||||
}
|
||||
|
||||
public GlobalPosition(final NBTTagCompound tagCompound) {
|
||||
dimensionId = tagCompound.getInteger("dimensionId");
|
||||
x = tagCompound.getInteger("x");
|
||||
|
@ -76,6 +102,22 @@ public class GlobalPosition {
|
|||
&& x == tileEntity.xCoord && y == tileEntity.yCoord && z == tileEntity.zCoord;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object object) {
|
||||
if (object instanceof GlobalPosition) {
|
||||
GlobalPosition globalPosition = (GlobalPosition) object;
|
||||
return (dimensionId == globalPosition.dimensionId) && (x == globalPosition.x) && (y == globalPosition.y) && (z == globalPosition.z);
|
||||
} else if (object instanceof VectorI) {
|
||||
VectorI vector = (VectorI) object;
|
||||
return (x == vector.x) && (y == vector.y) && (z == vector.z);
|
||||
} else if (object instanceof TileEntity) {
|
||||
TileEntity tileEntity = (TileEntity) object;
|
||||
return (dimensionId == tileEntity.getWorldObj().provider.dimensionId) && (x == tileEntity.xCoord) && (y == tileEntity.yCoord) && (z == tileEntity.zCoord);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return dimensionId << 24 + (x >> 10) << 12 + y << 10 + (z >> 10);
|
||||
|
|
|
@ -8,36 +8,49 @@ import net.minecraft.entity.Entity;
|
|||
import net.minecraft.entity.player.EntityPlayer;
|
||||
|
||||
public class MovingEntity {
|
||||
|
||||
private final WeakReference<Entity> weakEntity;
|
||||
public final double originalX;
|
||||
public final double originalY;
|
||||
public final double originalZ;
|
||||
|
||||
public MovingEntity(final Entity entity) {
|
||||
weakEntity = new WeakReference<>(entity);
|
||||
originalX = entity.posX;
|
||||
originalY = entity.posY;
|
||||
originalZ = entity.posZ;
|
||||
}
|
||||
|
||||
public Entity getEntity() {
|
||||
return weakEntity.get();
|
||||
}
|
||||
|
||||
public boolean isUnlimited() {
|
||||
final Entity entity = getEntity();
|
||||
if (!(entity instanceof EntityPlayer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final String playerName = ((EntityPlayer) entity).getDisplayName();
|
||||
for (final String unlimitedName : WarpDriveConfig.SHIP_VOLUME_UNLIMITED_PLAYERNAMES) {
|
||||
if (unlimitedName.equals(playerName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static final MovingEntity INVALID = new MovingEntity(null);
|
||||
|
||||
private final WeakReference<Entity> weakEntity;
|
||||
public final Vector3 v3OriginalPosition;
|
||||
|
||||
public MovingEntity(final Entity entity) {
|
||||
if (entity == null) {
|
||||
weakEntity = new WeakReference<>(null);
|
||||
v3OriginalPosition = new Vector3(0, -100, 0);
|
||||
} else {
|
||||
weakEntity = new WeakReference<>(entity);
|
||||
v3OriginalPosition = new Vector3(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public Entity getEntity() {
|
||||
return weakEntity.get();
|
||||
}
|
||||
|
||||
public boolean isUnlimited() {
|
||||
final Entity entity = getEntity();
|
||||
if (!(entity instanceof EntityPlayer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final String playerName = ((EntityPlayer) entity).getDisplayName();
|
||||
for (final String unlimitedName : WarpDriveConfig.SHIP_VOLUME_UNLIMITED_PLAYERNAMES) {
|
||||
if (unlimitedName.equals(playerName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public double getDistanceMoved_square() {
|
||||
final Entity entity = getEntity();
|
||||
if (entity == null) {
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
return v3OriginalPosition.distanceTo_square(entity);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
|
@ -95,6 +96,25 @@ public class StarMapRegistry {
|
|||
// not found => ignore it
|
||||
}
|
||||
|
||||
public StarMapRegistryItem getByUUID(final EnumStarMapEntryType enumStarMapEntryType, final UUID uuid) {
|
||||
for (final Integer dimensionId : registry.keySet()) {
|
||||
final CopyOnWriteArraySet<StarMapRegistryItem> setStarMapRegistryItems = registry.get(dimensionId);
|
||||
if (setStarMapRegistryItems == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (final StarMapRegistryItem starMapRegistryItem : setStarMapRegistryItems) {
|
||||
if ( enumStarMapEntryType == null
|
||||
|| starMapRegistryItem.type == enumStarMapEntryType ) {
|
||||
if (starMapRegistryItem.uuid.equals(uuid)) {
|
||||
return starMapRegistryItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String find(final String nameShip) {
|
||||
final int MAX_LENGTH = 2000;
|
||||
final StringBuilder resultMatch = new StringBuilder();
|
||||
|
|
|
@ -29,7 +29,8 @@ public class StarMapRegistryItem extends GlobalPosition {
|
|||
STAR(4, "star"), // a star
|
||||
STRUCTURE(5, "structure"), // a structure from WorldGeneration (moon, asteroid field, etc.)
|
||||
WARP_ECHO(6, "warp_echo"), // remains of a warp
|
||||
ACCELERATOR(7, "accelerator"); // an accelerator setup
|
||||
ACCELERATOR(7, "accelerator"), // an accelerator setup
|
||||
TRANSPORTER(8, "transporter"); // a transporter room
|
||||
|
||||
private final int id;
|
||||
private final String name;
|
||||
|
|
|
@ -1083,17 +1083,14 @@ public class JumpSequencer extends AbstractSequencer {
|
|||
continue;
|
||||
}
|
||||
|
||||
final double oldEntityX = movingEntity.originalX;
|
||||
final double oldEntityY = movingEntity.originalY;
|
||||
final double oldEntityZ = movingEntity.originalZ;
|
||||
Vec3 target = transformation.apply(oldEntityX, oldEntityY, oldEntityZ);
|
||||
final Vec3 target = transformation.apply(movingEntity.v3OriginalPosition.x, movingEntity.v3OriginalPosition.y, movingEntity.v3OriginalPosition.z);
|
||||
final double newEntityX = target.xCoord;
|
||||
final double newEntityY = target.yCoord;
|
||||
final double newEntityZ = target.zCoord;
|
||||
|
||||
if (WarpDriveConfig.LOGGING_JUMP) {
|
||||
WarpDrive.logger.info(String.format("Entity moving: (%.2f %.2f %.2f) -> (%.2f %.2f %.2f) entity %s",
|
||||
oldEntityX, oldEntityY, oldEntityZ,
|
||||
movingEntity.v3OriginalPosition.x, movingEntity.v3OriginalPosition.y, movingEntity.v3OriginalPosition.z,
|
||||
newEntityX, newEntityY, newEntityZ, entity.toString()));
|
||||
}
|
||||
|
||||
|
@ -1357,16 +1354,16 @@ public class JumpSequencer extends AbstractSequencer {
|
|||
|
||||
if (WarpDriveConfig.LOGGING_JUMP) {
|
||||
WarpDrive.logger.info(String.format("Entity restoring position at (%f %f %f)",
|
||||
movingEntity.originalX, movingEntity.originalY, movingEntity.originalZ));
|
||||
movingEntity.v3OriginalPosition.x, movingEntity.v3OriginalPosition.y, movingEntity.v3OriginalPosition.z));
|
||||
}
|
||||
|
||||
// Update position
|
||||
if (entity instanceof EntityPlayerMP) {
|
||||
final EntityPlayerMP player = (EntityPlayerMP) entity;
|
||||
|
||||
player.setPositionAndUpdate(movingEntity.originalX, movingEntity.originalY, movingEntity.originalZ);
|
||||
player.setPositionAndUpdate(movingEntity.v3OriginalPosition.x, movingEntity.v3OriginalPosition.y, movingEntity.v3OriginalPosition.z);
|
||||
} else {
|
||||
entity.setPosition(movingEntity.originalX, movingEntity.originalY, movingEntity.originalZ);
|
||||
entity.setPosition(movingEntity.v3OriginalPosition.x, movingEntity.v3OriginalPosition.y, movingEntity.v3OriginalPosition.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package cr0s.warpdrive.network;
|
|||
import cr0s.warpdrive.Commons;
|
||||
import cr0s.warpdrive.WarpDrive;
|
||||
import cr0s.warpdrive.config.WarpDriveConfig;
|
||||
import cr0s.warpdrive.data.GlobalPosition;
|
||||
import cr0s.warpdrive.data.MovingEntity;
|
||||
import cr0s.warpdrive.data.Vector3;
|
||||
import cr0s.warpdrive.data.VectorI;
|
||||
import cr0s.warpdrive.render.EntityFXBeam;
|
||||
|
@ -26,15 +28,16 @@ import cpw.mods.fml.relauncher.Side;
|
|||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public class MessageTransporterEffect implements IMessage, IMessageHandler<MessageTransporterEffect, IMessage> {
|
||||
|
||||
private final int ENTITY_ID_NONE = 0;
|
||||
|
||||
private VectorI vSource;
|
||||
private VectorI vDestination;
|
||||
private boolean isTransporterRoom;
|
||||
private GlobalPosition globalPosition;
|
||||
private ArrayList<Integer> idEntities;
|
||||
private ArrayList<Vector3> v3EntityPositions;
|
||||
private double lockStrength;
|
||||
private int idEntity;
|
||||
private Vector3 v3EntityPosition;
|
||||
private int tickEnergizing;
|
||||
private int tickCooldown;
|
||||
|
||||
|
@ -42,56 +45,79 @@ public class MessageTransporterEffect implements IMessage, IMessageHandler<Messa
|
|||
// required on receiving side
|
||||
}
|
||||
|
||||
public MessageTransporterEffect(final VectorI vSource, final VectorI vDestination, final double lockStrength,
|
||||
final Entity entity, final Vector3 v3EntityPosition,
|
||||
final int tickEnergizing, final int tickCooldown) {
|
||||
this.vSource = vSource;
|
||||
this.vDestination = vDestination;
|
||||
public MessageTransporterEffect(final boolean isTransporterRoom, final GlobalPosition globalPosition,
|
||||
final Collection<MovingEntity> movingEntities,
|
||||
final double lockStrength, final int tickEnergizing, final int tickCooldown) {
|
||||
this.isTransporterRoom = isTransporterRoom;
|
||||
this.globalPosition = globalPosition;
|
||||
if ( movingEntities == null
|
||||
|| movingEntities.isEmpty() ) {
|
||||
this.idEntities = null;
|
||||
this.v3EntityPositions = null;
|
||||
} else {
|
||||
idEntities = new ArrayList<>(movingEntities.size());
|
||||
v3EntityPositions = new ArrayList<>(movingEntities.size());
|
||||
for (final MovingEntity movingEntity : movingEntities) {
|
||||
final Entity entity = movingEntity.getEntity();
|
||||
if (entity != null) {
|
||||
idEntities.add(entity.getEntityId());
|
||||
v3EntityPositions.add(movingEntity.v3OriginalPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.lockStrength = lockStrength;
|
||||
this.idEntity = entity == null ? ENTITY_ID_NONE : entity.getEntityId();
|
||||
this.v3EntityPosition = v3EntityPosition;
|
||||
this.tickEnergizing = tickEnergizing;
|
||||
this.tickCooldown = tickCooldown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes(final ByteBuf buffer) {
|
||||
int x = buffer.readInt();
|
||||
int y = buffer.readInt();
|
||||
int z = buffer.readInt();
|
||||
vSource = new VectorI(x, y, z);
|
||||
isTransporterRoom = buffer.readBoolean();
|
||||
|
||||
x = buffer.readInt();
|
||||
y = buffer.readInt();
|
||||
z = buffer.readInt();
|
||||
vDestination = new VectorI(x, y, z);
|
||||
final short dimensionId = buffer.readShort();
|
||||
final int x = buffer.readInt();
|
||||
final int y = buffer.readInt();
|
||||
final int z = buffer.readInt();
|
||||
globalPosition = new GlobalPosition(dimensionId, x, y, z);
|
||||
|
||||
final int countEntities = buffer.readByte();
|
||||
idEntities = new ArrayList<>(countEntities);
|
||||
v3EntityPositions = new ArrayList<>(countEntities);
|
||||
for (int indexEntity = 0; indexEntity < countEntities; indexEntity++) {
|
||||
final int idEntity = buffer.readInt();
|
||||
idEntities.add(idEntity);
|
||||
|
||||
final double xEntity = buffer.readDouble();
|
||||
final double yEntity = buffer.readDouble();
|
||||
final double zEntity = buffer.readDouble();
|
||||
v3EntityPositions.add(new Vector3(xEntity, yEntity, zEntity));
|
||||
}
|
||||
|
||||
lockStrength = buffer.readFloat();
|
||||
|
||||
idEntity = buffer.readInt();
|
||||
|
||||
final double xEntity = buffer.readDouble();
|
||||
final double yEntity = buffer.readDouble();
|
||||
final double zEntity = buffer.readDouble();
|
||||
v3EntityPosition = new Vector3(xEntity, yEntity, zEntity);
|
||||
|
||||
tickEnergizing = buffer.readShort();
|
||||
tickCooldown = buffer.readShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(ByteBuf buffer) {
|
||||
buffer.writeInt(vSource.x);
|
||||
buffer.writeInt(vSource.y);
|
||||
buffer.writeInt(vSource.z);
|
||||
buffer.writeInt(vDestination.x);
|
||||
buffer.writeInt(vDestination.y);
|
||||
buffer.writeInt(vDestination.z);
|
||||
buffer.writeBoolean(isTransporterRoom);
|
||||
|
||||
buffer.writeShort(globalPosition.dimensionId);
|
||||
buffer.writeInt(globalPosition.x);
|
||||
buffer.writeInt(globalPosition.y);
|
||||
buffer.writeInt(globalPosition.z);
|
||||
|
||||
final int countEntities = idEntities == null ? 0 : idEntities.size();
|
||||
buffer.writeByte(countEntities);
|
||||
for (int indexEntity = 0; indexEntity < countEntities; indexEntity++) {
|
||||
buffer.writeInt(idEntities.get(indexEntity));
|
||||
final Vector3 v3EntityPosition = v3EntityPositions.get(indexEntity);
|
||||
buffer.writeDouble(v3EntityPosition.x);
|
||||
buffer.writeDouble(v3EntityPosition.y);
|
||||
buffer.writeDouble(v3EntityPosition.z);
|
||||
}
|
||||
|
||||
buffer.writeFloat((float) lockStrength);
|
||||
buffer.writeInt(idEntity);
|
||||
buffer.writeDouble(v3EntityPosition == null ? 0.0D : v3EntityPosition.x);
|
||||
buffer.writeDouble(v3EntityPosition == null ? -1000.0D : v3EntityPosition.y);
|
||||
buffer.writeDouble(v3EntityPosition == null ? 0.0D : v3EntityPosition.z);
|
||||
buffer.writeShort(tickEnergizing);
|
||||
buffer.writeShort(tickCooldown);
|
||||
}
|
||||
|
@ -105,50 +131,36 @@ public class MessageTransporterEffect implements IMessage, IMessageHandler<Messa
|
|||
final EntityPlayer player = Minecraft.getMinecraft().thePlayer;
|
||||
|
||||
// handle source
|
||||
if (vSource.distance2To(player) <= maxRenderDistance_squared) {
|
||||
if (globalPosition.distance2To(player) <= maxRenderDistance_squared) {
|
||||
handleAtSource(world);
|
||||
}
|
||||
|
||||
// handle target
|
||||
if (vDestination.distance2To(player) <= maxRenderDistance_squared) {
|
||||
handleAtDestination(world);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAtSource(final World world) {
|
||||
// add flying particles in area of effect
|
||||
spawnParticlesInArea(world, vSource, false,
|
||||
0.4F, 0.7F, 0.9F,
|
||||
0.10F, 0.15F, 0.10F);
|
||||
|
||||
// get actual entity
|
||||
final Entity entity = idEntity == ENTITY_ID_NONE ? null : world.getEntityByID(idEntity);
|
||||
|
||||
// energizing
|
||||
// @TODO cylinder fade in + shower
|
||||
if (entity != null) {
|
||||
final Vector3 v3Position = new Vector3(entity);
|
||||
final Vector3 v3Target = v3Position.clone().translate(ForgeDirection.UP, entity.height);
|
||||
EntityFX effect = new EntityFXBeam(world, v3Position, v3Target,
|
||||
0.6F + 0.1F * world.rand.nextFloat(),
|
||||
0.6F + 0.15F * world.rand.nextFloat(),
|
||||
0.8F + 0.10F * world.rand.nextFloat(),
|
||||
20, 0);
|
||||
FMLClientHandler.instance().getClient().effectRenderer.addEffect(effect);
|
||||
// add flying particles in area of effect when in the wild
|
||||
if (!isTransporterRoom) {
|
||||
spawnParticlesInArea(world, globalPosition.getVectorI(), false,
|
||||
0.4F, 0.7F, 0.9F,
|
||||
0.10F, 0.15F, 0.10F);
|
||||
}
|
||||
|
||||
// cooldown
|
||||
// @TODO cylinder fade out
|
||||
}
|
||||
|
||||
private void handleAtDestination(final World world) {
|
||||
// add flying particles in area of effect
|
||||
spawnParticlesInArea(world, vDestination, true,
|
||||
0.4F, 0.9F, 0.7F,
|
||||
0.10F, 0.10F, 0.15F);
|
||||
|
||||
// energizing
|
||||
// @TODO cylinder fade in + shower
|
||||
// get actual entity
|
||||
for (int indexEntity = 0; indexEntity < idEntities.size(); indexEntity++) {
|
||||
final Entity entity = world.getEntityByID(idEntities.get(indexEntity));
|
||||
|
||||
// energizing
|
||||
// @TODO cylinder fade in + shower
|
||||
if (entity != null) {
|
||||
final Vector3 v3Position = new Vector3(entity);
|
||||
final Vector3 v3Target = v3Position.clone().translate(ForgeDirection.UP, entity.height);
|
||||
final EntityFX effect = new EntityFXBeam(world, v3Position, v3Target,
|
||||
0.6F + 0.1F * world.rand.nextFloat(),
|
||||
0.6F + 0.15F * world.rand.nextFloat(),
|
||||
0.8F + 0.10F * world.rand.nextFloat(),
|
||||
20, 0);
|
||||
FMLClientHandler.instance().getClient().effectRenderer.addEffect(effect);
|
||||
}
|
||||
}
|
||||
|
||||
// cooldown
|
||||
// @TODO cylinder fade out
|
||||
|
@ -221,10 +233,10 @@ public class MessageTransporterEffect implements IMessage, IMessageHandler<Messa
|
|||
}
|
||||
|
||||
if (WarpDriveConfig.LOGGING_EFFECTS) {
|
||||
WarpDrive.logger.info("Received transporter effect from %s to %s with %.3f lockStrength towards entity with id %d at %s, energizing in %d ticks, cooldown for %d ticks",
|
||||
messageSpawnParticle.vSource, messageSpawnParticle.vDestination, messageSpawnParticle.lockStrength,
|
||||
messageSpawnParticle.idEntity, messageSpawnParticle.v3EntityPosition,
|
||||
messageSpawnParticle.tickEnergizing, messageSpawnParticle.tickCooldown);
|
||||
WarpDrive.logger.info("Received transporter effect isTransporterRoom %s at %s towards %d entities, with %.3f lockStrength, energizing in %d ticks, cooldown for %d ticks",
|
||||
messageSpawnParticle.isTransporterRoom, messageSpawnParticle.globalPosition,
|
||||
messageSpawnParticle.idEntities.size(),
|
||||
messageSpawnParticle.lockStrength, messageSpawnParticle.tickEnergizing, messageSpawnParticle.tickCooldown);
|
||||
}
|
||||
|
||||
messageSpawnParticle.handle(Minecraft.getMinecraft().theWorld);
|
||||
|
|
|
@ -4,10 +4,12 @@ import cr0s.warpdrive.WarpDrive;
|
|||
import cr0s.warpdrive.config.WarpDriveConfig;
|
||||
import cr0s.warpdrive.data.CelestialObject;
|
||||
import cr0s.warpdrive.data.CloakedArea;
|
||||
import cr0s.warpdrive.data.GlobalPosition;
|
||||
import cr0s.warpdrive.data.MovingEntity;
|
||||
import cr0s.warpdrive.data.Vector3;
|
||||
import cr0s.warpdrive.data.VectorI;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
|
@ -115,27 +117,31 @@ public class PacketHandler {
|
|||
}
|
||||
|
||||
// Transporter effect sent to client side
|
||||
public static void sendTransporterEffectPacket(final World world, final VectorI vSource, final VectorI vDestination, final double lockStrength,
|
||||
final Entity entity, final Vector3 v3EntityPosition,
|
||||
final int tickEnergizing, final int tickCooldown, final int radius) {
|
||||
public static void sendTransporterEffectPacket(final World world, final GlobalPosition globalPositionLocal, final GlobalPosition globalPositionRemote, final double lockStrength,
|
||||
final Collection<MovingEntity> movingEntitiesLocal, final Collection<MovingEntity> movingEntitiesRemote,
|
||||
final int tickEnergizing, final int tickCooldown, final int radius) {
|
||||
assert(!world.isRemote);
|
||||
|
||||
final MessageTransporterEffect messageTransporterEffect = new MessageTransporterEffect(vSource, vDestination, lockStrength,
|
||||
entity, v3EntityPosition,
|
||||
tickEnergizing, tickCooldown);
|
||||
final MessageTransporterEffect messageTransporterEffectLocal = new MessageTransporterEffect(
|
||||
true, globalPositionLocal, movingEntitiesLocal,
|
||||
lockStrength, tickEnergizing, tickCooldown);
|
||||
final MessageTransporterEffect messageTransporterEffectRemote = new MessageTransporterEffect(
|
||||
false, globalPositionRemote, movingEntitiesRemote,
|
||||
lockStrength, tickEnergizing, tickCooldown);
|
||||
|
||||
// check both ends to send packet
|
||||
final List<EntityPlayerMP> playerEntityList = MinecraftServer.getServer().getConfigurationManager().playerEntityList;
|
||||
final int dimensionId = world.provider.dimensionId;
|
||||
final int radius_square = radius * radius;
|
||||
for (int index = 0; index < playerEntityList.size(); index++) {
|
||||
final EntityPlayerMP entityPlayerMP = playerEntityList.get(index);
|
||||
|
||||
if (entityPlayerMP.dimension == dimensionId) {
|
||||
if ( vSource.distance2To(entityPlayerMP) < radius_square
|
||||
|| vDestination.distance2To(entityPlayerMP) < radius_square ) {
|
||||
simpleNetworkManager.sendTo(messageTransporterEffect, entityPlayerMP);
|
||||
}
|
||||
if ( globalPositionLocal != null
|
||||
&& globalPositionLocal.distance2To(entityPlayerMP) < radius_square ) {
|
||||
simpleNetworkManager.sendTo(messageTransporterEffectLocal, entityPlayerMP);
|
||||
}
|
||||
if ( globalPositionRemote != null
|
||||
&& globalPositionRemote.distance2To(entityPlayerMP) < radius_square ) {
|
||||
simpleNetworkManager.sendTo(messageTransporterEffectRemote, entityPlayerMP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -297,7 +297,9 @@ tile.warpdrive.movement.ShipCore.name=Raumschiff Kern
|
|||
tile.warpdrive.movement.ShipCore.tooltip=Definiert dein Schiff relativ zur Steuerung. Schließe eine Energiequelle an, um den Kern zu laden.\nSollte horizontal neben der Steuerung plaziert werden.
|
||||
tile.warpdrive.movement.ShipCore.bounding_box.disabled=Bounding box display have been disabled.
|
||||
tile.warpdrive.movement.ShipCore.bounding_box.enabled=Bounding box display is now enabled. Only you can see it.\nSneak right-click the Ship core again to disable it.
|
||||
tile.warpdrive.movement.Transporter.name=Transporter
|
||||
tile.warpdrive.movement.transporter_containment.name=Transporter Containment
|
||||
tile.warpdrive.movement.transporter_core.name=Transporter Core
|
||||
tile.warpdrive.movement.transporter_scanner.name=Transporter Scanner
|
||||
|
||||
tile.warpdrive.weapon.LaserCamera.name=Laser und Kamera
|
||||
tile.warpdrive.weapon.WeaponController.name=Waffen Steuerung
|
||||
|
|
|
@ -294,7 +294,9 @@ tile.warpdrive.movement.ShipCore.name=Ship Core
|
|||
tile.warpdrive.movement.ShipCore.tooltip=Defines your ship center relative to the controller. Connecting an energy source will charge the core.\nShall be placed horizontally directly next to the Ship controller.
|
||||
tile.warpdrive.movement.ShipCore.bounding_box.disabled=Bounding box display have been disabled.
|
||||
tile.warpdrive.movement.ShipCore.bounding_box.enabled=Bounding box display is now enabled. Only you can see it.\nSneak right-click the Ship core again to disable it.
|
||||
tile.warpdrive.movement.Transporter.name=Transporter
|
||||
tile.warpdrive.movement.transporter_containment.name=Transporter Containment
|
||||
tile.warpdrive.movement.transporter_core.name=Transporter Core
|
||||
tile.warpdrive.movement.transporter_scanner.name=Transporter Scanner
|
||||
|
||||
tile.warpdrive.weapon.LaserCamera.name=Laser + Camera
|
||||
tile.warpdrive.weapon.WeaponController.name=Weapon Controller
|
||||
|
|
|
@ -292,7 +292,9 @@ tile.warpdrive.movement.ShipController.name=Controlleur de vaisseau
|
|||
tile.warpdrive.movement.ShipController.tooltip=Défini l'avant du vaisseau par rapport au coeur. Attache un ordinateur pour ouvrir l'interface utilisateur.\nDoit être placé horizontalement directement à coté du Coeur de vaisseau.
|
||||
tile.warpdrive.movement.ShipCore.name=Coeur de vaisseau
|
||||
tile.warpdrive.movement.ShipCore.tooltip=Défini le centre du vaisseau par rapport au controlleur. Connecte une source d'énergie pour charger le coeur\nDoit être placé horizontalement directement à coté du Controlleur de vaisseau.
|
||||
tile.warpdrive.movement.Transporter.name=Transporteur
|
||||
tile.warpdrive.movement.transporter_containment.name=Confinement de transporteur
|
||||
tile.warpdrive.movement.transporter_core.name=Cœur de transporteur
|
||||
tile.warpdrive.movement.transporter_scanner.name=Scanneur de transporteur
|
||||
|
||||
tile.warpdrive.weapon.LaserCamera.name=Laser + Caméra
|
||||
tile.warpdrive.weapon.WeaponController.name=Controlleur d'armement
|
||||
|
|
|
@ -294,7 +294,9 @@ tile.warpdrive.movement.ShipCore.name=Schip-Kern
|
|||
tile.warpdrive.movement.ShipCore.tooltip=Definieert uw schips-middelpunt ten opzichte van ships-bestuurder. Sluit een stroombron aan om de kern op te laden.\nMoet horizontaal naast een Schips-bestuurder worden geplaatst.
|
||||
tile.warpdrive.movement.ShipCore.bounding_box.disabled=Bounding box display have been disabled.
|
||||
tile.warpdrive.movement.ShipCore.bounding_box.enabled=Bounding box display is now enabled. Only you can see it.\nSneak right-click the Ship core again to disable it.
|
||||
tile.warpdrive.movement.Transporter.name=Transporteur
|
||||
tile.warpdrive.movement.transporter_containment.name=Transporter Containment
|
||||
tile.warpdrive.movement.transporter_core.name=Transporter Core
|
||||
tile.warpdrive.movement.transporter_scanner.name=Transporter Scanner
|
||||
|
||||
tile.warpdrive.weapon.LaserCamera.name=Laser met Camera
|
||||
tile.warpdrive.weapon.WeaponController.name=Wapens-Bestuurder
|
||||
|
|
|
@ -292,7 +292,9 @@ tile.warpdrive.movement.ShipController.name=Контроллер корабля
|
|||
tile.warpdrive.movement.ShipController.tooltip=Defines your ship front relative to the core. Attach a computer to open the user interface.\nShall be placed horizontally directly next to the Ship core.
|
||||
tile.warpdrive.movement.ShipCore.name=Ядро корабля
|
||||
tile.warpdrive.movement.ShipCore.tooltip=Defines your ship center relative to the controller. Connecting an energy source will charge the core.\nShall be placed horizontally directly next to the Ship controller.
|
||||
tile.warpdrive.movement.Transporter.name=Транспортер
|
||||
tile.warpdrive.movement.transporter_containment.name=Transporter Containment
|
||||
tile.warpdrive.movement.transporter_core.name=Транспортер
|
||||
tile.warpdrive.movement.transporter_scanner.name=Transporter Scanner
|
||||
|
||||
tile.warpdrive.weapon.LaserCamera.name=Камера с прикрепленным лазером
|
||||
tile.warpdrive.weapon.WeaponController.name=Контроллер оружия
|
||||
|
|
|
@ -294,7 +294,9 @@ tile.warpdrive.movement.ShipCore.name=飞船核心
|
|||
tile.warpdrive.movement.ShipCore.tooltip=相对于控制器以设定飞船中心.连接供能设备充能.\n必须水平紧贴控制器才能连接.
|
||||
tile.warpdrive.movement.ShipCore.bounding_box.disabled=边界显示已禁用.
|
||||
tile.warpdrive.movement.ShipCore.bounding_box.enabled=边界显示启用. 只有你可见.\n再次潜行右击核心可关闭.
|
||||
tile.warpdrive.movement.Transporter.name=传送台
|
||||
tile.warpdrive.movement.transporter_containment.name=Transporter Containment
|
||||
tile.warpdrive.movement.transporter_core.name=传送台
|
||||
tile.warpdrive.movement.transporter_scanner.name=Transporter Scanner
|
||||
|
||||
tile.warpdrive.weapon.LaserCamera.name=激光+相机
|
||||
tile.warpdrive.weapon.WeaponController.name=武器控制器
|
||||
|
|
|
@ -210,7 +210,9 @@ tile.warpdrive.forcefield.relay3.tooltip=支持在其網絡內共享最多1個
|
|||
tile.warpdrive.movement.Lift.name=升降機
|
||||
tile.warpdrive.movement.ShipController.name=船艦制禦器
|
||||
tile.warpdrive.movement.ShipCore.name=波動核心
|
||||
tile.warpdrive.movement.Transporter.name=運輸
|
||||
tile.warpdrive.movement.transporter_containment.name=Transporter Containment
|
||||
tile.warpdrive.movement.transporter_core.name=運輸
|
||||
tile.warpdrive.movement.transporter_scanner.name=Transporter Scanner
|
||||
|
||||
tile.warpdrive.weapon.LaserCamera.name=鐳射&攝像機
|
||||
tile.warpdrive.weapon.WeaponController.name=火控系統
|
||||
|
|
Loading…
Add table
Reference in a new issue