From bee50891611b46b14e0602d217ac5ab885f894e4 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Wed, 4 Sep 2013 17:52:05 +0400 Subject: [PATCH 01/56] merge upstream --- src/cr0s/WarpDrive/SpaceEventHandler.java | 222 ++++++++-------- src/cr0s/serverMods/AntiFallDamage.java | 74 +++--- src/cr0s/serverMods/LoginHookClass.java | 296 +++++++++++----------- 3 files changed, 296 insertions(+), 296 deletions(-) diff --git a/src/cr0s/WarpDrive/SpaceEventHandler.java b/src/cr0s/WarpDrive/SpaceEventHandler.java index 71a21242..c85888ee 100644 --- a/src/cr0s/WarpDrive/SpaceEventHandler.java +++ b/src/cr0s/WarpDrive/SpaceEventHandler.java @@ -1,111 +1,111 @@ -package cr0s.WarpDrive; - -import java.util.HashMap; - -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.util.DamageSource; -import net.minecraft.util.MathHelper; -import net.minecraftforge.common.DimensionManager; -import net.minecraftforge.event.ForgeSubscribe; -import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; - -/** - * Обработчик событий в мире Space - * @author Cr0s - */ -public class SpaceEventHandler { - private HashMap<String, Integer> vacuumPlayers; - - public SpaceEventHandler() { - vacuumPlayers = new HashMap<String, Integer>(); - } - - @ForgeSubscribe - public void livingUpdate(LivingUpdateEvent event) { - EntityLivingBase entity = event.entityLiving; - - if (Math.abs(MathHelper.floor_double(entity.posX)) > WarpDrive.WORLD_LIMIT_BLOCKS || Math.abs(MathHelper.floor_double(entity.posZ)) > WarpDrive.WORLD_LIMIT_BLOCKS) { - if (entity instanceof EntityPlayerMP) { - if (((EntityPlayerMP)entity).capabilities.isCreativeMode) { - return; - } - } - entity.attackEntityFrom(DamageSource.outOfWorld, 9000); - return; - } - - final int HELMET_ID_SKUBA = 30082; - final int HELMET_ID_HAZMAT = 14023; - final int HELMET_ID_QUANTUM = 30174; - final int AIR_CELL_ID = 30079; - - // Обновление происходит в космическом или гипер пространстве - if (entity.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID || entity.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) { - boolean inVacuum = isEntityInVacuum(entity); - - // Damage entity if in vacuum without protection - if (inVacuum) { - if (entity instanceof EntityPlayerMP) { - if (((EntityPlayerMP)entity).getCurrentArmor(3) != null && ((((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_SKUBA || ((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_HAZMAT) || ((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_QUANTUM)) { - Integer airValue = vacuumPlayers.get(((EntityPlayerMP)entity).username); - if (airValue == null) { - vacuumPlayers.put(((EntityPlayerMP)entity).username, 300); - airValue = 300; - } - - if (airValue <= 0) { - if (((EntityPlayerMP)entity).inventory.consumeInventoryItem(AIR_CELL_ID)) { - setPlayerAirValue(entity, 300); - } else { - setPlayerAirValue(entity, 0); - entity.attackEntityFrom(DamageSource.drown, 1); - } - } else { - setPlayerAirValue(entity, airValue - 1); - } - } else { - entity.attackEntityFrom(DamageSource.drown, 1); - } - - // Отправить назад на Землю - if (entity.posY < -10.0D) { - ((EntityPlayerMP)entity).mcServer.getConfigurationManager().transferPlayerToDimension(((EntityPlayerMP) entity), 0, new SpaceTeleporter(DimensionManager.getWorld(WarpDrive.instance.spaceDimID), 0, MathHelper.floor_double(entity.posX), 250, MathHelper.floor_double(entity.posZ))); - ((EntityPlayerMP)entity).setFire(30); - ((EntityPlayerMP)entity).setPositionAndUpdate(entity.posX, 250D, entity.posZ); - } - } else { - entity.attackEntityFrom(DamageSource.drown, 1); - } - } - } - } - - private void setPlayerAirValue(EntityLivingBase entity, Integer air) { - vacuumPlayers.remove(((EntityPlayerMP)entity).username); - vacuumPlayers.put(((EntityPlayerMP)entity).username, air); - } - - - /** - * Проверка, находится ли Entity в открытом космосе - * @param e - * @return - */ - private boolean isEntityInVacuum(Entity e) { - - int x = MathHelper.floor_double(e.posX); - int y = MathHelper.floor_double(e.posY); - int z = MathHelper.floor_double(e.posZ); - - int id1 = e.worldObj.getBlockId(x, y, z); - int id2 = e.worldObj.getBlockId(x, y + 1, z); - - if (id1 == WarpDrive.instance.config.airID || id2 == WarpDrive.instance.config.airID) { - return false; - } - - return true; - } -} +package cr0s.WarpDrive; + +import java.util.HashMap; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.DamageSource; +import net.minecraft.util.MathHelper; +import net.minecraftforge.common.DimensionManager; +import net.minecraftforge.event.ForgeSubscribe; +import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; + +/** + * Обработчик событий в мире Space + * @author Cr0s + */ +public class SpaceEventHandler { + private HashMap<String, Integer> vacuumPlayers; + + public SpaceEventHandler() { + vacuumPlayers = new HashMap<String, Integer>(); + } + + @ForgeSubscribe + public void livingUpdate(LivingUpdateEvent event) { + EntityLivingBase entity = event.entityLiving; + + if (Math.abs(MathHelper.floor_double(entity.posX)) > WarpDrive.WORLD_LIMIT_BLOCKS || Math.abs(MathHelper.floor_double(entity.posZ)) > WarpDrive.WORLD_LIMIT_BLOCKS) { + if (entity instanceof EntityPlayerMP) { + if (((EntityPlayerMP)entity).capabilities.isCreativeMode) { + return; + } + } + entity.attackEntityFrom(DamageSource.outOfWorld, 9000); + return; + } + + final int HELMET_ID_SKUBA = 30082; + final int HELMET_ID_HAZMAT = 14023; + final int HELMET_ID_QUANTUM = 30174; + final int AIR_CELL_ID = 30079; + + // Обновление происходит в космическом или гипер пространстве + if (entity.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID || entity.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) { + boolean inVacuum = isEntityInVacuum(entity); + + // Damage entity if in vacuum without protection + if (inVacuum) { + if (entity instanceof EntityPlayerMP) { + if (((EntityPlayerMP)entity).getCurrentArmor(3) != null && ((((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_SKUBA || ((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_HAZMAT) || ((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_QUANTUM)) { + Integer airValue = vacuumPlayers.get(((EntityPlayerMP)entity).username); + if (airValue == null) { + vacuumPlayers.put(((EntityPlayerMP)entity).username, 300); + airValue = 300; + } + + if (airValue <= 0) { + if (((EntityPlayerMP)entity).inventory.consumeInventoryItem(AIR_CELL_ID)) { + setPlayerAirValue(entity, 300); + } else { + setPlayerAirValue(entity, 0); + entity.attackEntityFrom(DamageSource.drown, 1); + } + } else { + setPlayerAirValue(entity, airValue - 1); + } + } else { + entity.attackEntityFrom(DamageSource.drown, 1); + } + + // Отправить назад на Землю + if (entity.posY < -10.0D) { + ((EntityPlayerMP)entity).mcServer.getConfigurationManager().transferPlayerToDimension(((EntityPlayerMP) entity), 0, new SpaceTeleporter(DimensionManager.getWorld(WarpDrive.instance.spaceDimID), 0, MathHelper.floor_double(entity.posX), 250, MathHelper.floor_double(entity.posZ))); + ((EntityPlayerMP)entity).setFire(30); + ((EntityPlayerMP)entity).setPositionAndUpdate(entity.posX, 250D, entity.posZ); + } + } else { + entity.attackEntityFrom(DamageSource.drown, 1); + } + } + } + } + + private void setPlayerAirValue(EntityLivingBase entity, Integer air) { + vacuumPlayers.remove(((EntityPlayerMP)entity).username); + vacuumPlayers.put(((EntityPlayerMP)entity).username, air); + } + + + /** + * Проверка, находится ли Entity в открытом космосе + * @param e + * @return + */ + private boolean isEntityInVacuum(Entity e) { + + int x = MathHelper.floor_double(e.posX); + int y = MathHelper.floor_double(e.posY); + int z = MathHelper.floor_double(e.posZ); + + int id1 = e.worldObj.getBlockId(x, y, z); + int id2 = e.worldObj.getBlockId(x, y + 1, z); + + if (id1 == WarpDrive.instance.config.airID || id2 == WarpDrive.instance.config.airID) { + return false; + } + + return true; + } +} diff --git a/src/cr0s/serverMods/AntiFallDamage.java b/src/cr0s/serverMods/AntiFallDamage.java index fbd5aa9b..807d88f7 100644 --- a/src/cr0s/serverMods/AntiFallDamage.java +++ b/src/cr0s/serverMods/AntiFallDamage.java @@ -1,37 +1,37 @@ -package cr0s.serverMods; - -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.util.MathHelper; -import net.minecraftforge.event.ForgeSubscribe; -import net.minecraftforge.event.entity.living.LivingFallEvent; - -/** - * Гашение урона при падении с джетпаком или квантовыми бутсами - * @author Cr0s - */ -public class AntiFallDamage { - private final int JETPACK_ID = 30210; - private final int ELECTRIC_JETPACK_ID = 30209; - private final int QUANTUM_BOOTS_ID = 30171; - - @ForgeSubscribe - public void livingFall(LivingFallEvent event) { - EntityLivingBase entity = event.entityLiving; - float distance = event.distance; - - if (entity instanceof EntityPlayer) { - EntityPlayer player = (EntityPlayer) entity; - - int check = MathHelper.ceiling_float_int(distance - 3.0F); - if (check > 0) { // Падение может нанести урон - // Проверяем наличие защиты - if ((player.getCurrentArmor(0) != null && player.getCurrentArmor(0).itemID == QUANTUM_BOOTS_ID) || - (player.getCurrentArmor(2) != null && player.getCurrentArmor(2).itemID == JETPACK_ID) || - (player.getCurrentArmor(2) != null && player.getCurrentArmor(2).itemID == ELECTRIC_JETPACK_ID)) { - event.setCanceled(true); // Блокируем падение, если защита есть - } - } - } - } -} +package cr0s.serverMods; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.MathHelper; +import net.minecraftforge.event.ForgeSubscribe; +import net.minecraftforge.event.entity.living.LivingFallEvent; + +/** + * Гашение урона при падении с джетпаком или квантовыми бутсами + * @author Cr0s + */ +public class AntiFallDamage { + private final int JETPACK_ID = 30210; + private final int ELECTRIC_JETPACK_ID = 30209; + private final int QUANTUM_BOOTS_ID = 30171; + + @ForgeSubscribe + public void livingFall(LivingFallEvent event) { + EntityLivingBase entity = event.entityLiving; + float distance = event.distance; + + if (entity instanceof EntityPlayer) { + EntityPlayer player = (EntityPlayer) entity; + + int check = MathHelper.ceiling_float_int(distance - 3.0F); + if (check > 0) { // Падение может нанести урон + // Проверяем наличие защиты + if ((player.getCurrentArmor(0) != null && player.getCurrentArmor(0).itemID == QUANTUM_BOOTS_ID) || + (player.getCurrentArmor(2) != null && player.getCurrentArmor(2).itemID == JETPACK_ID) || + (player.getCurrentArmor(2) != null && player.getCurrentArmor(2).itemID == ELECTRIC_JETPACK_ID)) { + event.setCanceled(true); // Блокируем падение, если защита есть + } + } + } + } +} diff --git a/src/cr0s/serverMods/LoginHookClass.java b/src/cr0s/serverMods/LoginHookClass.java index a6beaa1e..d983054e 100644 --- a/src/cr0s/serverMods/LoginHookClass.java +++ b/src/cr0s/serverMods/LoginHookClass.java @@ -1,149 +1,149 @@ -package cr0s.serverMods; - -import cpw.mods.fml.common.network.IConnectionHandler; -import cpw.mods.fml.common.network.Player; -import java.io.*; -import java.util.logging.Level; -import java.util.logging.Logger; -import net.minecraft.network.INetworkManager; -import net.minecraft.network.NetLoginHandler; -import net.minecraft.network.packet.NetHandler; -import net.minecraft.network.packet.Packet1Login; -import net.minecraft.server.MinecraftServer; - -/** - * Авторизация РЅРёРє.пароль - * @author Cr0s - */ -public class LoginHookClass implements IConnectionHandler { - - private String kickReason = ""; - private File uFile; - - public LoginHookClass() { - uFile = MinecraftServer.getServer().getFile("users.txt"); - } - - private void checkLogin(NetLoginHandler netHandler) throws FileNotFoundException, IOException { - String s = netHandler.clientUsername; - System.out.println("[SERVER MODS] Logging in user: " + s); - - BufferedReader bufferedreader = new BufferedReader(new FileReader(uFile)); - - if (s.indexOf(".") == -1 || s.split("\\.").length != 2) { - kickReason = "Никнейм Рё пароль должны быть разделены точками."; - bufferedreader.close(); - return; - } - - if (!s.matches("^[a-zA-Z0-9_.]+$")) { - kickReason = "Р�РјСЏ пользователя или пароль содержат недопустимые символы."; - bufferedreader.close(); - return; - } - - String s4 = s.split("\\.")[0].trim(); - String s5 = s.split("\\.")[1].trim(); - - if (s4.length() < 2 && !s4.equals("Q")) { - kickReason = "Р�РјСЏ пользователя слишком короткое."; - bufferedreader.close(); - return; - } - - if (s5.length() < 3) { - kickReason = "Пароль слишком короткий."; - bufferedreader.close(); - return; - } - - if (s4.length() > 15) { - kickReason = "\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u0434\u043B\u0438\u043D\u043D\u044B\u0439 \u043B\u043E\u0433\u0438\u043D! (>15)"; - bufferedreader.close(); - return; - } - - String s1; - - while ((s1 = bufferedreader.readLine()) != null) { - String s2; - String s3; - - try { - s2 = s1.split("\\.")[0]; - s3 = s1.split("\\.")[1]; - } catch (Exception exception) { - kickReason = "login.password error, database is corrupted."; - bufferedreader.close(); - return; - } - - if (s2.toLowerCase().equals(s4.toLowerCase())) { - if (!s3.equals(s5)) { - kickReason = "Неправильный пароль!"; - System.out.println((new StringBuilder()).append(netHandler.clientUsername).append(" failed to login (pwd: ").append(s3).append(")").toString()); - bufferedreader.close(); - return; - } else { - bufferedreader.close(); - return; - } - } - } - - bufferedreader.close(); - - // Создаём новый аккаунт - PrintWriter printwriter = new PrintWriter(new FileWriter(uFile, true)); - printwriter.println(s); - printwriter.close(); - - kickReason = ""; - } - - @Override - public void playerLoggedIn(Player player, NetHandler netHandler, INetworkManager manager) { - //throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public String connectionReceived(NetLoginHandler netHandler, INetworkManager manager) { - kickReason = ""; - - try { - checkLogin(netHandler); - } catch (FileNotFoundException ex) { - Logger.getLogger(LoginHookClass.class.getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { - Logger.getLogger(LoginHookClass.class.getName()).log(Level.SEVERE, null, ex); - } - - // РќРµ кикать - if (kickReason.isEmpty()) { - // Удалить пароль РёР· имени пользователя - netHandler.clientUsername = netHandler.clientUsername.split("\\.")[0]; - } - - return kickReason; - } - - @Override - public void connectionOpened(NetHandler netClientHandler, String server, int port, INetworkManager manager) { - //throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void connectionOpened(NetHandler netClientHandler, MinecraftServer server, INetworkManager manager) { - //throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void connectionClosed(INetworkManager manager) { - //throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void clientLoggedIn(NetHandler clientHandler, INetworkManager manager, Packet1Login login) { - throw new UnsupportedOperationException("Not supported yet."); - } +package cr0s.serverMods; + +import cpw.mods.fml.common.network.IConnectionHandler; +import cpw.mods.fml.common.network.Player; +import java.io.*; +import java.util.logging.Level; +import java.util.logging.Logger; +import net.minecraft.network.INetworkManager; +import net.minecraft.network.NetLoginHandler; +import net.minecraft.network.packet.NetHandler; +import net.minecraft.network.packet.Packet1Login; +import net.minecraft.server.MinecraftServer; + +/** + * Авторизация РЅРёРє.пароль + * @author Cr0s + */ +public class LoginHookClass implements IConnectionHandler { + + private String kickReason = ""; + private File uFile; + + public LoginHookClass() { + uFile = MinecraftServer.getServer().getFile("users.txt"); + } + + private void checkLogin(NetLoginHandler netHandler) throws FileNotFoundException, IOException { + String s = netHandler.clientUsername; + System.out.println("[SERVER MODS] Logging in user: " + s); + + BufferedReader bufferedreader = new BufferedReader(new FileReader(uFile)); + + if (s.indexOf(".") == -1 || s.split("\\.").length != 2) { + kickReason = "Никнейм Рё пароль должны быть разделены точками."; + bufferedreader.close(); + return; + } + + if (!s.matches("^[a-zA-Z0-9_.]+$")) { + kickReason = "Р�РјСЏ пользователя или пароль содержат недопустимые символы."; + bufferedreader.close(); + return; + } + + String s4 = s.split("\\.")[0].trim(); + String s5 = s.split("\\.")[1].trim(); + + if (s4.length() < 2 && !s4.equals("Q")) { + kickReason = "Р�РјСЏ пользователя слишком короткое."; + bufferedreader.close(); + return; + } + + if (s5.length() < 3) { + kickReason = "Пароль слишком короткий."; + bufferedreader.close(); + return; + } + + if (s4.length() > 15) { + kickReason = "\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u0434\u043B\u0438\u043D\u043D\u044B\u0439 \u043B\u043E\u0433\u0438\u043D! (>15)"; + bufferedreader.close(); + return; + } + + String s1; + + while ((s1 = bufferedreader.readLine()) != null) { + String s2; + String s3; + + try { + s2 = s1.split("\\.")[0]; + s3 = s1.split("\\.")[1]; + } catch (Exception exception) { + kickReason = "login.password error, database is corrupted."; + bufferedreader.close(); + return; + } + + if (s2.toLowerCase().equals(s4.toLowerCase())) { + if (!s3.equals(s5)) { + kickReason = "Неправильный пароль!"; + System.out.println((new StringBuilder()).append(netHandler.clientUsername).append(" failed to login (pwd: ").append(s3).append(")").toString()); + bufferedreader.close(); + return; + } else { + bufferedreader.close(); + return; + } + } + } + + bufferedreader.close(); + + // Создаём новый аккаунт + PrintWriter printwriter = new PrintWriter(new FileWriter(uFile, true)); + printwriter.println(s); + printwriter.close(); + + kickReason = ""; + } + + @Override + public void playerLoggedIn(Player player, NetHandler netHandler, INetworkManager manager) { + //throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String connectionReceived(NetLoginHandler netHandler, INetworkManager manager) { + kickReason = ""; + + try { + checkLogin(netHandler); + } catch (FileNotFoundException ex) { + Logger.getLogger(LoginHookClass.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(LoginHookClass.class.getName()).log(Level.SEVERE, null, ex); + } + + // РќРµ кикать + if (kickReason.isEmpty()) { + // Удалить пароль РёР· имени пользователя + netHandler.clientUsername = netHandler.clientUsername.split("\\.")[0]; + } + + return kickReason; + } + + @Override + public void connectionOpened(NetHandler netClientHandler, String server, int port, INetworkManager manager) { + //throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void connectionOpened(NetHandler netClientHandler, MinecraftServer server, INetworkManager manager) { + //throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void connectionClosed(INetworkManager manager) { + //throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void clientLoggedIn(NetHandler clientHandler, INetworkManager manager, Packet1Login login) { + throw new UnsupportedOperationException("Not supported yet."); + } } \ No newline at end of file From ae7e1442b79baeb788d05575a052fc75a053d964 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Fri, 15 Nov 2013 19:48:56 +0400 Subject: [PATCH 02/56] =?UTF-8?q?=D0=9A=D1=80=D0=BE=D1=81=20=D0=BD=D0=B5?= =?UTF-8?q?=20=D0=BD=D1=83=D0=B6=D0=B5=D0=BD.=201.6.4,=20IC2=20Experimenta?= =?UTF-8?q?l,=20=D0=BB=D0=B0=D0=B7=D0=BE=D1=80=D1=8B=20=D0=BC=D0=BE=D0=B3?= =?UTF-8?q?=D1=83=D1=82=20=D0=B2=20=D0=90=D0=95=20=D0=B8=D0=BD=D1=82=D0=B5?= =?UTF-8?q?=D1=80=D1=84=D0=B5=D0=B9=D1=81,=20=D0=BD=D0=BE=D1=80=D0=BC?= =?UTF-8?q?=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D1=81=D0=BE=D0=BE=D0=B1?= =?UTF-8?q?=D1=89=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D0=B0=D0=B2=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8,=20=D1=88?= =?UTF-8?q?=D0=BB=D1=8E=D0=BF=D0=BA=D0=B8=20-=20=D1=87=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B4=D0=B0=20=D0=B1=D0=B0=D0=B3=D0=BE=D0=B2=20=D0=B8=20=D0=BD?= =?UTF-8?q?=D0=B5=20=D0=BD=D1=83=D0=B6=D0=BD=D1=8B.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 22 - src/cr0s/WarpDrive/BiomeSpace.java | 21 +- src/cr0s/WarpDrive/BlockAir.java | 166 +- src/cr0s/WarpDrive/BlockAirGenerator.java | 72 +- src/cr0s/WarpDrive/BlockCamera.java | 26 +- src/cr0s/WarpDrive/BlockGas.java | 35 +- src/cr0s/WarpDrive/BlockIridium.java | 3 +- src/cr0s/WarpDrive/BlockLaser.java | 26 +- src/cr0s/WarpDrive/BlockLaserCam.java | 26 +- src/cr0s/WarpDrive/BlockLift.java | 70 +- src/cr0s/WarpDrive/BlockMiningLaser.java | 30 +- src/cr0s/WarpDrive/BlockMonitor.java | 71 +- src/cr0s/WarpDrive/BlockParticleBooster.java | 60 +- src/cr0s/WarpDrive/BlockProtocol.java | 48 +- src/cr0s/WarpDrive/BlockRadar.java | 73 +- src/cr0s/WarpDrive/BlockReactor.java | 68 +- src/cr0s/WarpDrive/BlockWarpIsolation.java | 16 +- src/cr0s/WarpDrive/CamRegistry.java | 110 +- src/cr0s/WarpDrive/CamRegistryItem.java | 35 +- src/cr0s/WarpDrive/CameraOverlay.java | 58 +- src/cr0s/WarpDrive/ClientCameraUtils.java | 60 +- src/cr0s/WarpDrive/ClientProxy.java | 19 +- src/cr0s/WarpDrive/CloudRenderBlank.java | 1 - src/cr0s/WarpDrive/CommonProxy.java | 20 +- src/cr0s/WarpDrive/EntityCamera.java | 263 +-- src/cr0s/WarpDrive/EntityJump.java | 712 ++++---- src/cr0s/WarpDrive/EntitySphereGen.java | 300 ++-- src/cr0s/WarpDrive/EntityStarCore.java | 93 +- src/cr0s/WarpDrive/FXBeam.java | 475 +++--- src/cr0s/WarpDrive/GenerateCommand.java | 75 +- src/cr0s/WarpDrive/GravityManager.java | 119 +- src/cr0s/WarpDrive/HyperSpaceGenerator.java | 53 +- src/cr0s/WarpDrive/HyperSpaceProvider.java | 128 +- src/cr0s/WarpDrive/HyperSpaceSkyRenderer.java | 8 +- .../WarpDrive/HyperSpaceWorldGenerator.java | 14 +- src/cr0s/WarpDrive/InvisibleCommand.java | 35 +- src/cr0s/WarpDrive/JumpGate.java | 31 +- src/cr0s/WarpDrive/JumpGateGenerator.java | 34 +- src/cr0s/WarpDrive/JumpGatesRegistry.java | 145 +- src/cr0s/WarpDrive/LocalProfiler.java | 23 +- src/cr0s/WarpDrive/MovingEntity.java | 11 +- src/cr0s/WarpDrive/PacketHandler.java | 276 +-- src/cr0s/WarpDrive/SoundHandler.java | 9 +- src/cr0s/WarpDrive/SpaceEventHandler.java | 108 +- src/cr0s/WarpDrive/SpaceGenerator.java | 54 +- src/cr0s/WarpDrive/SpaceProvider.java | 160 +- src/cr0s/WarpDrive/SpaceSkyRenderer.java | 22 +- src/cr0s/WarpDrive/SpaceTeleporter.java | 18 +- src/cr0s/WarpDrive/SpaceTpCommand.java | 41 +- src/cr0s/WarpDrive/SpaceWorldGenerator.java | 471 ++--- .../WarpDrive/TileEntityAirGenerator.java | 142 +- src/cr0s/WarpDrive/TileEntityCamera.java | 182 +- src/cr0s/WarpDrive/TileEntityLaser.java | 986 ++++++----- src/cr0s/WarpDrive/TileEntityLift.java | 405 +++-- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 887 +++++----- src/cr0s/WarpDrive/TileEntityMonitor.java | 152 +- .../WarpDrive/TileEntityParticleBooster.java | 140 +- src/cr0s/WarpDrive/TileEntityProtocol.java | 460 ++--- src/cr0s/WarpDrive/TileEntityRadar.java | 228 +-- src/cr0s/WarpDrive/TileEntityReactor.java | 880 ++++++---- src/cr0s/WarpDrive/Vector3.java | 1512 +++++++++-------- src/cr0s/WarpDrive/WarpCoresRegistry.java | 169 +- src/cr0s/WarpDrive/WarpDrive.java | 229 ++- src/cr0s/WarpDrive/WarpDriveConfig.java | 87 +- src/cr0s/WarpDrive/WorldGenSmallShip.java | 1323 ++++++++------- src/cr0s/WarpDrive/WorldGenStation.java | 12 +- src/cr0s/WarpDrive/WorldGenStructure.java | 45 +- src/cr0s/WarpDrive/client/ClientProxy.java | 19 +- .../WarpDriveCore/WCClassTransformer.java | 118 +- src/cr0s/WarpDriveCore/WCDummyContainer.java | 80 +- .../WarpDriveCore/WCFMLLoadingPlugin.java | 62 +- src/cr0s/serverMods/AntiFallDamage.java | 19 +- src/cr0s/serverMods/CommonProxy.java | 7 +- src/cr0s/serverMods/LoginHookClass.java | 216 ++- src/cr0s/serverMods/ServerMods.java | 50 +- src/shipmod/BlockID.java | 195 --- src/shipmod/BlockMetaRotation.java | 41 - src/shipmod/ClientProxy.java | 37 - src/shipmod/CommonProxy.java | 10 - src/shipmod/ConnectionHandler.java | 27 - src/shipmod/ForgeHookContainer.java | 31 - src/shipmod/MetaRotations$1.java | 19 - src/shipmod/MetaRotations.java | 723 -------- src/shipmod/PacketHandler.java | 134 -- src/shipmod/ShipMod.java | 119 -- src/shipmod/ShipModConfig.java | 81 - src/shipmod/blockitem/BlockMarkShip.java | 184 -- src/shipmod/blockitem/ItemCreateShip.java | 69 - src/shipmod/chunk/ChunkBuilder.java | 233 --- src/shipmod/chunk/LocatedBlock.java | 22 - src/shipmod/chunk/MobileChunk.java | 640 ------- ...hunkBuilder$ShipSizeOverflowException.java | 5 - .../chunk/ShipSizeOverflowException.java | 5 - src/shipmod/command/CommandAlignShip.java | 50 - src/shipmod/command/CommandDismountShip.java | 65 - src/shipmod/command/CommandHelp.java | 58 - src/shipmod/command/CommandKillShip.java | 102 -- .../command/CommandReloadMetaRotations.java | 28 - src/shipmod/command/CommandShipInfo.java | 54 - src/shipmod/command/CommandTpShip.java | 115 -- src/shipmod/control/ShipController.java | 19 - src/shipmod/control/ShipControllerClient.java | 20 - src/shipmod/control/ShipKeyHandler.java | 123 -- src/shipmod/entity/EntityShip.java | 1320 -------------- src/shipmod/entity/IShipTileEntity.java | 6 - src/shipmod/entity/ShipCapabilities.java | 42 - src/shipmod/render/MobileChunkRenderer.java | 254 --- src/shipmod/render/RenderShip.java | 50 - src/shipmod/util/AABBRotator.java | 51 - src/shipmod/util/MathHelperMod.java | 16 - src/shipmod/util/StackSafeFiller.java | 37 - 111 files changed, 7187 insertions(+), 11022 deletions(-) delete mode 100644 .gitattributes delete mode 100644 src/shipmod/BlockID.java delete mode 100644 src/shipmod/BlockMetaRotation.java delete mode 100644 src/shipmod/ClientProxy.java delete mode 100644 src/shipmod/CommonProxy.java delete mode 100644 src/shipmod/ConnectionHandler.java delete mode 100644 src/shipmod/ForgeHookContainer.java delete mode 100644 src/shipmod/MetaRotations$1.java delete mode 100644 src/shipmod/MetaRotations.java delete mode 100644 src/shipmod/PacketHandler.java delete mode 100644 src/shipmod/ShipMod.java delete mode 100644 src/shipmod/ShipModConfig.java delete mode 100644 src/shipmod/blockitem/BlockMarkShip.java delete mode 100644 src/shipmod/blockitem/ItemCreateShip.java delete mode 100644 src/shipmod/chunk/ChunkBuilder.java delete mode 100644 src/shipmod/chunk/LocatedBlock.java delete mode 100644 src/shipmod/chunk/MobileChunk.java delete mode 100644 src/shipmod/chunk/ShipChunkBuilder$ShipSizeOverflowException.java delete mode 100644 src/shipmod/chunk/ShipSizeOverflowException.java delete mode 100644 src/shipmod/command/CommandAlignShip.java delete mode 100644 src/shipmod/command/CommandDismountShip.java delete mode 100644 src/shipmod/command/CommandHelp.java delete mode 100644 src/shipmod/command/CommandKillShip.java delete mode 100644 src/shipmod/command/CommandReloadMetaRotations.java delete mode 100644 src/shipmod/command/CommandShipInfo.java delete mode 100644 src/shipmod/command/CommandTpShip.java delete mode 100644 src/shipmod/control/ShipController.java delete mode 100644 src/shipmod/control/ShipControllerClient.java delete mode 100644 src/shipmod/control/ShipKeyHandler.java delete mode 100644 src/shipmod/entity/EntityShip.java delete mode 100644 src/shipmod/entity/IShipTileEntity.java delete mode 100644 src/shipmod/entity/ShipCapabilities.java delete mode 100644 src/shipmod/render/MobileChunkRenderer.java delete mode 100644 src/shipmod/render/RenderShip.java delete mode 100644 src/shipmod/util/AABBRotator.java delete mode 100644 src/shipmod/util/MathHelperMod.java delete mode 100644 src/shipmod/util/StackSafeFiller.java diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 412eeda7..00000000 --- a/.gitattributes +++ /dev/null @@ -1,22 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.cs diff=csharp -*.sln merge=union -*.csproj merge=union -*.vbproj merge=union -*.fsproj merge=union -*.dbproj merge=union - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/src/cr0s/WarpDrive/BiomeSpace.java b/src/cr0s/WarpDrive/BiomeSpace.java index 22d92051..cc74a0d8 100644 --- a/src/cr0s/WarpDrive/BiomeSpace.java +++ b/src/cr0s/WarpDrive/BiomeSpace.java @@ -2,11 +2,11 @@ package cr0s.WarpDrive; import net.minecraft.world.biome.BiomeGenBase; -public class BiomeSpace extends BiomeGenBase { - - public BiomeSpace(int par1) { +public class BiomeSpace extends BiomeGenBase +{ + public BiomeSpace(int par1) + { super(par1); - this.theBiomeDecorator.treesPerChunk = 0; //this.temperature = 1F; this.theBiomeDecorator.flowersPerChunk = 0; @@ -15,17 +15,20 @@ public class BiomeSpace extends BiomeGenBase { } @Override - public float getSpawningChance() { + public float getSpawningChance() + { return 0; } - + @Override - public boolean canSpawnLightningBolt() { + public boolean canSpawnLightningBolt() + { return false; } - + @Override - public boolean getEnableSnow() { + public boolean getEnableSnow() + { return false; } } diff --git a/src/cr0s/WarpDrive/BlockAir.java b/src/cr0s/WarpDrive/BlockAir.java index eed2d3fa..8546fdb7 100644 --- a/src/cr0s/WarpDrive/BlockAir.java +++ b/src/cr0s/WarpDrive/BlockAir.java @@ -1,6 +1,5 @@ package cr0s.WarpDrive; -import cr0s.WarpDrive.WarpDrive; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.material.Material; @@ -12,7 +11,7 @@ import net.minecraft.world.World; public class BlockAir extends Block { private final boolean TRANSPARENT_AIR = true; - + public BlockAir(int par1) { super(par1, Material.air); @@ -65,7 +64,7 @@ public class BlockAir extends Block { this.blockIcon = par1IconRegister.registerIcon("warpdrive:airBlock"); } - + @Override public int getMobilityFlag() { @@ -78,7 +77,6 @@ public class BlockAir extends Block return -1; } - /** * Returns the quantity of items to drop on block destruction. */ @@ -95,8 +93,8 @@ public class BlockAir extends Block public int tickRate(World par1World) { return 20; - } - + } + /** * Ticks the block if it's been scheduled */ @@ -105,18 +103,21 @@ public class BlockAir extends Block { int concentration = par1World.getBlockMetadata(x, y, z); boolean isInSpaceWorld = par1World.provider.dimensionId == WarpDrive.instance.spaceDimID || par1World.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID; - + // Remove air block to vacuum block - if (concentration <= 0 || !isInSpaceWorld) { + if (concentration <= 0 || !isInSpaceWorld) + { //System.out.println("Killing air block"); par1World.setBlock(x, y, z, 0, 0, 2); // replace our air block to vacuum block - } else { + } + else + { //System.out.println("Conc: current " + concentration + " new: " + (concentration - 1) + " to spread: " + (concentration - 2)); - // Try to spread the air + // Try to spread the air spreadAirBlock(par1World, x, y, z, concentration); } - - par1World.scheduleBlockUpdate(x, y, z, this.blockID, 20); + + par1World.scheduleBlockUpdate(x, y, z, this.blockID, 20); } @Override @@ -167,73 +168,95 @@ public class BlockAir extends Block return false; } } - } - - private void spreadAirBlock(World worldObj, int x, int y, int z, int concentration) { - if (concentration <= 0) { + } + + private void spreadAirBlock(World worldObj, int x, int y, int z, int concentration) + { + if (concentration <= 0) + { return; } - int mid_concentration; - int block_count = 1; - + int mid_concentration; + int block_count = 1; final int K = 128; - - mid_concentration = worldObj.getBlockMetadata(x, y, z) * K; - - if(worldObj.isAirBlock(x + 1, y, z)){ - block_count++; - mid_concentration += worldObj.getBlockMetadata(x + 1, y, z) * K; - } - if(worldObj.isAirBlock(x - 1, y, z)){ - block_count++; - mid_concentration += worldObj.getBlockMetadata(x - 1, y, z) * K; - } - if(worldObj.isAirBlock(x, y + 1, z)){ - block_count++; - mid_concentration += worldObj.getBlockMetadata(x, y + 1, z) * K; - } - if(worldObj.isAirBlock(x, y - 1, z)){ - block_count++; - mid_concentration += worldObj.getBlockMetadata(x, y - 1, z) * K; - } - if(worldObj.isAirBlock(x, y, z + 1)){ - block_count++; - mid_concentration += worldObj.getBlockMetadata(x, y, z + 1) * K; - } - if(worldObj.isAirBlock(x, y, z - 1)){ - block_count++; - mid_concentration += worldObj.getBlockMetadata(x, y, z - 1) * K; - } + mid_concentration = worldObj.getBlockMetadata(x, y, z) * K; - mid_concentration = mid_concentration / block_count; - - SetAirBlockConcentration(worldObj, x, y, z, mid_concentration / K); - - if(worldObj.isAirBlock(x + 1, y, z) && (mid_concentration>worldObj.getBlockMetadata(x+1, y, z) * K)){ - SetAirBlockConcentration(worldObj, x+1, y, z, mid_concentration / K); - } - if(worldObj.isAirBlock(x - 1, y, z) && (mid_concentration>worldObj.getBlockMetadata(x-1, y, z) * K)){ - SetAirBlockConcentration(worldObj, x-1, y, z, mid_concentration / K); - } - if(worldObj.isAirBlock(x, y + 1, z) && (mid_concentration>worldObj.getBlockMetadata(x, y+1, z) * K)){ - SetAirBlockConcentration(worldObj, x, y + 1, z, mid_concentration / K); - } - if(worldObj.isAirBlock(x, y - 1, z) && (mid_concentration>worldObj.getBlockMetadata(x, y-1, z) * K)){ - SetAirBlockConcentration(worldObj, x, y - 1, z, mid_concentration / K); - } - if(worldObj.isAirBlock(x, y, z + 1) && (mid_concentration>worldObj.getBlockMetadata(x, y, z+1) * K)){ - SetAirBlockConcentration(worldObj, x, y, z + 1, mid_concentration / K); - } - if(worldObj.isAirBlock(x, y, z - 1) && (mid_concentration>worldObj.getBlockMetadata(x, y, z-1) * K)){ - SetAirBlockConcentration(worldObj, x, y, z - 1, mid_concentration / K); + if (worldObj.isAirBlock(x + 1, y, z)) + { + block_count++; + mid_concentration += worldObj.getBlockMetadata(x + 1, y, z) * K; + } + + if (worldObj.isAirBlock(x - 1, y, z)) + { + block_count++; + mid_concentration += worldObj.getBlockMetadata(x - 1, y, z) * K; + } + + if (worldObj.isAirBlock(x, y + 1, z)) + { + block_count++; + mid_concentration += worldObj.getBlockMetadata(x, y + 1, z) * K; + } + + if (worldObj.isAirBlock(x, y - 1, z)) + { + block_count++; + mid_concentration += worldObj.getBlockMetadata(x, y - 1, z) * K; + } + + if (worldObj.isAirBlock(x, y, z + 1)) + { + block_count++; + mid_concentration += worldObj.getBlockMetadata(x, y, z + 1) * K; + } + + if (worldObj.isAirBlock(x, y, z - 1)) + { + block_count++; + mid_concentration += worldObj.getBlockMetadata(x, y, z - 1) * K; + } + + mid_concentration = mid_concentration / block_count; + SetAirBlockConcentration(worldObj, x, y, z, mid_concentration / K); + + if (worldObj.isAirBlock(x + 1, y, z) && (mid_concentration > worldObj.getBlockMetadata(x + 1, y, z) * K)) + { + SetAirBlockConcentration(worldObj, x + 1, y, z, mid_concentration / K); + } + + if (worldObj.isAirBlock(x - 1, y, z) && (mid_concentration > worldObj.getBlockMetadata(x - 1, y, z) * K)) + { + SetAirBlockConcentration(worldObj, x - 1, y, z, mid_concentration / K); + } + + if (worldObj.isAirBlock(x, y + 1, z) && (mid_concentration > worldObj.getBlockMetadata(x, y + 1, z) * K)) + { + SetAirBlockConcentration(worldObj, x, y + 1, z, mid_concentration / K); + } + + if (worldObj.isAirBlock(x, y - 1, z) && (mid_concentration > worldObj.getBlockMetadata(x, y - 1, z) * K)) + { + SetAirBlockConcentration(worldObj, x, y - 1, z, mid_concentration / K); + } + + if (worldObj.isAirBlock(x, y, z + 1) && (mid_concentration > worldObj.getBlockMetadata(x, y, z + 1) * K)) + { + SetAirBlockConcentration(worldObj, x, y, z + 1, mid_concentration / K); + } + + if (worldObj.isAirBlock(x, y, z - 1) && (mid_concentration > worldObj.getBlockMetadata(x, y, z - 1) * K)) + { + SetAirBlockConcentration(worldObj, x, y, z - 1, mid_concentration / K); } } - private void SetAirBlockConcentration(World worldObj, int x, int y, int z, int concentration) { - worldObj.setBlock(x, y, z, this.blockID, concentration, 2); + private void SetAirBlockConcentration(World worldObj, int x, int y, int z, int concentration) + { + worldObj.setBlock(x, y, z, this.blockID, concentration, 2); } - + @Override public boolean func_82506_l() { @@ -255,7 +278,8 @@ public class BlockAir extends Block if (par1World.provider.dimensionId == WarpDrive.instance.spaceDimID || par1World.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) { par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World)); - } else + } + else { par1World.setBlockToAir(par2, par3, par4); } diff --git a/src/cr0s/WarpDrive/BlockAirGenerator.java b/src/cr0s/WarpDrive/BlockAirGenerator.java index 9de0d9cb..8a304d7b 100644 --- a/src/cr0s/WarpDrive/BlockAirGenerator.java +++ b/src/cr0s/WarpDrive/BlockAirGenerator.java @@ -14,12 +14,14 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Icon; import net.minecraft.world.World; -public class BlockAirGenerator extends BlockContainer { +public class BlockAirGenerator extends BlockContainer +{ private Icon[] iconBuffer; - - private final int ICON_INACTIVE_SIDE = 0, ICON_BOTTOM = 1, ICON_SIDE_ACTIVATED = 2; - public BlockAirGenerator(int id, int texture, Material material) { + private final int ICON_INACTIVE_SIDE = 0, ICON_BOTTOM = 1, ICON_SIDE_ACTIVATED = 2; + + public BlockAirGenerator(int id, int texture, Material material) + { super(id, material); } @@ -28,41 +30,48 @@ public class BlockAirGenerator extends BlockContainer { public void registerIcons(IconRegister par1IconRegister) { iconBuffer = new Icon[3]; - iconBuffer[ICON_INACTIVE_SIDE] = par1IconRegister.registerIcon("warpdrive:airgenSideInactive"); iconBuffer[ICON_BOTTOM] = par1IconRegister.registerIcon("warpdrive:contBottom"); iconBuffer[ICON_SIDE_ACTIVATED] = par1IconRegister.registerIcon("warpdrive:airgenSideActive"); } - + @Override public Icon getIcon(int side, int metadata) { - if (side == 0) { + if (side == 0) + { return iconBuffer[ICON_BOTTOM]; - } else - if (side == 1) { - if (metadata == 0) { + } + else if (side == 1) + { + if (metadata == 0) + { return iconBuffer[ICON_INACTIVE_SIDE]; - } else { + } + else + { return iconBuffer[ICON_SIDE_ACTIVATED]; } } - + if (metadata == 0) // Inactive state { return iconBuffer[ICON_INACTIVE_SIDE]; - } else if (metadata == 1) { + } + else if (metadata == 1) + { return iconBuffer[ICON_SIDE_ACTIVATED]; } - + return null; - } - + } + @Override - public TileEntity createNewTileEntity(World var1) { + public TileEntity createNewTileEntity(World var1) + { return new TileEntityAirGenerator(); } - + /** * Returns the quantity of items to drop on block destruction. */ @@ -79,33 +88,36 @@ public class BlockAirGenerator extends BlockContainer { public int idDropped(int par1, Random par2Random, int par3) { return this.blockID; - } - + } + @Override public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) { - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { return false; } - + TileEntityAirGenerator gen = (TileEntityAirGenerator)par1World.getBlockTileEntity(par2, par3, par4); - if (gen != null){ + if (gen != null) + { par5EntityPlayer.addChatMessage("[AirGen] Energy level: " + gen.getCurrentEnergyValue() + " Eu"); } return true; - } - + } + @Override public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) { TileEntity te = par1World.getBlockTileEntity(par2, par3, par4); - - if (te != null) { - te.invalidate(); + + if (te != null) + { + te.invalidate(); } - + super.breakBlock(par1World, par2, par3, par4, par5, par6); - } + } } diff --git a/src/cr0s/WarpDrive/BlockCamera.java b/src/cr0s/WarpDrive/BlockCamera.java index 4ee58dde..2576c2bc 100644 --- a/src/cr0s/WarpDrive/BlockCamera.java +++ b/src/cr0s/WarpDrive/BlockCamera.java @@ -12,36 +12,38 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Icon; import net.minecraft.world.World; -public class BlockCamera extends BlockContainer { +public class BlockCamera extends BlockContainer +{ private Icon[] iconBuffer; - + private final int ICON_SIDE = 0; - - public BlockCamera(int id, int texture, Material material) { + + public BlockCamera(int id, int texture, Material material) + { super(id, material); } - + @Override @SideOnly(Side.CLIENT) public void registerIcons(IconRegister par1IconRegister) { iconBuffer = new Icon[1]; - // Solid textures iconBuffer[ICON_SIDE] = par1IconRegister.registerIcon("warpdrive:cameraSide"); } - + @Override public Icon getIcon(int side, int metadata) { - return iconBuffer[ICON_SIDE]; + return iconBuffer[ICON_SIDE]; } - + @Override - public TileEntity createNewTileEntity(World var1) { + public TileEntity createNewTileEntity(World var1) + { return new TileEntityCamera(); } - + /** * Returns the quantity of items to drop on block destruction. */ @@ -58,5 +60,5 @@ public class BlockCamera extends BlockContainer { public int idDropped(int par1, Random par2Random, int par3) { return this.blockID; - } + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/BlockGas.java b/src/cr0s/WarpDrive/BlockGas.java index 5a552ebf..003fef0a 100644 --- a/src/cr0s/WarpDrive/BlockGas.java +++ b/src/cr0s/WarpDrive/BlockGas.java @@ -1,6 +1,5 @@ package cr0s.WarpDrive; -import cr0s.WarpDrive.WarpDrive; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.material.Material; @@ -11,9 +10,9 @@ import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; public class BlockGas extends Block -{ +{ private Icon[] gasIcons; - + public BlockGas(int par1) { super(par1, Material.air); @@ -65,27 +64,26 @@ public class BlockGas extends Block public void registerIcons(IconRegister par1IconRegister) { gasIcons = new Icon[12]; - gasIcons[0] = par1IconRegister.registerIcon("warpdrive:gasBlockBlue"); - gasIcons[1] = par1IconRegister.registerIcon("warpdrive:gasBlockRed"); + gasIcons[1] = par1IconRegister.registerIcon("warpdrive:gasBlockRed"); gasIcons[2] = par1IconRegister.registerIcon("warpdrive:gasBlockGreen"); - gasIcons[3] = par1IconRegister.registerIcon("warpdrive:gasBlockYellow"); - gasIcons[4] = par1IconRegister.registerIcon("warpdrive:gasBlockDark"); - gasIcons[5] = par1IconRegister.registerIcon("warpdrive:gasBlockDarkness"); - gasIcons[6] = par1IconRegister.registerIcon("warpdrive:gasBlockWhite"); - gasIcons[7] = par1IconRegister.registerIcon("warpdrive:gasBlockMilk"); - gasIcons[8] = par1IconRegister.registerIcon("warpdrive:gasBlockOrange"); - gasIcons[9] = par1IconRegister.registerIcon("warpdrive:gasBlockSyren"); - gasIcons[10] = par1IconRegister.registerIcon("warpdrive:gasBlockGray"); + gasIcons[3] = par1IconRegister.registerIcon("warpdrive:gasBlockYellow"); + gasIcons[4] = par1IconRegister.registerIcon("warpdrive:gasBlockDark"); + gasIcons[5] = par1IconRegister.registerIcon("warpdrive:gasBlockDarkness"); + gasIcons[6] = par1IconRegister.registerIcon("warpdrive:gasBlockWhite"); + gasIcons[7] = par1IconRegister.registerIcon("warpdrive:gasBlockMilk"); + gasIcons[8] = par1IconRegister.registerIcon("warpdrive:gasBlockOrange"); + gasIcons[9] = par1IconRegister.registerIcon("warpdrive:gasBlockSyren"); + gasIcons[10] = par1IconRegister.registerIcon("warpdrive:gasBlockGray"); gasIcons[11] = par1IconRegister.registerIcon("warpdrive:gasBlockViolet"); } - + @Override public Icon getIcon(int side, int metadata) { return gasIcons[metadata]; - } - + } + @Override public int getMobilityFlag() { @@ -98,7 +96,6 @@ public class BlockGas extends Block return -1; } - /** * Returns the quantity of items to drop on block destruction. */ @@ -156,8 +153,8 @@ public class BlockGas extends Block return false; } } - } - + } + @Override public boolean func_82506_l() { diff --git a/src/cr0s/WarpDrive/BlockIridium.java b/src/cr0s/WarpDrive/BlockIridium.java index 0b5155f2..c560457a 100644 --- a/src/cr0s/WarpDrive/BlockIridium.java +++ b/src/cr0s/WarpDrive/BlockIridium.java @@ -1,6 +1,5 @@ package cr0s.WarpDrive; -import cr0s.WarpDrive.WarpDrive; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.material.Material; @@ -10,7 +9,7 @@ import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; public class BlockIridium extends Block -{ +{ public BlockIridium(int par1) { super(par1, Material.rock); diff --git a/src/cr0s/WarpDrive/BlockLaser.java b/src/cr0s/WarpDrive/BlockLaser.java index 615fc66b..11e93fdf 100644 --- a/src/cr0s/WarpDrive/BlockLaser.java +++ b/src/cr0s/WarpDrive/BlockLaser.java @@ -12,36 +12,38 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Icon; import net.minecraft.world.World; -public class BlockLaser extends BlockContainer { +public class BlockLaser extends BlockContainer +{ private Icon[] iconBuffer; - + private final int ICON_SIDE = 0; - - public BlockLaser(int id, int texture, Material material) { + + public BlockLaser(int id, int texture, Material material) + { super(id, material); } - + @Override @SideOnly(Side.CLIENT) public void registerIcons(IconRegister par1IconRegister) { iconBuffer = new Icon[1]; - // Solid textures iconBuffer[ICON_SIDE] = par1IconRegister.registerIcon("warpdrive:laserSide"); } - + @Override public Icon getIcon(int side, int metadata) { - return iconBuffer[ICON_SIDE]; + return iconBuffer[ICON_SIDE]; } - + @Override - public TileEntity createNewTileEntity(World var1) { + public TileEntity createNewTileEntity(World var1) + { return new TileEntityLaser(); } - + /** * Returns the quantity of items to drop on block destruction. */ @@ -58,5 +60,5 @@ public class BlockLaser extends BlockContainer { public int idDropped(int par1, Random par2Random, int par3) { return this.blockID; - } + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/BlockLaserCam.java b/src/cr0s/WarpDrive/BlockLaserCam.java index 17941cfd..165f403f 100644 --- a/src/cr0s/WarpDrive/BlockLaserCam.java +++ b/src/cr0s/WarpDrive/BlockLaserCam.java @@ -12,36 +12,38 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Icon; import net.minecraft.world.World; -public class BlockLaserCam extends BlockContainer { +public class BlockLaserCam extends BlockContainer +{ private Icon[] iconBuffer; - + private final int ICON_SIDE = 0; - - public BlockLaserCam(int id, int texture, Material material) { + + public BlockLaserCam(int id, int texture, Material material) + { super(id, material); } - + @Override @SideOnly(Side.CLIENT) public void registerIcons(IconRegister par1IconRegister) { iconBuffer = new Icon[1]; - // Solid textures iconBuffer[ICON_SIDE] = par1IconRegister.registerIcon("warpdrive:laserSideCam"); } - + @Override public Icon getIcon(int side, int metadata) { - return iconBuffer[ICON_SIDE]; + return iconBuffer[ICON_SIDE]; } - + @Override - public TileEntity createNewTileEntity(World var1) { + public TileEntity createNewTileEntity(World var1) + { return new TileEntityLaser(); } - + /** * Returns the quantity of items to drop on block destruction. */ @@ -58,5 +60,5 @@ public class BlockLaserCam extends BlockContainer { public int idDropped(int par1, Random par2Random, int par3) { return this.blockID; - } + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/BlockLift.java b/src/cr0s/WarpDrive/BlockLift.java index a880bebc..dad3ac2b 100644 --- a/src/cr0s/WarpDrive/BlockLift.java +++ b/src/cr0s/WarpDrive/BlockLift.java @@ -1,10 +1,8 @@ package cr0s.WarpDrive; - import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.TileEntityProtocol; import java.util.Random; @@ -16,50 +14,56 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Icon; import net.minecraft.world.World; -public class BlockLift extends BlockContainer { +public class BlockLift extends BlockContainer +{ private Icon[] iconBuffer; - - public BlockLift(int id, int texture, Material material) { + + public BlockLift(int id, int texture, Material material) + { super(id, material); } - + @Override @SideOnly(Side.CLIENT) public void registerIcons(IconRegister par1IconRegister) { iconBuffer = new Icon[6]; - iconBuffer[0] = par1IconRegister.registerIcon("warpdrive:liftSideOffline"); - iconBuffer[1] = par1IconRegister.registerIcon("warpdrive:liftSideUp"); iconBuffer[2] = par1IconRegister.registerIcon("warpdrive:liftSideDown"); - iconBuffer[3] = par1IconRegister.registerIcon("warpdrive:liftUpInactive"); iconBuffer[4] = par1IconRegister.registerIcon("warpdrive:liftUpOut"); iconBuffer[5] = par1IconRegister.registerIcon("warpdrive:liftUpIn"); } - + @Override public Icon getIcon(int side, int metadata) { - if (side == 1) { - return iconBuffer[3 + metadata]; - } else - if (side == 0) { - if (metadata == 0) - return iconBuffer[3]; - else - return iconBuffer[6 - metadata]; + if (side == 1) + { + return iconBuffer[3 + metadata]; } - + else if (side == 0) + { + if (metadata == 0) + { + return iconBuffer[3]; + } + else + { + return iconBuffer[6 - metadata]; + } + } + return iconBuffer[metadata]; } - + @Override - public TileEntity createNewTileEntity(World var1) { + public TileEntity createNewTileEntity(World var1) + { return new TileEntityLift(); } - + /** * Returns the quantity of items to drop on block destruction. */ @@ -77,7 +81,7 @@ public class BlockLift extends BlockContainer { { return this.blockID; } - + /** * Called upon block activation (right click on the block.) */ @@ -85,22 +89,28 @@ public class BlockLift extends BlockContainer { public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) { if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { return false; + } + TileEntityLift booster = (TileEntityLift)par1World.getBlockTileEntity(par2, par3, par4); - if (booster != null){ + if (booster != null) + { par5EntityPlayer.addChatMessage("[Laser Lift] Energy level: " + booster.getCurrentEnergyValue()); } + return true; - } - + } + @Override public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) { TileEntity te = par1World.getBlockTileEntity(par2, par3, par4); - - if (te != null) { - te.invalidate(); + + if (te != null) + { + te.invalidate(); } - } + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/BlockMiningLaser.java b/src/cr0s/WarpDrive/BlockMiningLaser.java index 53cfd7f1..c90936f3 100644 --- a/src/cr0s/WarpDrive/BlockMiningLaser.java +++ b/src/cr0s/WarpDrive/BlockMiningLaser.java @@ -12,42 +12,44 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Icon; import net.minecraft.world.World; -public class BlockMiningLaser extends BlockContainer { +public class BlockMiningLaser extends BlockContainer +{ private Icon[] iconBuffer; - + private final int ICON_SIDE = 0; - - public BlockMiningLaser(int id, int texture, Material material) { + + public BlockMiningLaser(int id, int texture, Material material) + { super(id, material); } - + @Override @SideOnly(Side.CLIENT) public void registerIcons(IconRegister par1IconRegister) { iconBuffer = new Icon[2]; - // Solid textures iconBuffer[0] = par1IconRegister.registerIcon("warpdrive:particleBoosterTopBottom"); - iconBuffer[1] = par1IconRegister.registerIcon("warpdrive:miningLaserSide0"); } - + @Override public Icon getIcon(int side, int metadata) { - if (side == 0 || side == 1) { + if (side == 0 || side == 1) + { return iconBuffer[0]; } - + return iconBuffer[metadata + 1]; } - + @Override - public TileEntity createNewTileEntity(World var1) { + public TileEntity createNewTileEntity(World var1) + { return new TileEntityMiningLaser(); } - + /** * Returns the quantity of items to drop on block destruction. */ @@ -64,5 +66,5 @@ public class BlockMiningLaser extends BlockContainer { public int idDropped(int par1, Random par2Random, int par3) { return this.blockID; - } + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/BlockMonitor.java b/src/cr0s/WarpDrive/BlockMonitor.java index 1014d31c..7f931d37 100644 --- a/src/cr0s/WarpDrive/BlockMonitor.java +++ b/src/cr0s/WarpDrive/BlockMonitor.java @@ -19,15 +19,12 @@ import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.Icon; import net.minecraft.world.ChunkPosition; import net.minecraft.world.World; -import shipmod.ShipMod; -import shipmod.chunk.ChunkBuilder; -import shipmod.entity.EntityShip; public class BlockMonitor extends BlockContainer { private Icon frontIcon; - private Icon blockIcon; - + private Icon blockIcon; + public BlockMonitor(int id) { super(id, Material.iron); @@ -53,7 +50,7 @@ public class BlockMonitor extends BlockContainer this.frontIcon = reg.registerIcon("warpdrive:monitorFront"); this.blockIcon = reg.registerIcon("warpdrive:monitorSide"); } - + /** * Called when the block is placed in the world. */ @@ -72,42 +69,44 @@ public class BlockMonitor extends BlockContainer { return true; } - + // Get camera frequency TileEntity te = world.getBlockTileEntity(x, y, z); - - if (te != null && te instanceof TileEntityMonitor) { - int freq = ((TileEntityMonitor)te).getFrequency(); - - WarpDrive.instance.cams.removeDeadCams(); - CamRegistryItem cam = WarpDrive.instance.cams.getCamByFreq(freq, world); - - if (cam == null || cam.worldObj == null || cam.worldObj != world || !WarpDrive.instance.cams.isCamAlive(cam)) { - entityplayer.addChatMessage("[Monitor: " + freq + "] Invalid frequency or camera is too far!"); - return false; - } else { - // Spawn camera entity - EntityCamera e = new EntityCamera(world, cam.camPos, entityplayer); - world.spawnEntityInWorld(e); - e.setPositionAndUpdate(cam.camPos.x, cam.camPos.y, cam.camPos.z); - //e.setPositionAndRotation(camPos.x, camPos.y, camPos.z, entityplayer.rotationYaw, entityplayer.rotationPitch); - - ClientCameraUtils.playerData = entityplayer; - WarpDrive.instance.overlayType = cam.type; - ClientCameraUtils.setupViewpoint(e); - } + + if (te != null && te instanceof TileEntityMonitor) + { + int freq = ((TileEntityMonitor)te).getFrequency(); + WarpDrive.instance.cams.removeDeadCams(); + CamRegistryItem cam = WarpDrive.instance.cams.getCamByFreq(freq, world); + + if (cam == null || cam.worldObj == null || cam.worldObj != world || !WarpDrive.instance.cams.isCamAlive(cam)) + { + entityplayer.addChatMessage("[Monitor: " + freq + "] Invalid frequency or camera is too far!"); + return false; + } + else + { + // Spawn camera entity + EntityCamera e = new EntityCamera(world, cam.camPos, entityplayer); + world.spawnEntityInWorld(e); + e.setPositionAndUpdate(cam.camPos.x, cam.camPos.y, cam.camPos.z); + //e.setPositionAndRotation(camPos.x, camPos.y, camPos.z, entityplayer.rotationYaw, entityplayer.rotationPitch); + ClientCameraUtils.playerData = entityplayer; + WarpDrive.instance.overlayType = cam.type; + ClientCameraUtils.setupViewpoint(e); + } } - + return false; } - + public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) { - - } + } - @Override - public TileEntity createNewTileEntity(World world) { - return new TileEntityMonitor(); - } + @Override + public TileEntity createNewTileEntity(World world) + { + return new TileEntityMonitor(); + } } diff --git a/src/cr0s/WarpDrive/BlockParticleBooster.java b/src/cr0s/WarpDrive/BlockParticleBooster.java index 7c250c09..8fc3e121 100644 --- a/src/cr0s/WarpDrive/BlockParticleBooster.java +++ b/src/cr0s/WarpDrive/BlockParticleBooster.java @@ -1,10 +1,8 @@ package cr0s.WarpDrive; - import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.TileEntityProtocol; import java.util.Random; @@ -16,19 +14,20 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Icon; import net.minecraft.world.World; -public class BlockParticleBooster extends BlockContainer { +public class BlockParticleBooster extends BlockContainer +{ private Icon[] iconBuffer; - - public BlockParticleBooster(int id, int texture, Material material) { + + public BlockParticleBooster(int id, int texture, Material material) + { super(id, material); } - + @Override @SideOnly(Side.CLIENT) public void registerIcons(IconRegister par1IconRegister) { iconBuffer = new Icon[12]; - iconBuffer[0] = par1IconRegister.registerIcon("warpdrive:particleBoosterSide0"); iconBuffer[1] = par1IconRegister.registerIcon("warpdrive:particleBoosterSide1"); iconBuffer[2] = par1IconRegister.registerIcon("warpdrive:particleBoosterSide2"); @@ -40,26 +39,31 @@ public class BlockParticleBooster extends BlockContainer { iconBuffer[8] = par1IconRegister.registerIcon("warpdrive:particleBoosterSide8"); iconBuffer[9] = par1IconRegister.registerIcon("warpdrive:particleBoosterSide9"); iconBuffer[10] = par1IconRegister.registerIcon("warpdrive:particleBoosterSide10"); - iconBuffer[11] = par1IconRegister.registerIcon("warpdrive:particleBoosterTopBottom"); } - + @Override public Icon getIcon(int side, int metadata) { - if (side == 0 || side == 1) { + if (side == 0 || side == 1) + { return iconBuffer[11]; } - - if (metadata > 10) { metadata = 10; } + + if (metadata > 10) + { + metadata = 10; + } + return iconBuffer[metadata]; } - + @Override - public TileEntity createNewTileEntity(World var1) { + public TileEntity createNewTileEntity(World var1) + { return new TileEntityParticleBooster(); } - + /** * Returns the quantity of items to drop on block destruction. */ @@ -77,7 +81,7 @@ public class BlockParticleBooster extends BlockContainer { { return this.blockID; } - + /** * Called upon block activation (right click on the block.) */ @@ -85,24 +89,30 @@ public class BlockParticleBooster extends BlockContainer { public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) { if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { return false; + } + TileEntityParticleBooster booster = (TileEntityParticleBooster)par1World.getBlockTileEntity(par2, par3, par4); - if (booster != null){ + if (booster != null) + { par5EntityPlayer.addChatMessage("[Particle Booster] Energy level: " + booster.getCurrentEnergyValue()); } + return true; - } - + } + @Override public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) { TileEntity te = par1World.getBlockTileEntity(par2, par3, par4); - - if (te != null) { - te.invalidate(); + + if (te != null) + { + te.invalidate(); } - - super.breakBlock(par1World, par2, par3, par4, par5, par6); - } + + super.breakBlock(par1World, par2, par3, par4, par5, par6); + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/BlockProtocol.java b/src/cr0s/WarpDrive/BlockProtocol.java index a5a756c9..84cda5d7 100644 --- a/src/cr0s/WarpDrive/BlockProtocol.java +++ b/src/cr0s/WarpDrive/BlockProtocol.java @@ -12,29 +12,28 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Icon; import net.minecraft.world.World; -public class BlockProtocol extends BlockContainer { +public class BlockProtocol extends BlockContainer +{ private Icon[] iconBuffer; - + private final int ICON_INACTIVE_SIDE = 0, ICON_BOTTOM = 1, ICON_TOP = 2, ICON_SIDE_ACTIVATED = 3; //private final int ANIMATION_ //private int currentTexture; - - public BlockProtocol(int id, int texture, Material material) { + public BlockProtocol(int id, int texture, Material material) + { super(id, material); } - + @Override @SideOnly(Side.CLIENT) public void registerIcons(IconRegister par1IconRegister) { iconBuffer = new Icon[9]; - // Solid textures iconBuffer[ICON_INACTIVE_SIDE] = par1IconRegister.registerIcon("warpdrive:contSideInactive"); iconBuffer[ICON_BOTTOM] = par1IconRegister.registerIcon("warpdrive:contBottom"); iconBuffer[ICON_TOP] = par1IconRegister.registerIcon("warpdrive:contTop"); - // Animated textures iconBuffer[ICON_SIDE_ACTIVATED] = par1IconRegister.registerIcon("warpdrive:contSideActive1"); iconBuffer[ICON_SIDE_ACTIVATED + 1] = par1IconRegister.registerIcon("warpdrive:contSideActive2"); @@ -43,33 +42,37 @@ public class BlockProtocol extends BlockContainer { iconBuffer[ICON_SIDE_ACTIVATED + 4] = par1IconRegister.registerIcon("warpdrive:contSideActive5"); iconBuffer[ICON_SIDE_ACTIVATED + 5] = par1IconRegister.registerIcon("warpdrive:contSideActive6"); } - + @Override public Icon getIcon(int side, int metadata) { - if (side == 0) { + if (side == 0) + { return iconBuffer[ICON_BOTTOM]; - } else - if (side == 1) { + } + else if (side == 1) + { return iconBuffer[ICON_TOP]; } - + if (metadata == 0) // Inactive state { return iconBuffer[ICON_INACTIVE_SIDE]; - } else - if (metadata > 0) { // Activated, in metadata stored mode number + } + else if (metadata > 0) // Activated, in metadata stored mode number + { return iconBuffer[ICON_SIDE_ACTIVATED + metadata - 1]; } - + return null; } - + @Override - public TileEntity createNewTileEntity(World var1) { + public TileEntity createNewTileEntity(World var1) + { return new TileEntityProtocol(); } - + /** * Returns the quantity of items to drop on block destruction. */ @@ -86,7 +89,7 @@ public class BlockProtocol extends BlockContainer { public int idDropped(int par1, Random par2Random, int par3) { return this.blockID; - } + } /** * Called upon block activation (right click on the block.) */ @@ -94,13 +97,18 @@ public class BlockProtocol extends BlockContainer { public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) { if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { return false; + } + TileEntityProtocol controller = (TileEntityProtocol)par1World.getBlockTileEntity(par2, par3, par4); - if (controller != null){ + if (controller != null) + { controller.attachPlayer(par5EntityPlayer); par5EntityPlayer.addChatMessage("[WarpCtrlr] Attached players: " + controller.getAttachedPlayersList()); } + return true; } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/BlockRadar.java b/src/cr0s/WarpDrive/BlockRadar.java index f76858f1..7aabc33e 100644 --- a/src/cr0s/WarpDrive/BlockRadar.java +++ b/src/cr0s/WarpDrive/BlockRadar.java @@ -3,7 +3,6 @@ package cr0s.WarpDrive; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.WarpDrive; import java.util.ArrayList; import java.util.Random; @@ -16,12 +15,14 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Icon; import net.minecraft.world.World; -public class BlockRadar extends BlockContainer { +public class BlockRadar extends BlockContainer +{ private Icon[] iconBuffer; - - private final int ICON_INACTIVE_SIDE = 0, ICON_BOTTOM = 1, ICON_TOP = 2, ICON_SIDE_ACTIVATED = 3, ICON_SIDE_ACTIVATED_SCAN = 4; - - public BlockRadar(int id, int texture, Material material) { + + private final int ICON_INACTIVE_SIDE = 0, ICON_BOTTOM = 1, ICON_TOP = 2, ICON_SIDE_ACTIVATED = 3, ICON_SIDE_ACTIVATED_SCAN = 4; + + public BlockRadar(int id, int texture, Material material) + { super(id, material); } @@ -30,42 +31,47 @@ public class BlockRadar extends BlockContainer { public void registerIcons(IconRegister par1IconRegister) { iconBuffer = new Icon[5]; - iconBuffer[ICON_INACTIVE_SIDE] = par1IconRegister.registerIcon("warpdrive:radarSideInactive"); iconBuffer[ICON_BOTTOM] = par1IconRegister.registerIcon("warpdrive:contBottom"); iconBuffer[ICON_TOP] = par1IconRegister.registerIcon("warpdrive:contTop"); - iconBuffer[ICON_SIDE_ACTIVATED] = par1IconRegister.registerIcon("warpdrive:radarSideActive"); iconBuffer[ICON_SIDE_ACTIVATED_SCAN] = par1IconRegister.registerIcon("warpdrive:radarSideActiveScan"); } - + @Override public Icon getIcon(int side, int metadata) { - if (side == 0) { + if (side == 0) + { return iconBuffer[ICON_BOTTOM]; - } else - if (side == 1) { + } + else if (side == 1) + { return iconBuffer[ICON_TOP]; } - + if (metadata == 0) // Inactive state { return iconBuffer[ICON_INACTIVE_SIDE]; - } else if (metadata == 1) { // Attached state + } + else if (metadata == 1) // Attached state + { return iconBuffer[ICON_SIDE_ACTIVATED]; - } else if (metadata == 2) { // Scanning state + } + else if (metadata == 2) // Scanning state + { return iconBuffer[ICON_SIDE_ACTIVATED_SCAN]; } - + return null; - } - + } + @Override - public TileEntity createNewTileEntity(World var1) { + public TileEntity createNewTileEntity(World var1) + { return new TileEntityRadar(); } - + /** * Returns the quantity of items to drop on block destruction. */ @@ -82,33 +88,36 @@ public class BlockRadar extends BlockContainer { public int idDropped(int par1, Random par2Random, int par3) { return this.blockID; - } - + } + @Override public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) { - - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { return false; + } + TileEntityRadar radar = (TileEntityRadar)par1World.getBlockTileEntity(par2, par3, par4); - if (radar != null){ + if (radar != null) + { par5EntityPlayer.addChatMessage("[Radar] Energy level: " + radar.getCurrentEnergyValue() + " Eu"); } return true; } - + @Override public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) { TileEntity te = par1World.getBlockTileEntity(par2, par3, par4); - - if (te != null) { - te.invalidate(); + + if (te != null) + { + te.invalidate(); } - - super.breakBlock(par1World, par2, par3, par4, par5, par6); - } + + super.breakBlock(par1World, par2, par3, par4, par5, par6); + } } diff --git a/src/cr0s/WarpDrive/BlockReactor.java b/src/cr0s/WarpDrive/BlockReactor.java index bae798c7..1bad6490 100644 --- a/src/cr0s/WarpDrive/BlockReactor.java +++ b/src/cr0s/WarpDrive/BlockReactor.java @@ -3,7 +3,6 @@ package cr0s.WarpDrive; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.WarpDrive; import java.util.Random; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; @@ -13,12 +12,14 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Icon; import net.minecraft.world.World; -public class BlockReactor extends BlockContainer { +public class BlockReactor extends BlockContainer +{ private Icon[] iconBuffer; - - private final int ICON_INACTIVE_SIDE = 0, ICON_BOTTOM = 1, ICON_TOP = 2, ICON_SIDE_ACTIVATED= 3; - - public BlockReactor(int id, int texture, Material material) { + + private final int ICON_INACTIVE_SIDE = 0, ICON_BOTTOM = 1, ICON_TOP = 2, ICON_SIDE_ACTIVATED = 3; + + public BlockReactor(int id, int texture, Material material) + { super(id, material); } @@ -27,39 +28,42 @@ public class BlockReactor extends BlockContainer { public void registerIcons(IconRegister par1IconRegister) { iconBuffer = new Icon[4]; - iconBuffer[ICON_INACTIVE_SIDE] = par1IconRegister.registerIcon("warpdrive:coreSideInactive"); iconBuffer[ICON_BOTTOM] = par1IconRegister.registerIcon("warpdrive:coreBottom"); iconBuffer[ICON_TOP] = par1IconRegister.registerIcon("warpdrive:coreTop"); - iconBuffer[ICON_SIDE_ACTIVATED] = par1IconRegister.registerIcon("warpdrive:coreSideActive"); } - + @Override public Icon getIcon(int side, int metadata) { - if (side == 0) { + if (side == 0) + { return iconBuffer[ICON_BOTTOM]; - } else - if (side == 1) { + } + else if (side == 1) + { return iconBuffer[ICON_TOP]; } - + if (metadata == 0) // Inactive state { return iconBuffer[ICON_INACTIVE_SIDE]; - } else if (metadata == 1) { // Activated state + } + else if (metadata == 1) // Activated state + { return iconBuffer[ICON_SIDE_ACTIVATED]; } - + return null; - } - + } + @Override - public TileEntity createNewTileEntity(World var1) { + public TileEntity createNewTileEntity(World var1) + { return new TileEntityReactor(); } - + /** * Returns the quantity of items to drop on block destruction. */ @@ -76,8 +80,8 @@ public class BlockReactor extends BlockContainer { public int idDropped(int par1, Random par2Random, int par3) { return this.blockID; - } - + } + /** * Called upon block activation (right click on the block.) */ @@ -85,26 +89,32 @@ public class BlockReactor extends BlockContainer { public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) { if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { return false; + } + TileEntityReactor reactor = (TileEntityReactor)par1World.getBlockTileEntity(par2, par3, par4); - - if (reactor != null){ + + if (reactor != null) + { par5EntityPlayer.addChatMessage(reactor.getCoreState()); } + return true; - } - + } + @Override public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) { TileEntity te = par1World.getBlockTileEntity(par2, par3, par4); - - if (te != null && te instanceof TileEntityReactor) { + + if (te != null && te instanceof TileEntityReactor) + { WarpDrive.instance.registry.removeFromRegistry((TileEntityReactor)te); te.invalidate(); } - + WarpDrive.instance.registry.removeDeadCores(); - super.breakBlock(par1World, par2, par3, par4, par5, par6); + super.breakBlock(par1World, par2, par3, par4, par5, par6); } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/BlockWarpIsolation.java b/src/cr0s/WarpDrive/BlockWarpIsolation.java index 33537393..efeb31ac 100644 --- a/src/cr0s/WarpDrive/BlockWarpIsolation.java +++ b/src/cr0s/WarpDrive/BlockWarpIsolation.java @@ -2,7 +2,6 @@ package cr0s.WarpDrive; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.TileEntityProtocol; import java.util.Random; @@ -14,28 +13,29 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Icon; import net.minecraft.world.World; -public class BlockWarpIsolation extends Block { +public class BlockWarpIsolation extends Block +{ private Icon[] iconBuffer; - - public BlockWarpIsolation(int id, int texture, Material material) { + + public BlockWarpIsolation(int id, int texture, Material material) + { super(id, material); } - + @Override @SideOnly(Side.CLIENT) public void registerIcons(IconRegister par1IconRegister) { iconBuffer = new Icon[1]; - iconBuffer[0] = par1IconRegister.registerIcon("warpdrive:warpIsolation"); } - + @Override public Icon getIcon(int side, int metadata) { return iconBuffer[0]; } - + /** * Returns the quantity of items to drop on block destruction. */ diff --git a/src/cr0s/WarpDrive/CamRegistry.java b/src/cr0s/WarpDrive/CamRegistry.java index 708d43e3..13eb09f4 100644 --- a/src/cr0s/WarpDrive/CamRegistry.java +++ b/src/cr0s/WarpDrive/CamRegistry.java @@ -6,53 +6,67 @@ import java.util.HashMap; import net.minecraft.world.ChunkPosition; import net.minecraft.world.World; -public class CamRegistry { - private ArrayList<CamRegistryItem> registry; - - public CamRegistry() { - registry = new ArrayList<CamRegistryItem>(); - } +public class CamRegistry +{ + private ArrayList<CamRegistryItem> registry; - public CamRegistryItem getCamByFreq(int frequency, World worldObj) { - for (CamRegistryItem i : registry) { - if (i.freq == frequency && i.worldObj == worldObj) { - return i; - } - } - - return null; - } - - public boolean isCamAlive(CamRegistryItem i) { - if (i.worldObj != null) { - if (i.worldObj.getBlockId(i.camPos.x, i.camPos.y, i.camPos.z) != WarpDrive.instance.config.camID && i.worldObj.getBlockId(i.camPos.x, i.camPos.y, i.camPos.z) != WarpDrive.instance.config.laserCamID) { - return false; - } - - return true; - } - - return false; - } - - public void removeDeadCams() { - for (CamRegistryItem i : registry) { - if (!isCamAlive(i)) { - registry.remove(i); - return; - } - } - } - - public void updateInRegistry(CamRegistryItem i) { - removeDeadCams(); - - if (isCamAlive(i)) { - CamRegistryItem existingCam = this.getCamByFreq(i.freq, i.worldObj); - - if (existingCam == null) { - registry.add(i); - } - } - } + public CamRegistry() + { + registry = new ArrayList<CamRegistryItem>(); + } + + public CamRegistryItem getCamByFreq(int frequency, World worldObj) + { + for (CamRegistryItem i : registry) + { + if (i.freq == frequency && i.worldObj == worldObj) + { + return i; + } + } + + return null; + } + + public boolean isCamAlive(CamRegistryItem i) + { + if (i.worldObj != null) + { + if (i.worldObj.getBlockId(i.camPos.x, i.camPos.y, i.camPos.z) != WarpDrive.instance.config.camID && i.worldObj.getBlockId(i.camPos.x, i.camPos.y, i.camPos.z) != WarpDrive.instance.config.laserCamID) + { + return false; + } + + return true; + } + + return false; + } + + public void removeDeadCams() + { + for (CamRegistryItem i : registry) + { + if (!isCamAlive(i)) + { + registry.remove(i); + return; + } + } + } + + public void updateInRegistry(CamRegistryItem i) + { + removeDeadCams(); + + if (isCamAlive(i)) + { + CamRegistryItem existingCam = this.getCamByFreq(i.freq, i.worldObj); + + if (existingCam == null) + { + registry.add(i); + } + } + } } diff --git a/src/cr0s/WarpDrive/CamRegistryItem.java b/src/cr0s/WarpDrive/CamRegistryItem.java index 69e95d9b..b841a970 100644 --- a/src/cr0s/WarpDrive/CamRegistryItem.java +++ b/src/cr0s/WarpDrive/CamRegistryItem.java @@ -3,20 +3,23 @@ package cr0s.WarpDrive; import net.minecraft.world.ChunkPosition; import net.minecraft.world.World; -public class CamRegistryItem { - public int freq; - public ChunkPosition camPos; - public World worldObj; - - public int type = 0; // 0 - basic cam, 1 - laser cam - public CamRegistryItem(int freq, ChunkPosition pos, World worldObj) { - this.freq = freq; - this.camPos = pos; - this.worldObj = worldObj; - } - - public CamRegistryItem setType(int type) { - this.type = type; - return this; - } +public class CamRegistryItem +{ + public int freq; + public ChunkPosition camPos; + public World worldObj; + + public int type = 0; // 0 - basic cam, 1 - laser cam + public CamRegistryItem(int freq, ChunkPosition pos, World worldObj) + { + this.freq = freq; + this.camPos = pos; + this.worldObj = worldObj; + } + + public CamRegistryItem setType(int type) + { + this.type = type; + return this; + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/CameraOverlay.java b/src/cr0s/WarpDrive/CameraOverlay.java index 06efaed9..eeab8ab1 100644 --- a/src/cr0s/WarpDrive/CameraOverlay.java +++ b/src/cr0s/WarpDrive/CameraOverlay.java @@ -9,13 +9,15 @@ import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType; import net.minecraftforge.event.ForgeSubscribe; -public class CameraOverlay { - private Minecraft mc; - - public CameraOverlay(Minecraft mc) { - this.mc = mc; - } - +public class CameraOverlay +{ + private Minecraft mc; + + public CameraOverlay(Minecraft mc) + { + this.mc = mc; + } + protected void renderOverlay(int par1, int par2) { GL11.glDisable(GL11.GL_DEPTH_TEST); @@ -23,11 +25,16 @@ public class CameraOverlay { GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); GL11.glDisable(GL11.GL_ALPHA_TEST); - if (WarpDrive.instance.overlayType == 0) { - this.mc.func_110434_K().func_110577_a(new ResourceLocation("warpdrive", "textures/blocks/camOverlay.png")); - } else { - this.mc.func_110434_K().func_110577_a(new ResourceLocation("warpdrive", "textures/blocks/lasercamOverlay.png")); + + if (WarpDrive.instance.overlayType == 0) + { + this.mc.getTextureManager().bindTexture(new ResourceLocation("warpdrive", "textures/blocks/camOverlay.png")); } + else + { + this.mc.getTextureManager().bindTexture(new ResourceLocation("warpdrive", "textures/blocks/lasercamOverlay.png")); + } + Tessellator tessellator = Tessellator.instance; tessellator.startDrawingQuads(); tessellator.addVertexWithUV(0.0D, (double)par2, -90.0D, 0.0D, 1.0D); @@ -40,16 +47,21 @@ public class CameraOverlay { GL11.glEnable(GL11.GL_ALPHA_TEST); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); } - - @ForgeSubscribe - public void onRender(RenderGameOverlayEvent.Pre event) { - if (WarpDrive.instance.isOverlayEnabled) { - if (event.type == ElementType.HELMET) { - renderOverlay(event.resolution.getScaledWidth(), event.resolution.getScaledHeight()); - } else if (event.type == ElementType.EXPERIENCE || event.type == ElementType.HOTBAR || event.type == ElementType.ARMOR || event.type == ElementType.HEALTH || event.type == ElementType.HEALTHMOUNT || event.type == ElementType.FOOD || event.type == ElementType.BOSSHEALTH || event.type == ElementType.TEXT) { - // Don't render other GUI parts - event.setCanceled(true); - } - } - } + + @ForgeSubscribe + public void onRender(RenderGameOverlayEvent.Pre event) + { + if (WarpDrive.instance.isOverlayEnabled) + { + if (event.type == ElementType.HELMET) + { + renderOverlay(event.resolution.getScaledWidth(), event.resolution.getScaledHeight()); + } + else if (event.type == ElementType.EXPERIENCE || event.type == ElementType.HOTBAR || event.type == ElementType.ARMOR || event.type == ElementType.HEALTH || event.type == ElementType.HEALTHMOUNT || event.type == ElementType.FOOD || event.type == ElementType.BOSSHEALTH || event.type == ElementType.TEXT) + { + // Don't render other GUI parts + event.setCanceled(true); + } + } + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/ClientCameraUtils.java b/src/cr0s/WarpDrive/ClientCameraUtils.java index 02e653b1..9fe0bf66 100644 --- a/src/cr0s/WarpDrive/ClientCameraUtils.java +++ b/src/cr0s/WarpDrive/ClientCameraUtils.java @@ -6,33 +6,37 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -public class ClientCameraUtils { - public static EntityPlayer playerData; - public static float oldFOV; - public static float oldSens; - - public static void setupViewpoint(Entity entity) { - Minecraft mc = Minecraft.getMinecraft(); - if(entity == null) { - System.out.println("Null"); - } +public class ClientCameraUtils +{ + public static EntityPlayer playerData; + public static float oldFOV; + public static float oldSens; - System.out.println("Setting viewpoint: " + entity.toString()); - mc.renderViewEntity = (EntityLivingBase)entity; - mc.gameSettings.thirdPersonView = 0; - oldFOV = mc.gameSettings.fovSetting; - oldSens = mc.gameSettings.mouseSensitivity; - WarpDrive.instance.isOverlayEnabled = true; - } - - public static void resetCam() { - Minecraft mc = Minecraft.getMinecraft(); - mc.renderViewEntity = playerData; - playerData = null; - mc.gameSettings.thirdPersonView = 0; - mc.gameSettings.setOptionFloatValue(EnumOptions.FOV, oldFOV); - mc.gameSettings.setOptionFloatValue(EnumOptions.SENSITIVITY, oldSens); - - WarpDrive.instance.isOverlayEnabled = false; - } + public static void setupViewpoint(Entity entity) + { + Minecraft mc = Minecraft.getMinecraft(); + + if (entity == null) + { + System.out.println("Null"); + } + + System.out.println("Setting viewpoint: " + entity.toString()); + mc.renderViewEntity = (EntityLivingBase)entity; + mc.gameSettings.thirdPersonView = 0; + oldFOV = mc.gameSettings.fovSetting; + oldSens = mc.gameSettings.mouseSensitivity; + WarpDrive.instance.isOverlayEnabled = true; + } + + public static void resetCam() + { + Minecraft mc = Minecraft.getMinecraft(); + mc.renderViewEntity = playerData; + playerData = null; + mc.gameSettings.thirdPersonView = 0; + mc.gameSettings.setOptionFloatValue(EnumOptions.FOV, oldFOV); + mc.gameSettings.setOptionFloatValue(EnumOptions.SENSITIVITY, oldSens); + WarpDrive.instance.isOverlayEnabled = false; + } } diff --git a/src/cr0s/WarpDrive/ClientProxy.java b/src/cr0s/WarpDrive/ClientProxy.java index 1b9136c6..92d94cb8 100644 --- a/src/cr0s/WarpDrive/ClientProxy.java +++ b/src/cr0s/WarpDrive/ClientProxy.java @@ -4,16 +4,17 @@ import cpw.mods.fml.client.FMLClientHandler; import net.minecraft.world.World; import net.minecraftforge.client.MinecraftForgeClient; -public class ClientProxy extends CommonProxy { +public class ClientProxy extends CommonProxy +{ + @Override + public void registerRenderers() + { + } @Override - public void registerRenderers() { + public void renderBeam(World world, Vector3 position, Vector3 target, float red, float green, float blue, int age, int energy) + { + //System.out.println("Rendering beam..."); + FMLClientHandler.instance().getClient().effectRenderer.addEffect(new FXBeam(world, position, target, red, green, blue, age, energy)); } - - @Override - public void renderBeam(World world, Vector3 position, Vector3 target, float red, float green, float blue, int age, int energy) - { - //System.out.println("Rendering beam..."); - FMLClientHandler.instance().getClient().effectRenderer.addEffect(new FXBeam(world, position, target, red, green, blue, age, energy)); - } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/CloudRenderBlank.java b/src/cr0s/WarpDrive/CloudRenderBlank.java index 7f7690c8..43d5d3bf 100644 --- a/src/cr0s/WarpDrive/CloudRenderBlank.java +++ b/src/cr0s/WarpDrive/CloudRenderBlank.java @@ -12,6 +12,5 @@ public class CloudRenderBlank extends IRenderHandler @Override public void render(float partialTicks, WorldClient world, Minecraft mc) { - } } diff --git a/src/cr0s/WarpDrive/CommonProxy.java b/src/cr0s/WarpDrive/CommonProxy.java index bdb9f141..272c2ca2 100644 --- a/src/cr0s/WarpDrive/CommonProxy.java +++ b/src/cr0s/WarpDrive/CommonProxy.java @@ -6,21 +6,21 @@ import java.io.DataOutputStream; import net.minecraft.world.World; import cpw.mods.fml.common.registry.EntityRegistry; -public class CommonProxy { - public void registerEntities() { +public class CommonProxy +{ + public void registerEntities() + { EntityRegistry.registerModEntity(EntityJump.class, "EntityJump", 1, WarpDrive.instance, 80, 1, false); EntityRegistry.registerModEntity(EntitySphereGen.class, "EntitySphereGenerator", 1, WarpDrive.instance, 200, 1, false); EntityRegistry.registerModEntity(EntityStarCore.class, "EntityStarCore", 1, WarpDrive.instance, 300, 1, false); EntityRegistry.registerModEntity(EntityCamera.class, "EntityCamera", 1, WarpDrive.instance, 300, 1, false); } - public void registerRenderers() { - + public void registerRenderers() + { + } + + public void renderBeam(World world, Vector3 position, Vector3 target, float red, float green, float blue, int age, int energy) + { } - - - public void renderBeam(World world, Vector3 position, Vector3 target, float red, float green, float blue, int age, int energy) - { - - } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/EntityCamera.java b/src/cr0s/WarpDrive/EntityCamera.java index 8a09a539..c954fc33 100644 --- a/src/cr0s/WarpDrive/EntityCamera.java +++ b/src/cr0s/WarpDrive/EntityCamera.java @@ -32,125 +32,151 @@ import net.minecraft.world.ChunkPosition; import net.minecraft.world.World; import net.minecraft.entity.player.EntityPlayer; -public final class EntityCamera extends EntityLivingBase { +public final class EntityCamera extends EntityLivingBase +{ public int xCoord; public int yCoord; public int zCoord; - + private int ticks = 0; private EntityPlayer player; private Minecraft mc = Minecraft.getMinecraft(); private int dx, dy, dz; - + private int zoomNumber = 0; - + private int waitTicks = 2; private int fireWaitTicks = 2; - + private float oldFOV; private float oldSens; - - public EntityCamera(World world, ChunkPosition pos, EntityPlayer player) { - super(world); - this.setInvisible(true); + + public EntityCamera(World world, ChunkPosition pos, EntityPlayer player) + { + super(world); + this.setInvisible(true); int x = pos.x; int y = pos.y; int z = pos.z; - this.xCoord = x; this.posX = (double) x; - this.yCoord = y; this.posY = (double) y; - this.zCoord = z; this.posZ = (double) z; - this.player = player; - } - + @Override - public void onEntityUpdate() { - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { - mc.renderViewEntity.rotationYaw = player.rotationYaw; - //mc.renderViewEntity.rotationYawHead = player.rotationYawHead; - mc.renderViewEntity.rotationPitch = player.rotationPitch; - - // Perform zoom - if (Mouse.isButtonDown(1) && waitTicks-- == 2) { - waitTicks = 2; - zoom(); - } - - if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) { - ClientCameraUtils.resetCam(); - this.setDead(); - } else if (Keyboard.isKeyDown(Keyboard.KEY_SPACE) && fireWaitTicks-- == 0) { - fireWaitTicks = 2; - // Make a shoot with camera-laser - if (worldObj.getBlockId(xCoord, yCoord, zCoord) == WarpDrive.instance.config.laserCamID) { - sendTargetPacket(); - } - } else { - if (Keyboard.isKeyDown(Keyboard.KEY_DOWN) && (dy != -2)) { - dy = -1; - } else if (Keyboard.isKeyDown(Keyboard.KEY_UP) && (dy != 2)) { - dy = 2; - } else if (Keyboard.isKeyDown(Keyboard.KEY_A) && (dz != -1)) { - dz = -1; - } else if (Keyboard.isKeyDown(Keyboard.KEY_D) && (dz != 1)) { - dz = 1; - } else if (Keyboard.isKeyDown(Keyboard.KEY_W) && (dx != 1)) { - dx = 1; - } else if (Keyboard.isKeyDown(Keyboard.KEY_S) && (dx != -1)) { - dx = -1; - } - } - - this.setPosition(xCoord + dx, yCoord + dy, zCoord + dz); + public void onEntityUpdate() + { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + mc.renderViewEntity.rotationYaw = player.rotationYaw; + //mc.renderViewEntity.rotationYawHead = player.rotationYawHead; + mc.renderViewEntity.rotationPitch = player.rotationPitch; + + // Perform zoom + if (Mouse.isButtonDown(1) && waitTicks-- == 2) + { + waitTicks = 2; + zoom(); + } + + if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) + { + ClientCameraUtils.resetCam(); + this.setDead(); + } + else if (Keyboard.isKeyDown(Keyboard.KEY_SPACE) && fireWaitTicks-- == 0) + { + fireWaitTicks = 2; + + // Make a shoot with camera-laser + if (worldObj.getBlockId(xCoord, yCoord, zCoord) == WarpDrive.instance.config.laserCamID) + { + sendTargetPacket(); + } + } + else + { + if (Keyboard.isKeyDown(Keyboard.KEY_DOWN) && (dy != -2)) + { + dy = -1; + } + else if (Keyboard.isKeyDown(Keyboard.KEY_UP) && (dy != 2)) + { + dy = 2; + } + else if (Keyboard.isKeyDown(Keyboard.KEY_A) && (dz != -1)) + { + dz = -1; + } + else if (Keyboard.isKeyDown(Keyboard.KEY_D) && (dz != 1)) + { + dz = 1; + } + else if (Keyboard.isKeyDown(Keyboard.KEY_W) && (dx != 1)) + { + dx = 1; + } + else if (Keyboard.isKeyDown(Keyboard.KEY_S) && (dx != -1)) + { + dx = -1; + } + } + + this.setPosition(xCoord + dx, yCoord + dy, zCoord + dz); } } - - public void zoom() { - if(zoomNumber == 0) { + + public void zoom() + { + if (zoomNumber == 0) + { this.oldFOV = mc.gameSettings.fovSetting; this.oldSens = mc.gameSettings.mouseSensitivity; - mc.gameSettings.setOptionFloatValue(EnumOptions.FOV, -0.75F); mc.gameSettings.setOptionFloatValue(EnumOptions.SENSITIVITY, 0.4F); ++zoomNumber; - } else if(zoomNumber == 1) { + } + else if (zoomNumber == 1) + { mc.gameSettings.setOptionFloatValue(EnumOptions.FOV, -1.25F); mc.gameSettings.setOptionFloatValue(EnumOptions.SENSITIVITY, 0.3F); ++zoomNumber; - } else if(zoomNumber == 2) { + } + else if (zoomNumber == 2) + { mc.gameSettings.setOptionFloatValue(EnumOptions.FOV, -1.6F); mc.gameSettings.setOptionFloatValue(EnumOptions.SENSITIVITY, 0.15F); zoomNumber = 3; - } else if(zoomNumber == 3) { + } + else if (zoomNumber == 3) + { mc.gameSettings.setOptionFloatValue(EnumOptions.FOV, this.oldFOV); mc.gameSettings.setOptionFloatValue(EnumOptions.SENSITIVITY, this.oldSens); zoomNumber = 0; - } + } } - + @Override public boolean shouldRenderInPass(int pass) { return false; - } - + } + @Override - protected void func_110147_ax() + protected void applyEntityAttributes() { - super.func_110147_ax(); - this.func_110140_aT().func_111150_b(SharedMonsterAttributes.field_111264_e).func_111128_a(1.0D); - } - + super.applyEntityAttributes(); + this.getAttributeMap().func_111150_b(SharedMonsterAttributes.attackDamage).setAttribute(1.0D); + } + @Override - public void readEntityFromNBT(NBTTagCompound nbttagcompound) { + public void readEntityFromNBT(NBTTagCompound nbttagcompound) + { this.xCoord = nbttagcompound.getInteger("x"); this.yCoord = nbttagcompound.getInteger("y"); this.zCoord = nbttagcompound.getInteger("z"); @@ -161,71 +187,80 @@ public final class EntityCamera extends EntityLivingBase { }*/ @Override - public void writeEntityToNBT(NBTTagCompound nbttagcompound) { + public void writeEntityToNBT(NBTTagCompound nbttagcompound) + { nbttagcompound.setInteger("x", this.xCoord); nbttagcompound.setInteger("y", this.yCoord); nbttagcompound.setInteger("z", this.zCoord); } - @Override - public ItemStack getHeldItem() { - return null; - } + @Override + public ItemStack getHeldItem() + { + return null; + } - @Override - public ItemStack getCurrentItemOrArmor(int i) { - return null; - } + @Override + public ItemStack getCurrentItemOrArmor(int i) + { + return null; + } - @Override - public void setCurrentItemOrArmor(int i, ItemStack itemstack) { - } + @Override + public void setCurrentItemOrArmor(int i, ItemStack itemstack) + { + } - @Override - public ItemStack[] getLastActiveItems() { - return null; - } + @Override + public ItemStack[] getLastActiveItems() + { + return null; + } // Camera frequency refresh to clients packet - public void sendTargetPacket() { + public void sendTargetPacket() + { Side side = FMLCommonHandler.instance().getEffectiveSide(); - if (side == Side.CLIENT) { + + if (side == Side.CLIENT) + { ByteArrayOutputStream bos = new ByteArrayOutputStream(8); DataOutputStream outputStream = new DataOutputStream(bos); - try { + + try + { // Write source vector - outputStream.writeInt(xCoord); - outputStream.writeInt(yCoord); - outputStream.writeInt(zCoord); - - outputStream.writeFloat(mc.renderViewEntity.rotationYaw); - outputStream.writeFloat(mc.renderViewEntity.rotationPitch); - } catch (Exception ex) { - ex.printStackTrace(); + outputStream.writeInt(xCoord); + outputStream.writeInt(yCoord); + outputStream.writeInt(zCoord); + outputStream.writeFloat(mc.renderViewEntity.rotationYaw); + outputStream.writeFloat(mc.renderViewEntity.rotationPitch); } - + catch (Exception ex) + { + ex.printStackTrace(); + } + Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "WarpDriveLaserT"; packet.data = bos.toByteArray(); packet.length = bos.size(); - PacketDispatcher.sendPacketToServer(packet); } - } - - /* - @Override - public void sendChatToPlayer(ChatMessageComponent chatmessagecomponent) { - - } + } - @Override - public boolean canCommandSenderUseCommand(int i, String s) { - return false; - } + /* + @Override + public void sendChatToPlayer(ChatMessageComponent chatmessagecomponent) { + } - @Override - public ChunkCoordinates getPlayerCoordinates() { - return new ChunkCoordinates(xCoord, yCoord, zCoord); - }*/ + @Override + public boolean canCommandSenderUseCommand(int i, String s) { + return false; + } + + @Override + public ChunkCoordinates getPlayerCoordinates() { + return new ChunkCoordinates(xCoord, yCoord, zCoord); + }*/ } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/EntityJump.java b/src/cr0s/WarpDrive/EntityJump.java index b3f1c674..d41d351d 100644 --- a/src/cr0s/WarpDrive/EntityJump.java +++ b/src/cr0s/WarpDrive/EntityJump.java @@ -1,8 +1,6 @@ package cr0s.WarpDrive; import cpw.mods.fml.common.FMLCommonHandler; -import cr0s.WarpDrive.LocalProfiler; -import cr0s.WarpDrive.WarpDrive; import dan200.computer.api.IPeripheral; import dan200.turtle.api.ITurtleAccess; import dan200.turtle.api.TurtleSide; @@ -37,7 +35,8 @@ import net.minecraftforge.common.ForgeChunkManager; import net.minecraftforge.common.ForgeChunkManager.Ticket; import net.minecraftforge.common.ForgeChunkManager.Type; -public class EntityJump extends Entity { +public class EntityJump extends Entity +{ // Jump vector private int moveX; private int moveY; @@ -63,9 +62,9 @@ public class EntityJump extends Entity { public int minY; public int dx; public int dz; - + public int mode; - + public World targetWorld; private Ticket sourceWorldTicket; private Ticket targetWorldTicket; @@ -83,127 +82,136 @@ public class EntityJump extends Entity { public final static int STATE_REMOVING = 2; int state = STATE_IDLE; int currentIndexInShip = 0; - + private final int BLOCKS_PER_TICK = 3500; - + private List<MovingEntity> entitiesOnShip; - + AxisAlignedBB axisalignedbb; - + private boolean fromSpace, toSpace, betweenWorlds; public boolean toHyperSpace, fromHyperSpace; private boolean isInHyperSpace; int destX, destY, destZ; - boolean isCoordJump; - + boolean isCoordJump; + long msCounter = 0; - - public EntityJump(World world) { + + public EntityJump(World world) + { super(world); - targetWorld = worldObj; - - System.out.println("[JE@"+this+"] Entity created (empty)"); + System.out.println("[JE@" + this + "] Entity created (empty)"); } - public EntityJump(World world, int x, int y, int z, int _dist, int _direction, int _dx, int _dz, TileEntityReactor parReactor) { + public EntityJump(World world, int x, int y, int z, int _dist, int _direction, int _dx, int _dz, TileEntityReactor parReactor) + { super(world); - this.xCoord = x; this.posX = (double) x; - this.yCoord = y; this.posY = (double) y; - this.zCoord = z; this.posZ = (double) z; - this.distance = _dist; this.dir = _direction; - shipLeft = shipRight = shipFront = shipBack = shipDown = shipUp = shipLength = 0; this.dx = _dx; this.dz = _dz; maxX = maxZ = maxY = minX = minZ = minY = 0; - targetWorld = worldObj; - - System.out.println("[JE@"+this+"] Entity created"); - + System.out.println("[JE@" + this + "] Entity created"); this.reactor = parReactor; } - public void killEntity(String reason) { - if (!on) { return; } + public void killEntity(String reason) + { + if (!on) + { + return; + } + on = false; - - System.out.println("[JE@"+this+"] Killing jump entity..."); - - if (!reason.isEmpty()) { + System.out.println("[JE@" + this + "] Killing jump entity..."); + + if (!reason.isEmpty()) + { System.out.println("[JUMP] Killed: " + reason); } unlockWorlds(); unforceChunks(); - worldObj.removeEntity(this); } @Override - public void onUpdate() { + public void onUpdate() + { if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { return; - if (!on) { - worldObj.removeEntity(this); - return; } - if (minY < 0 || maxY > 256) { + if (!on) + { + worldObj.removeEntity(this); + return; + } + + if (minY < 0 || maxY > 256) + { killEntity("Y-coord error!"); return; } - if (state == STATE_IDLE) { + if (state == STATE_IDLE) + { System.out.println("[JE] Preparing to jump..."); - prepareToJump(); - state = STATE_JUMPING; - } else if(state == STATE_JUMPING) { - if (currentIndexInShip >= ship.length-1) { + } + else if (state == STATE_JUMPING) + { + if (currentIndexInShip >= ship.length - 1) + { moveEntities(false); - currentIndexInShip = 0; - state = STATE_REMOVING; - } else { + } + else + { //moveEntities(true); moveShip(); } - } else if (state == STATE_REMOVING) { + } + else if (state == STATE_REMOVING) + { removeShip(); - if (currentIndexInShip >= ship.length-1) { + if (currentIndexInShip >= ship.length - 1) + { finishJump(); - state = STATE_IDLE; } } } - private void forceChunks() { - System.out.println("[JE@"+this+"] Forcing chunks"); + private void forceChunks() + { + System.out.println("[JE@" + this + "] Forcing chunks"); sourceWorldTicket = ForgeChunkManager.requestTicket(WarpDrive.instance, worldObj, Type.ENTITY); targetWorldTicket = ForgeChunkManager.requestTicket(WarpDrive.instance, targetWorld, Type.NORMAL); sourceWorldTicket.bindEntity(this); - int x1 = minX >> 4; int x2 = maxX >> 4; int z1 = minZ >> 4; int z2 = maxZ >> 4; - for(int x = x1; x <= x2; x++) { - for(int z = z1; z <= z2; z++) { + + for (int x = x1; x <= x2; x++) + { + for (int z = z1; z <= z2; z++) + { ForgeChunkManager.forceChunk(sourceWorldTicket, new ChunkCoordIntPair(x, z)); } } @@ -212,23 +220,34 @@ public class EntityJump extends Entity { x2 = (maxX + moveX) >> 4; z1 = (minZ + moveZ) >> 4; z2 = (maxZ + moveZ) >> 4; - for(int x = x1; x <= x2; x++) { - for(int z = z1; z <= z2; z++) { + + for (int x = x1; x <= x2; x++) + { + for (int z = z1; z <= z2; z++) + { ForgeChunkManager.forceChunk(targetWorldTicket, new ChunkCoordIntPair(x, z)); } } } - private void unforceChunks() { - System.out.println("[JE@"+this+"] Unforcing chunks"); - if(sourceWorldTicket == null || targetWorldTicket == null) return; + private void unforceChunks() + { + System.out.println("[JE@" + this + "] Unforcing chunks"); + + if (sourceWorldTicket == null || targetWorldTicket == null) + { + return; + } int x1 = minX >> 4; int x2 = maxX >> 4; int z1 = minZ >> 4; int z2 = maxZ >> 4; - for(int x = x1; x <= x2; x++) { - for(int z = z1; z <= z2; z++) { + + for (int x = x1; x <= x2; x++) + { + for (int z = z1; z <= z2; z++) + { ForgeChunkManager.unforceChunk(sourceWorldTicket, new ChunkCoordIntPair(x, z)); } } @@ -237,67 +256,82 @@ public class EntityJump extends Entity { x2 = (maxX + moveX) >> 4; z1 = (minZ + moveZ) >> 4; z2 = (maxZ + moveZ) >> 4; - for(int x = x1; x <= x2; x++) { - for(int z = z1; z <= z2; z++) { + + for (int x = x1; x <= x2; x++) + { + for (int z = z1; z <= z2; z++) + { ForgeChunkManager.unforceChunk(targetWorldTicket, new ChunkCoordIntPair(x, z)); } } ForgeChunkManager.releaseTicket(sourceWorldTicket); ForgeChunkManager.releaseTicket(targetWorldTicket); - sourceWorldTicket = null; targetWorldTicket = null; } - public void lockWorlds() { - System.out.println("[JE@"+this+"] Locking worlds..."); + public void lockWorlds() + { + System.out.println("[JE@" + this + "] Locking worlds..."); targetWorld.isRemote = true; - + // When warping between dimensions is need to lock both worlds - if (targetWorld.provider.dimensionId != worldObj.provider.dimensionId) { - worldObj.isRemote = true; + if (targetWorld.provider.dimensionId != worldObj.provider.dimensionId) + { + worldObj.isRemote = true; } } - - public void unlockWorlds() { - System.out.println("[JE@"+this+"] Unlocking worlds.."); + + public void unlockWorlds() + { + System.out.println("[JE@" + this + "] Unlocking worlds.."); targetWorld.isRemote = false; - - if (targetWorld.provider.dimensionId != worldObj.provider.dimensionId) { + + if (targetWorld.provider.dimensionId != worldObj.provider.dimensionId) + { worldObj.isRemote = false; - } + } } - public void messageToAllPlayersOnShip(String msg) { - if (entitiesOnShip != null) { - for (MovingEntity me : entitiesOnShip) { + public void messageToAllPlayersOnShip(String msg) + { + if (entitiesOnShip != null) + { + for (MovingEntity me : entitiesOnShip) + { Entity entity = me.entity; - if (entity instanceof EntityPlayer) { + if (entity instanceof EntityPlayer) + { ((EntityPlayer)entity).addChatMessage("[WarpCore] " + msg); } } } } - - public void prepareToJump() { - LocalProfiler.start("EntityJump.prepareToJump"); + public void prepareToJump() + { + LocalProfiler.start("EntityJump.prepareToJump"); isInHyperSpace = (worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID); - toSpace = (dir == -1 && (maxY + distance > 255) && worldObj.provider.dimensionId == 0); fromSpace = (dir == -2 && (minY - distance < 0) && worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID); - betweenWorlds = fromSpace || toSpace || toHyperSpace || fromHyperSpace; - if (toSpace || fromHyperSpace) { + if (toSpace || fromHyperSpace) + { targetWorld = DimensionManager.getWorld(WarpDrive.instance.spaceDimID); - } else if (fromSpace) { + } + else if (fromSpace) + { targetWorld = DimensionManager.getWorld(0); - } else if (toHyperSpace) { + } + else if (toHyperSpace) + { targetWorld = DimensionManager.getWorld(WarpDrive.instance.hyperSpaceDimID); - } else { + } + else + { targetWorld = this.worldObj; } @@ -307,29 +341,44 @@ public class EntityJump extends Entity { //turnOffModems(); // Calculate jump vector - if (isCoordJump) { + if (isCoordJump) + { moveX = destX - xCoord; moveZ = destZ - zCoord; moveY = destY - yCoord; distance = 0; - } else if (toHyperSpace || fromHyperSpace) { + } + else if (toHyperSpace || fromHyperSpace) + { moveX = moveY = moveZ = 0; distance = 0; - } else { - if (betweenWorlds) { + } + else + { + if (betweenWorlds) + { moveX = moveY = 0; - if (fromSpace) { + + if (fromSpace) + { moveY = 245 - maxY; } - if (toSpace) { + + if (toSpace) + { moveY = 0; } - } else { + } + else + { // Do not check in long jumps - if (distance < 256) { + if (distance < 256) + { distance = getPossibleJumpDistance(); } - if (distance <= shipLength) { + + if (distance <= shipLength) + { killEntity("Not enough space for jump."); messageToAllPlayersOnShip("Not enough space for jump!"); LocalProfiler.stop(); @@ -342,38 +391,52 @@ public class EntityJump extends Entity { moveZ = movementVector[2] * distance; // Нужно не упереться в пол мира и потолок космоса - if ((maxY + moveY) > 255) { + if ((maxY + moveY) > 255) + { moveY = 255 - maxY; } - if ((minY + moveY) < 5) { + + if ((minY + moveY) < 5) + { moveY = 5 - minY; } } } - if (betweenWorlds) { + if (betweenWorlds) + { System.out.println("[JE] Worlds: " + worldObj.provider.getDimensionName() + " -> " + targetWorld.provider.getDimensionName()); } - + forceChunks(); lockWorlds(); - saveEntities(axisalignedbb); System.out.println("[JE] Saved " + entitiesOnShip.size() + " entities from ship"); - if (!isCoordJump && !(toHyperSpace || fromHyperSpace)) { - if (dir != -2 && dir != -1) { + if (!isCoordJump && !(toHyperSpace || fromHyperSpace)) + { + if (dir != -2 && dir != -1) + { messageToAllPlayersOnShip("Jumping in direction " + dir + " degrees to distance " + distance + " blocks "); - } else if (dir == -1) { + } + else if (dir == -1) + { messageToAllPlayersOnShip("Jumping UP to distance " + distance + " blocks "); - } else if (dir == -2) { + } + else if (dir == -2) + { messageToAllPlayersOnShip("Jumping DOWN to distance " + distance + " blocks "); } - } else if (toHyperSpace) { + } + else if (toHyperSpace) + { messageToAllPlayersOnShip("Entering HYPERSPACE..."); - } else if (fromHyperSpace) { + } + else if (fromHyperSpace) + { messageToAllPlayersOnShip("Leaving HYPERSPACE"); - } else if (isCoordJump) + } + else if (isCoordJump) { messageToAllPlayersOnShip("Jumping by coordinates to (" + destX + "; " + yCoord + "; " + destZ + ")!"); } @@ -381,7 +444,8 @@ public class EntityJump extends Entity { bedrockOnShip = false; int shipSize = getRealShipSize(); // sets bedrockOnShip - if (bedrockOnShip) { + if (bedrockOnShip) + { killEntity("Bedrock is on the ship. Aborting."); messageToAllPlayersOnShip("Bedrock is on the ship. Aborting."); LocalProfiler.stop(); @@ -389,9 +453,7 @@ public class EntityJump extends Entity { } saveShip(shipSize); - - this.currentIndexInShip = 0; - + this.currentIndexInShip = 0; msCounter = System.currentTimeMillis(); LocalProfiler.stop(); } @@ -399,41 +461,48 @@ public class EntityJump extends Entity { /** * Finish jump: move entities, unlock worlds and delete self */ - public void finishJump() { + public void finishJump() + { System.out.println("[JE] Finished. Jump took " + ((System.currentTimeMillis() - msCounter) / 1000F) + " seconds"); - //FIXME TileEntity duplication workaround System.out.println("Removing TE duplicates. Size before: " + targetWorld.loadedTileEntityList.size()); LocalProfiler.start("EntityJump.removeDuplicates()"); - - try { - targetWorld.loadedTileEntityList = this.removeDuplicates(targetWorld.loadedTileEntityList); - } catch (Exception e) { - System.out.println("TE Duplicates removing exception: " + e.getMessage()); + + try + { + targetWorld.loadedTileEntityList = this.removeDuplicates(targetWorld.loadedTileEntityList); } - + catch (Exception e) + { + System.out.println("TE Duplicates removing exception: " + e.getMessage()); + } + LocalProfiler.stop(); - System.out.println("Removing TE duplicates. Size after: " + targetWorld.loadedTileEntityList.size()); - killEntity(""); } /** * Removing ship from world - * + * */ - public void removeShip() { + public void removeShip() + { LocalProfiler.start("EntityJump.removeShip"); int blocksToMove = Math.min(BLOCKS_PER_TICK, ship.length - currentIndexInShip); - System.out.println("[JE] Removing ship part: " + currentIndexInShip + "/" + ship.length + " [btm: " + blocksToMove + "]"); - for (int index = 0; index < blocksToMove; index++) { - if (currentIndexInShip >= ship.length) break; + for (int index = 0; index < blocksToMove; index++) + { + if (currentIndexInShip >= ship.length) + { + break; + } + JumpBlock jb = ship[currentIndexInShip]; - if (jb != null && jb.blockTileEntity != null) { + if (jb != null && jb.blockTileEntity != null) + { worldObj.removeBlockTileEntity(jb.x, jb.y, jb.z); } @@ -441,100 +510,117 @@ public class EntityJump extends Entity { int newX = jb.x + moveX; int newY = jb.y + moveY; int newZ = jb.z + moveZ; - refreshIC2Tile(targetWorld, newX, newY, newZ); - //System.out.println("[EJ] Removing block: " + jb.x + " " + jb.y + " " + jb.z + " " + jb.blockID); worldObj.setBlockToAir(jb.x, jb.y, jb.z); - currentIndexInShip++; } + LocalProfiler.stop(); } // Fix IC2 blocks after jump via reflection calls - public static void refreshIC2Tile(World world, int x, int y, int z) { - TileEntity te = world.getBlockTileEntity(x, y, z); - - if (te != null && te instanceof IEnergyTile) { - Class c = te.getClass().getSuperclass(); - - // Cable - if (c.getName().equals("ic2.core.block.wiring.TileEntityElectricBlock")) { - try { - Method method; - - method = c.getDeclaredMethod ("onUnloaded", new Class[0]); - method.invoke (te, new Object[0]); - - method = c.getDeclaredMethod ("onLoaded", new Class[0]); - method.invoke (te, new Object[0]); - } catch (Exception e) { - //e.printStackTrace(); - } - } else // Machine/Generator - if (c.getName().equals("ic2.core.block.TileEntityBlock") || c.getName().contains("ic2.core.block.generator")) { - try { - Method method; - - method = c.getDeclaredMethod ("onUnloaded", new Class[0]); - method.invoke (te, new Object[0]); - - method = c.getDeclaredMethod ("onLoaded", new Class[0]); - method.invoke (te, new Object[0]); - } catch (Exception e) { - //e.printStackTrace(); - } - } - - te.updateContainingBlockInfo(); - - try { - NetworkHelper.updateTileEntityField(te, "facing"); - } catch (Exception e) { - //e.printStackTrace(); - } - } + public static void refreshIC2Tile(World world, int x, int y, int z) + { + TileEntity te = world.getBlockTileEntity(x, y, z); + + if (te != null && te instanceof IEnergyTile) + { + Class c = te.getClass().getSuperclass(); + + // Cable + if (c.getName().equals("ic2.core.block.wiring.TileEntityElectricBlock")) + { + try + { + Method method; + method = c.getDeclaredMethod("onUnloaded", new Class[0]); + method.invoke(te, new Object[0]); + method = c.getDeclaredMethod("onLoaded", new Class[0]); + method.invoke(te, new Object[0]); + } + catch (Exception e) + { + //e.printStackTrace(); + } + } + else // Machine/Generator + if (c.getName().equals("ic2.core.block.TileEntityBlock") || c.getName().contains("ic2.core.block.generator")) + { + try + { + Method method; + method = c.getDeclaredMethod("onUnloaded", new Class[0]); + method.invoke(te, new Object[0]); + method = c.getDeclaredMethod("onLoaded", new Class[0]); + method.invoke(te, new Object[0]); + } + catch (Exception e) + { + //e.printStackTrace(); + } + } + + te.updateContainingBlockInfo(); + /* + try { + NetworkHelper.updateTileEntityField(te, "facing"); + } catch (Exception e) { + //e.printStackTrace(); + } + */ + } } - + /** * Saving ship to memory * * @param shipSize */ - public void saveShip(int shipSize) { + public void saveShip(int shipSize) + { LocalProfiler.start("EntityJump.saveShip"); ship = new JumpBlock[shipSize]; - if (ship == null) { + + if (ship == null) + { killEntity("ship is null!"); LocalProfiler.stop(); return; } - int index = 0; + int index = 0; int xc1 = minX >> 4; int xc2 = maxX >> 4; int zc1 = minZ >> 4; int zc2 = maxZ >> 4; - for (int xc = xc1; xc <= xc2; xc++) { + for (int xc = xc1; xc <= xc2; xc++) + { int x1 = Math.max(minX, xc << 4); int x2 = Math.min(maxX, (xc << 4) + 15); - for(int zc = zc1; zc <= zc2; zc++) { + + for (int zc = zc1; zc <= zc2; zc++) + { int z1 = Math.max(minZ, zc << 4); int z2 = Math.min(maxZ, (zc << 4) + 15); - for (int y = minY; y <= maxY; y++) { - for(int x = x1; x <= x2; x++) { - for(int z = z1; z <= z2; z++) { + + for (int y = minY; y <= maxY; y++) + { + for (int x = x1; x <= x2; x++) + { + for (int z = z1; z <= z2; z++) + { int blockID = worldObj.getBlockId(x, y, z); + // Skip air blocks - if (blockID == 0 || blockID == WarpDrive.instance.config.gasID) { + if (blockID == 0 || blockID == WarpDrive.instance.config.gasID) + { continue; } int blockMeta = worldObj.getBlockMetadata(x, y, z); TileEntity tileentity = worldObj.getBlockTileEntity(x, y, z); - ship[index] = new JumpBlock(blockID, blockMeta, tileentity, x, y, z); index++; } @@ -550,18 +636,23 @@ public class EntityJump extends Entity { /** *Ship moving */ - public void moveShip() { + public void moveShip() + { LocalProfiler.start("EntityJump.moveShip"); int blocksToMove = Math.min(BLOCKS_PER_TICK, ship.length - currentIndexInShip); - System.out.println("[JE] Moving ship part: " + currentIndexInShip + "/" + ship.length + " [btm: " + blocksToMove + "]"); - - for (int index = 0; index < blocksToMove; index++) { - if (currentIndexInShip >= ship.length) break; + + for (int index = 0; index < blocksToMove; index++) + { + if (currentIndexInShip >= ship.length) + { + break; + } moveBlockSimple(currentIndexInShip); currentIndexInShip++; } + LocalProfiler.stop(); } @@ -570,25 +661,29 @@ public class EntityJump extends Entity { * * @return possible jump distance or -1 */ - public int getPossibleJumpDistance() { + public int getPossibleJumpDistance() + { System.out.println("[JUMP] Calculating possible jump distance..."); int testDistance = this.distance; int blowPoints = 0; - while (testDistance >= 0) { + while (testDistance >= 0) + { // Is there enough space in destination point? boolean canJump = checkMovement(testDistance); - if (canJump) { + if (canJump) + { break; } blowPoints++; testDistance--; } - + // Make an explosion in collision point - if (blowPoints > 5 && (this.dir != -1 && this.dir != -2)) { + if (blowPoints > 5 && (this.dir != -1 && this.dir != -2)) + { messageToAllPlayersOnShip(" [COLLISION] at (" + blowX + "; " + blowY + "; " + blowZ + ")"); worldObj.createExplosion((Entity) null, blowX, blowY, blowZ, Math.min(4F * 30, 4F * (distance / 2)), true); } @@ -597,25 +692,31 @@ public class EntityJump extends Entity { } /* - * Получить реальное количество блоков, из которых состоит корабль + * Получить реальное количество блоков, из которых состоит корабль */ - public int getRealShipSize() { + public int getRealShipSize() + { LocalProfiler.start("EntityJump.getRealShipSize"); int shipSize = 0; - for (int x = minX; x <= maxX; x++) { - for (int z = minZ; z <= maxZ; z++) { - for (int y = minY; y <= maxY; y++) { + for (int x = minX; x <= maxX; x++) + { + for (int z = minZ; z <= maxZ; z++) + { + for (int y = minY; y <= maxY; y++) + { int blockID = worldObj.getBlockId(x, y, z); // Skipping air blocks - if (blockID == 0 || blockID == WarpDrive.instance.config.gasID) { - continue; + if (blockID == 0 || blockID == WarpDrive.instance.config.gasID) + { + continue; } - + shipSize++; - if (blockID == Block.bedrock.blockID) { + if (blockID == Block.bedrock.blockID) + { bedrockOnShip = true; LocalProfiler.stop(); return shipSize; @@ -628,53 +729,63 @@ public class EntityJump extends Entity { return shipSize; } - public void saveEntities(AxisAlignedBB axisalignedbb) { + public void saveEntities(AxisAlignedBB axisalignedbb) + { entitiesOnShip = new ArrayList<MovingEntity>(); List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, axisalignedbb); - for (Object o : list) { - if (o == null || !(o instanceof Entity) || (o instanceof EntityJump)) { + for (Object o : list) + { + if (o == null || !(o instanceof Entity) || (o instanceof EntityJump)) + { continue; } Entity entity = (Entity)o; - MovingEntity movingEntity = new MovingEntity(entity); - // Добавим в список Entity entitiesOnShip.add(movingEntity); } } - + /** * Перемещение сущностей вместе с кораблем * @param axisalignedbb область корабля * @param distance расстояние перемещения * @param direction направление перемещения * @param restorePositions восстановление старых позиций для предотвращения выпадения, либо перемещение на новую - * @return + * @return */ - public boolean moveEntities(boolean restorePositions) { + public boolean moveEntities(boolean restorePositions) + { System.out.println("[JE] Moving entities"); - if (entitiesOnShip != null) { - for (MovingEntity me : entitiesOnShip) { + + if (entitiesOnShip != null) + { + for (MovingEntity me : entitiesOnShip) + { Entity entity = me.entity; - - if (entity == null) { continue; } + + if (entity == null) + { + continue; + } double oldEntityX = me.oldX; double oldEntityY = me.oldY; double oldEntityZ = me.oldZ; - double newEntityX; double newEntityY; double newEntityZ; - if (restorePositions) { + if (restorePositions) + { newEntityX = oldEntityX; newEntityY = oldEntityY; newEntityZ = oldEntityZ; - } else { + } + else + { newEntityX = oldEntityX + moveX; newEntityY = oldEntityY + moveY; newEntityZ = oldEntityZ + moveZ; @@ -683,28 +794,33 @@ public class EntityJump extends Entity { //System.out.println("Entity moving: old (" + oldEntityX + " " + oldEntityY + " " + oldEntityZ + ") -> new (" + newEntityX + " " + newEntityY + " " + newEntityZ); // Travel to another dimension if needed - if(betweenWorlds && !restorePositions) { + if (betweenWorlds && !restorePositions) + { MinecraftServer server = MinecraftServer.getServer(); WorldServer from = server.worldServerForDimension(worldObj.provider.dimensionId); WorldServer to = server.worldServerForDimension(targetWorld.provider.dimensionId); - SpaceTeleporter teleporter = new SpaceTeleporter(to, 0, MathHelper.floor_double(newEntityX), MathHelper.floor_double(newEntityY), MathHelper.floor_double(newEntityZ)); - if (entity instanceof EntityPlayerMP) { + if (entity instanceof EntityPlayerMP) + { EntityPlayerMP player = (EntityPlayerMP) entity; server.getConfigurationManager().transferPlayerToDimension(player, targetWorld.provider.dimensionId, teleporter); - } else { + } + else + { server.getConfigurationManager().transferEntityToWorld(entity, worldObj.provider.dimensionId, from, to, teleporter); } } // Update position - if (entity instanceof EntityPlayerMP) { + if (entity instanceof EntityPlayerMP) + { EntityPlayerMP player = (EntityPlayerMP) entity; - // Если на корабле есть кровать, то передвинуть точку спауна игрока ChunkCoordinates bedLocation = player.getBedLocation(); - if (bedLocation != null && testBB(axisalignedbb, bedLocation.posX, bedLocation.posY, bedLocation.posZ)) { + + if (bedLocation != null && testBB(axisalignedbb, bedLocation.posX, bedLocation.posY, bedLocation.posZ)) + { bedLocation.posX = bedLocation.posX + moveX; bedLocation.posY = bedLocation.posY + moveY; bedLocation.posZ = bedLocation.posZ + moveZ; @@ -712,7 +828,9 @@ public class EntityJump extends Entity { } player.setPositionAndUpdate(newEntityX, newEntityY, newEntityZ); - } else { + } + else + { entity.setPosition(newEntityX, newEntityY, newEntityZ); } } @@ -724,17 +842,21 @@ public class EntityJump extends Entity { /** * Проверка на вхождение точки в область (bounding-box) */ - public boolean testBB(AxisAlignedBB axisalignedbb, int x, int y, int z) { + public boolean testBB(AxisAlignedBB axisalignedbb, int x, int y, int z) + { return axisalignedbb.minX <= (double) x && axisalignedbb.maxX >= (double) x && axisalignedbb.minY <= (double) y && axisalignedbb.maxY >= (double) y && axisalignedbb.minZ <= (double) z && axisalignedbb.maxZ >= (double) z; } // Получение вектора в зависимости от направления прыжка - public int[] getVector(int i) { - int v[] = { + public int[] getVector(int i) + { + int v[] = + { 0, 0, 0 }; - switch(i) { + switch (i) + { case -1: v[1] = 1; break; @@ -773,17 +895,19 @@ public class EntityJump extends Entity { * @param i * @return true, если корабль уместился на новом месте */ - public boolean checkMovement(int testDistance) { - if ((dir == -1 && maxY + testDistance > 255) && !toSpace) { + public boolean checkMovement(int testDistance) + { + if ((dir == -1 && maxY + testDistance > 255) && !toSpace) + { System.out.println("[JUMP] Reactor will blow due +high limit"); return false; } - if ((dir == -2 && minY - testDistance <= 8) && !fromSpace) { + if ((dir == -2 && minY - testDistance <= 8) && !fromSpace) + { blowY = minY - testDistance; blowX = xCoord; blowZ = zCoord; - System.out.println("[JUMP] Reactor will blow due -low limit"); return false; } @@ -794,29 +918,34 @@ public class EntityJump extends Entity { int moveY = movementVector[1] * testDistance; int moveZ = movementVector[2] * testDistance; - for (int y = minY; y <= maxY; y++) { - for (int x = minX; x <= maxX; x++) { - for (int z = minZ; z <= maxZ; z++) { + for (int y = minY; y <= maxY; y++) + { + for (int x = minX; x <= maxX; x++) + { + for (int z = minZ; z <= maxZ; z++) + { int newX = x + moveX; int newY = y + moveY; int newZ = z + moveZ; - if (isBlockInShip(newX, newY, newZ)) { + if (isBlockInShip(newX, newY, newZ)) + { continue; } int blockID = worldObj.getBlockId(newX, newY, newZ); int blockOnShipID = worldObj.getBlockId(x, y, z); - if (blockOnShipID == Block.bedrock.blockID) { + if (blockOnShipID == Block.bedrock.blockID) + { return false; } - if (blockOnShipID != 0 && blockID != 0 && blockID != WarpDrive.instance.config.airID && blockID != WarpDrive.instance.config.gasID && blockID != 18) { + if (blockOnShipID != 0 && blockID != 0 && blockID != WarpDrive.instance.config.airID && blockID != WarpDrive.instance.config.gasID && blockID != 18) + { blowX = x; blowY = y; blowZ = z; - System.out.println((new StringBuilder()).append("[JUMP] Reactor will blow due BlockID ").append((new StringBuilder()).append(blockID).append(" at (").append(newX).append(";").append(newY).append(";").append(newZ).append(")").toString()).toString()); return false; } @@ -835,7 +964,8 @@ public class EntityJump extends Entity { * @param z * @return true, если находится */ - public boolean isBlockInShip(int x, int y, int z) { + public boolean isBlockInShip(int x, int y, int z) + { return x >= minX && x <= maxX && y >= minY && y <= maxY && z >= minZ && z <= maxZ; } @@ -843,7 +973,8 @@ public class EntityJump extends Entity { * Выключение модема, если периферийное устройство является модемом * @param p - периферийное устройство */ - private void turnOffModem(IPeripheral p) { + private void turnOffModem(IPeripheral p) + { // FIXME /*if (p.getType() == "modem") { String[] methods = p.getMethodNames(); @@ -863,7 +994,8 @@ public class EntityJump extends Entity { /** * Выключение всех модемов на корабле */ - private void turnOffModems() { + private void turnOffModems() + { // FIXME /*for (int x = minX; x <= maxX; x++) { for (int z = minZ; z <= maxZ; z++) { @@ -892,105 +1024,116 @@ public class EntityJump extends Entity { }*/ } - - public boolean moveBlockSimple(int indexInShip) { - try { + public boolean moveBlockSimple(int indexInShip) + { + try + { JumpBlock shipBlock = ship[indexInShip]; - if (shipBlock == null) { + if (shipBlock == null) + { return false; } int oldX = shipBlock.x; int oldY = shipBlock.y; int oldZ = shipBlock.z; - int newX = oldX + moveX; int newY = oldY + moveY; int newZ = oldZ + moveZ; - int blockID = shipBlock.blockID; int blockMeta = shipBlock.blockMeta; - mySetBlock(targetWorld, newX, newY, newZ, blockID, blockMeta, 2); + // Re-schedule air blocks update - if (blockID == WarpDrive.instance.config.airID) { - targetWorld.markBlockForUpdate(newX, newY, newZ); - targetWorld.scheduleBlockUpdate(newX, newY, newZ, blockID, 40 + targetWorld.rand.nextInt(20)); + if (blockID == WarpDrive.instance.config.airID) + { + targetWorld.markBlockForUpdate(newX, newY, newZ); + targetWorld.scheduleBlockUpdate(newX, newY, newZ, blockID, 40 + targetWorld.rand.nextInt(20)); } - - + NBTTagCompound oldnbt = new NBTTagCompound(); - - if (shipBlock.blockTileEntity != null && blockID != 159 && blockID != 149 && blockID != 156 && blockID != 146 && blockID != 145) { + if (shipBlock.blockTileEntity != null && blockID != 159 && blockID != 149 && blockID != 156 && blockID != 146 && blockID != 145) + { shipBlock.blockTileEntity.writeToNBT(oldnbt); TileEntity newTileEntity = null; + // CC's computers and turtles moving workaround - if (blockID == 1225 || blockID == 1226 || blockID == 1227 || blockID == 1228 || blockID == 1230) { + if (blockID == 1225 || blockID == 1226 || blockID == 1227 || blockID == 1228 || blockID == 1230) + { oldnbt.setInteger("x", newX); oldnbt.setInteger("y", newY); oldnbt.setInteger("z", newZ); - newTileEntity = TileEntity.createAndLoadEntity(oldnbt); newTileEntity.invalidate(); - } else { + } + else + { newTileEntity = targetWorld.getBlockTileEntity(newX, newY, newZ); - if (newTileEntity == null) { + + if (newTileEntity == null) + { System.out.println("[EJ] Error moving tileEntity! TE is null"); return false; } newTileEntity.invalidate(); - newTileEntity.readFromNBT(oldnbt); } newTileEntity.worldObj = targetWorld; newTileEntity.validate(); - worldObj.removeBlockTileEntity(oldX, oldY, oldZ); - targetWorld.setBlockTileEntity(newX, newY, newZ, newTileEntity); } - } catch (Exception exception) { + } + catch (Exception exception) + { exception.printStackTrace(); return false; } return true; } - - public ArrayList<Object> removeDuplicates(List<TileEntity> l) { - Set<TileEntity> s = new TreeSet<TileEntity>(new Comparator<TileEntity>() { + public ArrayList<Object> removeDuplicates(List<TileEntity> l) + { + Set<TileEntity> s = new TreeSet<TileEntity>(new Comparator<TileEntity>() + { @Override - public int compare(TileEntity o1, TileEntity o2) { - if (o1.xCoord == o2.xCoord && o1.yCoord == o2.yCoord && o1.zCoord == o2.zCoord) { - System.out.println("Removed duplicated TE: " + o1 + ", " + o2); - return 0; - } else { - return 1; + public int compare(TileEntity o1, TileEntity o2) + { + if (o1.xCoord == o2.xCoord && o1.yCoord == o2.yCoord && o1.zCoord == o2.zCoord) + { + System.out.println("Removed duplicated TE: " + o1 + ", " + o2); + return 0; + } + else + { + return 1; } } }); - s.addAll(l); return new ArrayList<Object>(Arrays.asList(s.toArray())); } - + @Override - protected void readEntityFromNBT(NBTTagCompound nbttagcompound) { + protected void readEntityFromNBT(NBTTagCompound nbttagcompound) + { //System.out.println("[JE@"+this+"] readEntityFromNBT()"); } @Override - protected void entityInit() { + protected void entityInit() + { //System.out.println("[JE@"+this+"] entityInit()"); } @Override - protected void writeEntityToNBT(NBTTagCompound var1) { + protected void writeEntityToNBT(NBTTagCompound var1) + { //System.out.println("[JE@"+this+"] writeEntityToNBT()"); } @@ -1011,7 +1154,6 @@ public class EntityJump extends Entity { { w.markBlockForUpdate(x, y, z); Chunk chunk = w.getChunkFromChunkCoords(x >> 4, z >> 4); - return myChunkSBIDWMT(chunk, x & 15, y, z & 15, blockId, blockMeta); } } @@ -1055,7 +1197,6 @@ public class EntityJump extends Entity { int j2 = c.xPosition * 16 + x; int k2 = c.zPosition * 16 + z; - extendedblockstorage.setExtBlockID(x, y & 15, z, blockId); if (l1 != 0) @@ -1067,6 +1208,7 @@ public class EntityJump extends Entity { else if (Block.blocksList[l1] != null && Block.blocksList[l1].hasTileEntity(i2)) { TileEntity te = worldObj.getBlockTileEntity(j2, y, k2); + if (te != null && te.shouldRefresh(l1, blockId, i2, blockMeta, worldObj, j2, y, k2)) { c.worldObj.removeBlockTileEntity(j2, y, k2); @@ -1081,7 +1223,6 @@ public class EntityJump extends Entity { else { extendedblockstorage.setExtBlockMetadata(x, y & 15, z, blockMeta); - // Removed light recalculations /*if (flag) { @@ -1103,7 +1244,6 @@ public class EntityJump extends Entity { c.propagateSkylightOcclusion(par1, par3); }*/ - TileEntity tileentity; if (blockId != 0) @@ -1130,5 +1270,5 @@ public class EntityJump extends Entity { return true; } } - } + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/EntitySphereGen.java b/src/cr0s/WarpDrive/EntitySphereGen.java index b7d0c1b1..21844388 100644 --- a/src/cr0s/WarpDrive/EntitySphereGen.java +++ b/src/cr0s/WarpDrive/EntitySphereGen.java @@ -4,8 +4,6 @@ import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Loader; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.JumpBlock; -import cr0s.WarpDrive.LocalProfiler; import java.util.ArrayList; import java.util.List; @@ -19,251 +17,340 @@ import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; -public final class EntitySphereGen extends Entity { +public final class EntitySphereGen extends Entity +{ public int xCoord; public int yCoord; public int zCoord; - + private int radius; private int blockID; private int blockMeta; private boolean hollow; private boolean fillingSphere; // new sphere blocks does not replace existing blocks (for gases) - private boolean surfaceSphere; // generate random surface blocks or fixed blockID - + private boolean surfaceSphere; // generate random surface blocks or fixed blockID + private final int BLOCKS_PER_TICK = 10000; private final int STATE_SAVING = 0; private final int STATE_SETUP = 1; private final int STATE_STOP = 2; private int state = STATE_SAVING; - + private int currentIndex = 0; - + private ArrayList<JumpBlock> blocks; - + private boolean isICBMLoaded = false, isAELoaded = false; - + private List<Integer> ores; - - public EntitySphereGen(World world) { + + public EntitySphereGen(World world) + { super(world); } - public EntitySphereGen(World world, int x, int y, int z, int radius, int blockID, int blockMeta, boolean hollow, boolean fillingSphere, boolean surfaceSphere) { + public EntitySphereGen(World world, int x, int y, int z, int radius, int blockID, int blockMeta, boolean hollow, boolean fillingSphere, boolean surfaceSphere) + { super(world); - // Check for mods is present isICBMLoaded = Loader.isModLoaded("ICBM|Explosion"); - isAELoaded = Loader.isModLoaded("AppliedEnergistics"); - + isAELoaded = Loader.isModLoaded("AppliedEnergistics"); this.xCoord = x; this.posX = (double) x; - this.yCoord = y; this.posY = (double) y; - this.zCoord = z; this.posZ = (double) z; - this.radius = radius; this.blockID = blockID; this.blockMeta = blockMeta; this.hollow = hollow; this.fillingSphere = fillingSphere; this.surfaceSphere = surfaceSphere; - this.state = STATE_SAVING; - blocks = new ArrayList<JumpBlock>(); ores = (List<Integer>)TileEntityMiningLaser.valuableOres.clone(); - + if (isICBMLoaded) { ores.add(3880); ores.add(3970); ores.add(39701); - } + } } - public void killEntity() { + public void killEntity() + { this.state = STATE_STOP; worldObj.removeEntity(this); } @Override - public void onUpdate() { + public void onUpdate() + { if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { return; - - switch (this.state) { + } + + switch (this.state) + { case STATE_SAVING: System.out.println("[ESG] Saving blocks..."); saveSphereBlocks(); this.state = STATE_SETUP; break; - + case STATE_SETUP: - if (currentIndex >= blocks.size()-1) { + if (currentIndex >= blocks.size() - 1) + { currentIndex = 0; killEntity(); - } else { + } + else + { setupBlocksTick(); } } } - - private void setupBlocksTick() { + + private void setupBlocksTick() + { LocalProfiler.start("EntitySphereGen.setupBlocksTick"); int blocksToMove = Math.min(BLOCKS_PER_TICK, blocks.size() - currentIndex); - System.out.println("[ESG] Setting up blocks: " + currentIndex + "/" + blocks.size() + " [bts: " + blocksToMove + "]"); int notifyFlag; - - for (int index = 0; index < blocksToMove; index++) { - if (currentIndex >= blocks.size()) break; + + for (int index = 0; index < blocksToMove; index++) + { + if (currentIndex >= blocks.size()) + { + break; + } notifyFlag = (currentIndex % 1000 == 0 ? 2 : 0); - JumpBlock jb = blocks.get(currentIndex); mySetBlock(worldObj, jb.x, jb.y, jb.z, jb.blockID, jb.blockMeta, notifyFlag); - currentIndex++; } - LocalProfiler.stop(); + + LocalProfiler.stop(); } - - private void saveSphereBlocks() { + + private void saveSphereBlocks() + { radius += 0.5D; // Radius from center of block double radiusSq = radius * radius; // Optimization to avoid square roots double radius1Sq = (radius - 1.0D) * (radius - 1.0D); // for hollow sphere - int ceilRadius = (int) Math.ceil(radius); - + // Pass the cube and check points for sphere equation x^2 + y^2 + z^2 = r^2 - for (int x = 0; x <= ceilRadius; x++) { - for (int y = 0; y <= ceilRadius; y++) { - for (int z = 0; z <= ceilRadius; z++) { + for (int x = 0; x <= ceilRadius; x++) + { + for (int y = 0; y <= ceilRadius; y++) + { + for (int z = 0; z <= ceilRadius; z++) + { double dSq = lengthSq(x, y, z); // Distance from current position to center // Skip too far blocks - if (dSq > radiusSq) { + if (dSq > radiusSq) + { continue; } // Hollow sphere condition if ((hollow) && ( - (dSq < radius1Sq) || ((lengthSq(x + 1, y, z) <= radiusSq) && (lengthSq(x, y + 1, z) <= radiusSq) && (lengthSq(x, y, z + 1) <= radiusSq)))) + (dSq < radius1Sq) || ((lengthSq(x + 1, y, z) <= radiusSq) && (lengthSq(x, y + 1, z) <= radiusSq) && (lengthSq(x, y, z + 1) <= radiusSq)))) { - continue; + continue; } - if (surfaceSphere) { + if (surfaceSphere) + { blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - if (blockID == 39701) { blockMeta = blockID % 10; blockID = blockID / 10; } + + if (blockID == 39701) + { + blockMeta = blockID % 10; + blockID = blockID / 10; + } } + // Add blocks to memory addBlock(new JumpBlock(blockID, blockMeta, xCoord + x, yCoord + y, zCoord + z)); - - if (surfaceSphere) { + + if (surfaceSphere) + { blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - if (blockID == 39701) { blockMeta = blockID % 10; blockID = blockID / 10; } + + if (blockID == 39701) + { + blockMeta = blockID % 10; + blockID = blockID / 10; + } } + addBlock(new JumpBlock(blockID, blockMeta, xCoord - x, yCoord + y, zCoord + z)); - - if (surfaceSphere) { + + if (surfaceSphere) + { blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - if (blockID == 39701) { blockMeta = blockID % 10; blockID = blockID / 10; } - } + + if (blockID == 39701) + { + blockMeta = blockID % 10; + blockID = blockID / 10; + } + } + addBlock(new JumpBlock(blockID, blockMeta, xCoord + x, yCoord - y, zCoord + z)); - - if (surfaceSphere) { + + if (surfaceSphere) + { blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - if (blockID == 39701) { blockMeta = blockID % 10; blockID = blockID / 10; } - } + + if (blockID == 39701) + { + blockMeta = blockID % 10; + blockID = blockID / 10; + } + } + addBlock(new JumpBlock(blockID, blockMeta, xCoord + x, yCoord + y, zCoord - z)); - - if (surfaceSphere) { + + if (surfaceSphere) + { blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - if (blockID == 39701) { blockMeta = blockID % 10; blockID = blockID / 10; } - } + + if (blockID == 39701) + { + blockMeta = blockID % 10; + blockID = blockID / 10; + } + } + addBlock(new JumpBlock(blockID, blockMeta, xCoord - x, yCoord - y, zCoord + z)); - - if (surfaceSphere) { + + if (surfaceSphere) + { blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - if (blockID == 39701) { blockMeta = blockID % 10; blockID = blockID / 10; } - } + + if (blockID == 39701) + { + blockMeta = blockID % 10; + blockID = blockID / 10; + } + } + addBlock(new JumpBlock(blockID, blockMeta, xCoord + x, yCoord - y, zCoord - z)); - - if (surfaceSphere) { + + if (surfaceSphere) + { blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - if (blockID == 39701) { blockMeta = blockID % 10; blockID = blockID / 10; } - } + + if (blockID == 39701) + { + blockMeta = blockID % 10; + blockID = blockID / 10; + } + } + addBlock(new JumpBlock(blockID, blockMeta, xCoord - x, yCoord + y, zCoord - z)); - - if (surfaceSphere) { + + if (surfaceSphere) + { blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - if (blockID == 39701) { blockMeta = blockID % 10; blockID = blockID / 10; } - } + + if (blockID == 39701) + { + blockMeta = blockID % 10; + blockID = blockID / 10; + } + } + addBlock(new JumpBlock(blockID, blockMeta, xCoord - x, yCoord - y, zCoord - z)); } } } - + if (blocks != null) - System.out.println("[ESG] Saved " + blocks.size() + " blocks"); + { + System.out.println("[ESG] Saved " + blocks.size() + " blocks"); + } } - - private void addBlock(JumpBlock jb) { + + private void addBlock(JumpBlock jb) + { // Do not replace exitsting blocks if fillingSphere is true - if (fillingSphere && !worldObj.isAirBlock(jb.x, jb.y, jb.z)) { + if (fillingSphere && !worldObj.isAirBlock(jb.x, jb.y, jb.z)) + { return; } - - if (blocks == null) { return; } + + if (blocks == null) + { + return; + } + blocks.add(jb); } - - public int getRandomSurfaceBlockID(Random random, boolean corrupted, boolean nocobble) { + + public int getRandomSurfaceBlockID(Random random, boolean corrupted, boolean nocobble) + { int _blockID = Block.stone.blockID; - if (corrupted) { + + if (corrupted) + { _blockID = Block.cobblestone.blockID; } - if (random.nextInt(25) == 5 || nocobble) { + if (random.nextInt(25) == 5 || nocobble) + { _blockID = ores.get(random.nextInt(ores.size())); - } - else if (random.nextInt(350) == 1 && isAELoaded) { + } + else if (random.nextInt(350) == 1 && isAELoaded) + { _blockID = 902; // quarz (AE) } - else if (random.nextInt(500) == 1) { + else if (random.nextInt(500) == 1) + { _blockID = Block.oreDiamond.blockID; - } else if (random.nextInt(1000) == 1) { + } + else if (random.nextInt(1000) == 1) + { _blockID = Block.bedrock.blockID; - } else if (random.nextInt(10000) == 42) { + } + else if (random.nextInt(10000) == 42) + { _blockID = WarpDrive.instance.config.iridiumID; } return _blockID; - } - - private static double lengthSq(double x, double y, double z) { + } + + private static double lengthSq(double x, double y, double z) + { return (x * x) + (y * y) + (z * z); - } - - @Override - protected void readEntityFromNBT(NBTTagCompound nbttagcompound) { } @Override - protected void entityInit() { + protected void readEntityFromNBT(NBTTagCompound nbttagcompound) + { } @Override - protected void writeEntityToNBT(NBTTagCompound var1) { + protected void entityInit() + { } - - // Own implementation of setting blocks withow light recalculation in optimization purposes + + @Override + protected void writeEntityToNBT(NBTTagCompound var1) + { + } + + // Own implementation of setting blocks withow light recalculation in optimization purposes public boolean mySetBlock(World w, int x, int y, int z, int blockId, int blockMeta, int par6) { if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) @@ -280,7 +367,6 @@ public final class EntitySphereGen extends Entity { { w.markBlockForUpdate(x, y, z); Chunk chunk = w.getChunkFromChunkCoords(x >> 4, z >> 4); - return myChunkSBIDWMT(chunk, x & 15, y, z & 15, blockId, blockMeta); } } @@ -324,7 +410,6 @@ public final class EntitySphereGen extends Entity { int j2 = c.xPosition * 16 + x; int k2 = c.zPosition * 16 + z; - extendedblockstorage.setExtBlockID(x, y & 15, z, blockId); if (extendedblockstorage.getExtBlockID(x, y & 15, z) != blockId) @@ -334,7 +419,6 @@ public final class EntitySphereGen extends Entity { else { extendedblockstorage.setExtBlockMetadata(x, y & 15, z, blockMeta); - TileEntity tileentity; if (blockId != 0) diff --git a/src/cr0s/WarpDrive/EntityStarCore.java b/src/cr0s/WarpDrive/EntityStarCore.java index 6443f72f..f362d58f 100644 --- a/src/cr0s/WarpDrive/EntityStarCore.java +++ b/src/cr0s/WarpDrive/EntityStarCore.java @@ -9,53 +9,53 @@ import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.DamageSource; import net.minecraft.world.World; -public final class EntityStarCore extends Entity { +public final class EntityStarCore extends Entity +{ public int xCoord; public int yCoord; public int zCoord; - + private int radius; - + private final int KILL_RADIUS = 60; private final int BURN_RADIUS = 200; //private final int ROCKET_INTERCEPT_RADIUS = 100; //disabled private final int ENTITY_ACTION_INTERVAL = 10; // ticks - + private int ticks = 0; - - public EntityStarCore(World world) { + + public EntityStarCore(World world) + { super(world); } - public EntityStarCore(World world, int x, int y, int z, int radius) { + public EntityStarCore(World world, int x, int y, int z, int radius) + { super(world); - this.xCoord = x; this.posX = (double) x; - this.yCoord = y; this.posY = (double) y; - this.zCoord = z; this.posZ = (double) z; - this.radius = radius; } - - private void actionToEntitiesNearStar() { + + private void actionToEntitiesNearStar() + { int xmax, ymax, zmax, x1, x2, z1, z2; int xmin, ymin, zmin; - final int CUBE_SIDE = this.radius + KILL_RADIUS + BURN_RADIUS;// + ROCKET_INTERCEPT_RADIUS; - x1 = xCoord + CUBE_SIDE; x2 = xCoord - CUBE_SIDE; - - if (x1 < x2) { + + if (x1 < x2) + { xmin = x1; xmax = x2; - } else + } + else { xmin = x2; xmax = x1; @@ -63,19 +63,20 @@ public final class EntityStarCore extends Entity { z1 = zCoord + CUBE_SIDE; z2 = zCoord - CUBE_SIDE; - - if (z1 < z2) { + + if (z1 < z2) + { zmin = z1; zmax = z2; - } else + } + else { zmin = z2; zmax = z1; } ymax = yCoord + CUBE_SIDE; - ymin = yCoord - CUBE_SIDE; - + ymin = yCoord - CUBE_SIDE; AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(xmin, ymin, zmin, xmax, ymax, zmax); List list = worldObj.getEntitiesWithinAABBExcludingEntity(this, aabb); @@ -85,24 +86,31 @@ public final class EntityStarCore extends Entity { System.out.println("[" + this + "] Y: " + ymin + " -> " + ymax); System.out.println("[" + this + "] Z: " + zmin + " -> " + zmax); */ - for (Object o : list) { - if (o == null || !(o instanceof Entity)) { + for (Object o : list) + { + if (o == null || !(o instanceof Entity)) + { continue; } - - if (o instanceof EntityLivingBase) { - EntityLivingBase entity = (EntityLivingBase)o; + + if (o instanceof EntityLivingBase) + { + EntityLivingBase entity = (EntityLivingBase)o; //System.out.println("Found: " + entity.getEntityName() + " distance: " + entity.getDistanceToEntity(this)); - if (entity.getDistanceToEntity(this) <= (this.radius + KILL_RADIUS)) { + if (entity.getDistanceToEntity(this) <= (this.radius + KILL_RADIUS)) + { // 100% kill, ignores any protection entity.attackEntityFrom(DamageSource.onFire, 9000); - } else if (entity.getDistanceToEntity(this) <= (this.radius + BURN_RADIUS)) { + } + else if (entity.getDistanceToEntity(this) <= (this.radius + BURN_RADIUS)) + { // burn entity to 100 seconds entity.setFire(100); entity.attackEntityFrom(DamageSource.onFire, 1); } }/* else { // Intercept ICBM rocket and kill + Entity entity = (Entity) o; if (entity.getDistanceToEntity(this) <= (this.radius + ROCKET_INTERCEPT_RADIUS)) { System.out.println("[SC] Intercepted entity: " + entity.getEntityName()); @@ -112,36 +120,43 @@ public final class EntityStarCore extends Entity { } } - public void killEntity() { + public void killEntity() + { worldObj.removeEntity(this); } @Override - public void onUpdate() { + public void onUpdate() + { if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { return; - - if (++ticks > ENTITY_ACTION_INTERVAL) { + } + + if (++ticks > ENTITY_ACTION_INTERVAL) + { ticks = 0; actionToEntitiesNearStar(); } } - + @Override - protected void readEntityFromNBT(NBTTagCompound nbttagcompound) { + protected void readEntityFromNBT(NBTTagCompound nbttagcompound) + { this.xCoord = nbttagcompound.getInteger("x"); this.yCoord = nbttagcompound.getInteger("y"); this.zCoord = nbttagcompound.getInteger("z"); - this.radius = nbttagcompound.getInteger("radius"); } @Override - protected void entityInit() { + protected void entityInit() + { } @Override - protected void writeEntityToNBT(NBTTagCompound nbttagcompound) { + protected void writeEntityToNBT(NBTTagCompound nbttagcompound) + { nbttagcompound.setInteger("x", this.xCoord); nbttagcompound.setInteger("y", this.yCoord); nbttagcompound.setInteger("z", this.zCoord); diff --git a/src/cr0s/WarpDrive/FXBeam.java b/src/cr0s/WarpDrive/FXBeam.java index 84b12234..cc84f312 100644 --- a/src/cr0s/WarpDrive/FXBeam.java +++ b/src/cr0s/WarpDrive/FXBeam.java @@ -11,7 +11,6 @@ import net.minecraft.world.World; import org.lwjgl.opengl.GL11; - //import calclavia.lib.render.CalclaviaRenderHelper; import cpw.mods.fml.client.FMLClientHandler; import cpw.mods.fml.relauncher.Side; @@ -20,265 +19,271 @@ import cpw.mods.fml.relauncher.SideOnly; @SideOnly(Side.CLIENT) public class FXBeam extends EntityFX { - private static ResourceLocation TEXTURE = null; + private static ResourceLocation TEXTURE = null; - double movX = 0.0D; - double movY = 0.0D; - double movZ = 0.0D; + double movX = 0.0D; + double movY = 0.0D; + double movZ = 0.0D; - private float length = 0.0F; - private float rotYaw = 0.0F; - private float rotPitch = 0.0F; - private float prevYaw = 0.0F; - private float prevPitch = 0.0F; - private Vector3 target = new Vector3(); - private float endModifier = 1.0F; - private boolean reverse = false; - private boolean pulse = true; - private int rotationSpeed = 20; - private float prevSize = 0.0F; - private int energy = 0; + private float length = 0.0F; + private float rotYaw = 0.0F; + private float rotPitch = 0.0F; + private float prevYaw = 0.0F; + private float prevPitch = 0.0F; + private Vector3 target = new Vector3(); + private float endModifier = 1.0F; + private boolean reverse = false; + private boolean pulse = true; + private int rotationSpeed = 20; + private float prevSize = 0.0F; + private int energy = 0; - boolean a = false; - - public FXBeam(World par1World, Vector3 position, float yaw, float pitch, float red, float green, float blue, int age, int energy) { - super(par1World, position.x, position.y, position.z, 0.0D, 0.0D, 0.0D); + boolean a = false; - a = true; - - this.setRGB(red, green, blue); + public FXBeam(World par1World, Vector3 position, float yaw, float pitch, float red, float green, float blue, int age, int energy) + { + super(par1World, position.x, position.y, position.z, 0.0D, 0.0D, 0.0D); + a = true; + this.setRGB(red, green, blue); + this.setSize(0.02F, 0.02F); + this.noClip = true; + this.motionX = 0.0D; + this.motionY = 0.0D; + this.motionZ = 0.0D; + this.length = 200; + this.rotYaw = yaw; + this.rotPitch = pitch; + this.prevYaw = this.rotYaw; + this.prevPitch = this.rotPitch; + this.particleMaxAge = age; + this.energy = energy; - this.setSize(0.02F, 0.02F); - this.noClip = true; - this.motionX = 0.0D; - this.motionY = 0.0D; - this.motionZ = 0.0D; - - this.length = 200; - this.rotYaw = yaw; - this.rotPitch = pitch; - this.prevYaw = this.rotYaw; - this.prevPitch = this.rotPitch; + if (red == 1 && green == 0 && blue == 0) + { + TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_red.png"); + } + else if (red == 0 && green == 1 && blue == 0) + { + TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_green.png"); + } + else if (red == 0 && green == 0 && blue == 1) + { + TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy.png"); + } + else if (red == 1 && green == 1 && blue == 0) + { + TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_yellow.png"); + } + else if (red == 1 && green == 0.5 && blue == 0) + { + TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_orange.png"); + } + else if (red == 0.5 && green == 0 && blue == 0.5) + { + TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_violet.png"); + } - this.particleMaxAge = age; - this.energy = energy; + /** + * Sets the particle age based on distance. + */ + EntityLivingBase renderentity = Minecraft.getMinecraft().renderViewEntity; + int visibleDistance = 300; - if (red == 1 && green == 0 && blue == 0) { - TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_red.png"); - } else if (red == 0 && green == 1 && blue == 0) { - TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_green.png"); - } else if (red == 0 && green == 0 && blue == 1) { - TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy.png"); - } else if (red == 1 && green == 1 && blue == 0) { - TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_yellow.png"); - } else if (red == 1 && green == 0.5 && blue == 0) { - TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_orange.png"); - } else if (red == 0.5 && green == 0 && blue == 0.5) { - TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_violet.png"); - } - - /** - * Sets the particle age based on distance. - */ - EntityLivingBase renderentity = Minecraft.getMinecraft().renderViewEntity; + if (!Minecraft.getMinecraft().gameSettings.fancyGraphics) + { + visibleDistance = 100; + } - int visibleDistance = 300; + if (renderentity.getDistance(this.posX, this.posY, this.posZ) > visibleDistance) + { + this.particleMaxAge = 0; + } + } - if (!Minecraft.getMinecraft().gameSettings.fancyGraphics) - { - visibleDistance = 100; - } - if (renderentity.getDistance(this.posX, this.posY, this.posZ) > visibleDistance) - { - this.particleMaxAge = 0; - } - } - - public FXBeam(World par1World, Vector3 position, Vector3 target, float red, float green, float blue, int age, int energy) - { - super(par1World, position.x, position.y, position.z, 0.0D, 0.0D, 0.0D); + public FXBeam(World par1World, Vector3 position, Vector3 target, float red, float green, float blue, int age, int energy) + { + super(par1World, position.x, position.y, position.z, 0.0D, 0.0D, 0.0D); + this.setRGB(red, green, blue); + this.setSize(0.02F, 0.02F); + this.noClip = true; + this.motionX = 0.0D; + this.motionY = 0.0D; + this.motionZ = 0.0D; + this.target = target; + float xd = (float)(this.posX - this.target.x); + float yd = (float)(this.posY - this.target.y); + float zd = (float)(this.posZ - this.target.z); + this.length = (float) new Vector3(this).distanceTo(this.target); + double var7 = MathHelper.sqrt_double(xd * xd + zd * zd); + this.rotYaw = ((float)(Math.atan2(xd, zd) * 180.0D / Math.PI)); + this.rotPitch = ((float)(Math.atan2(yd, var7) * 180.0D / Math.PI)); + this.prevYaw = this.rotYaw; + this.prevPitch = this.rotPitch; + this.particleMaxAge = age; + this.energy = energy; - this.setRGB(red, green, blue); + if (red == 1 && green == 0 && blue == 0) + { + TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_red.png"); + } + else if (red == 0 && green == 1 && blue == 0) + { + TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_green.png"); + } + else if (red == 0 && green == 0 && blue == 1) + { + TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy.png"); + } + else if (red == 1 && green == 1 && blue == 0) + { + TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_yellow.png"); + } + else if (red == 1 && green == 0.5 && blue == 0) + { + TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_orange.png"); + } + else if (red == 0.5 && green == 0 && blue == 0.5) + { + TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_violet.png"); + } - this.setSize(0.02F, 0.02F); - this.noClip = true; - this.motionX = 0.0D; - this.motionY = 0.0D; - this.motionZ = 0.0D; - this.target = target; - float xd = (float) (this.posX - this.target.x); - float yd = (float) (this.posY - this.target.y); - float zd = (float) (this.posZ - this.target.z); - this.length = (float) new Vector3(this).distanceTo(this.target); - double var7 = MathHelper.sqrt_double(xd * xd + zd * zd); - this.rotYaw = ((float) (Math.atan2(xd, zd) * 180.0D / 3.141592653589793D)); - this.rotPitch = ((float) (Math.atan2(yd, var7) * 180.0D / 3.141592653589793D)); - this.prevYaw = this.rotYaw; - this.prevPitch = this.rotPitch; + /** + * Sets the particle age based on distance. + */ + EntityLivingBase renderentity = Minecraft.getMinecraft().renderViewEntity; + int visibleDistance = 300; - this.particleMaxAge = age; - this.energy = energy; + if (!Minecraft.getMinecraft().gameSettings.fancyGraphics) + { + visibleDistance = 100; + } - if (red == 1 && green == 0 && blue == 0) { - TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_red.png"); - } else if (red == 0 && green == 1 && blue == 0) { - TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_green.png"); - } else if (red == 0 && green == 0 && blue == 1) { - TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy.png"); - } else if (red == 1 && green == 1 && blue == 0) { - TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_yellow.png"); - } else if (red == 1 && green == 0.5 && blue == 0) { - TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_orange.png"); - } else if (red == 0.5 && green == 0 && blue == 0.5) { - TEXTURE = new ResourceLocation("warpdrive", "textures/blocks/energy_violet.png"); - } - - /** - * Sets the particle age based on distance. - */ - EntityLivingBase renderentity = Minecraft.getMinecraft().renderViewEntity; + if (renderentity.getDistance(this.posX, this.posY, this.posZ) > visibleDistance) + { + this.particleMaxAge = 0; + } - int visibleDistance = 300; + //this.pulse = (energy == 0); + //if (TEXTURE != null) { + // System.out.println("BeamFX created. Texture: " + TEXTURE); + //} + } - if (!Minecraft.getMinecraft().gameSettings.fancyGraphics) - { - visibleDistance = 100; - } - if (renderentity.getDistance(this.posX, this.posY, this.posZ) > visibleDistance) - { - this.particleMaxAge = 0; - } - - //this.pulse = (energy == 0); - - //if (TEXTURE != null) { - // System.out.println("BeamFX created. Texture: " + TEXTURE); - //} - } + @Override + public void onUpdate() + { + this.prevPosX = this.posX; + this.prevPosY = this.posY; + this.prevPosZ = this.posZ; + this.prevYaw = this.rotYaw; + this.prevPitch = this.rotPitch; - @Override - public void onUpdate() - { - this.prevPosX = this.posX; - this.prevPosY = this.posY; - this.prevPosZ = this.posZ; + if (!a) + { + float xd = (float)(this.posX - this.target.x); + float yd = (float)(this.posY - this.target.y); + float zd = (float)(this.posZ - this.target.z); + this.length = MathHelper.sqrt_float(xd * xd + yd * yd + zd * zd); + double var7 = MathHelper.sqrt_double(xd * xd + zd * zd); + this.rotYaw = ((float)(Math.atan2(xd, zd) * 180.0D / Math.PI)); + this.rotPitch = ((float)(Math.atan2(yd, var7) * 180.0D / Math.PI)); + } - this.prevYaw = this.rotYaw; - this.prevPitch = this.rotPitch; + if (this.particleAge++ >= this.particleMaxAge) + { + setDead(); + } + } - if (!a) { - float xd = (float) (this.posX - this.target.x); - float yd = (float) (this.posY - this.target.y); - float zd = (float) (this.posZ - this.target.z); + public void setRGB(float r, float g, float b) + { + this.particleRed = r; + this.particleGreen = g; + this.particleBlue = b; + } - this.length = MathHelper.sqrt_float(xd * xd + yd * yd + zd * zd); + @Override + public void renderParticle(Tessellator tessellator, float f, float f1, float f2, float f3, float f4, float f5) + { + tessellator.draw(); + GL11.glPushMatrix(); + float var9 = 1.0F; + float slide = this.worldObj.getTotalWorldTime(); + float rot = this.worldObj.provider.getWorldTime() % (360 / this.rotationSpeed) * this.rotationSpeed + this.rotationSpeed * f; + float size = 1.0F; - double var7 = MathHelper.sqrt_double(xd * xd + zd * zd); + if (this.pulse) + { + size = Math.min(this.particleAge / 4.0F, 1.0F); + size = this.prevSize + (size - this.prevSize) * f; + } + else + { + size = Math.min(Math.max(energy / 50000F, 1.0F), 7F); + } - this.rotYaw = ((float) (Math.atan2(xd, zd) * 180.0D / 3.141592653589793D)); - this.rotPitch = ((float) (Math.atan2(yd, var7) * 180.0D / 3.141592653589793D)); - } - - if (this.particleAge++ >= this.particleMaxAge) - { - setDead(); - } - } + float op = 0.5F; - public void setRGB(float r, float g, float b) - { - this.particleRed = r; - this.particleGreen = g; - this.particleBlue = b; - } + if ((this.pulse) && (this.particleMaxAge - this.particleAge <= 4)) + { + op = 0.5F - (4 - (this.particleMaxAge - this.particleAge)) * 0.1F; + } - @Override - public void renderParticle(Tessellator tessellator, float f, float f1, float f2, float f3, float f4, float f5) - { - tessellator.draw(); + FMLClientHandler.instance().getClient().renderEngine.bindTexture(TEXTURE); + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, 10497.0F); + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, 10497.0F); + GL11.glDisable(GL11.GL_CULL_FACE); + float var11 = slide + f; - GL11.glPushMatrix(); - float var9 = 1.0F; - float slide = this.worldObj.getTotalWorldTime(); - float rot = this.worldObj.provider.getWorldTime() % (360 / this.rotationSpeed) * this.rotationSpeed + this.rotationSpeed * f; + if (this.reverse) + { + var11 *= -1.0F; + } - float size = 1.0F; - if (this.pulse) - { - size = Math.min(this.particleAge / 4.0F, 1.0F); - size = this.prevSize + (size - this.prevSize) * f; - } else { - size = Math.min(Math.max(energy / 50000F, 1.0F), 7F); - } + float var12 = -var11 * 0.2F - MathHelper.floor_float(-var11 * 0.1F); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); + GL11.glDepthMask(false); + float xx = (float)(this.prevPosX + (this.posX - this.prevPosX) * f - interpPosX); + float yy = (float)(this.prevPosY + (this.posY - this.prevPosY) * f - interpPosY); + float zz = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * f - interpPosZ); + GL11.glTranslated(xx, yy, zz); + float ry = this.prevYaw + (this.rotYaw - this.prevYaw) * f; + float rp = this.prevPitch + (this.rotPitch - this.prevPitch) * f; + GL11.glRotatef(90.0F, 1.0F, 0.0F, 0.0F); + GL11.glRotatef(180.0F + ry, 0.0F, 0.0F, -1.0F); + GL11.glRotatef(rp, 1.0F, 0.0F, 0.0F); + double var44 = -0.15D * size; + double var17 = 0.15D * size; + double var44b = -0.15D * size * this.endModifier; + double var17b = 0.15D * size * this.endModifier; + GL11.glRotatef(rot, 0.0F, 1.0F, 0.0F); - float op = 0.5F; - if ((this.pulse) && (this.particleMaxAge - this.particleAge <= 4)) - { - op = 0.5F - (4 - (this.particleMaxAge - this.particleAge)) * 0.1F; - } + for (int t = 0; t < 3; t++) + { + double var29 = this.length * size * var9; + double var31 = 0.0D; + double var33 = 1.0D; + double var35 = -1.0F + var12 + t / 3.0F; + double var37 = this.length * size * var9 + var35; + GL11.glRotatef(60.0F, 0.0F, 1.0F, 0.0F); + tessellator.startDrawingQuads(); + tessellator.setBrightness(200); + tessellator.setColorRGBA_F(this.particleRed, this.particleGreen, this.particleBlue, op); + tessellator.addVertexWithUV(var44b, var29, 0.0D, var33, var37); + tessellator.addVertexWithUV(var44, 0.0D, 0.0D, var33, var35); + tessellator.addVertexWithUV(var17, 0.0D, 0.0D, var31, var35); + tessellator.addVertexWithUV(var17b, var29, 0.0D, var31, var37); + tessellator.draw(); + } - FMLClientHandler.instance().getClient().renderEngine.func_110577_a(TEXTURE); - - GL11.glTexParameterf(3553, 10242, 10497.0F); - GL11.glTexParameterf(3553, 10243, 10497.0F); - - GL11.glDisable(2884); - - float var11 = slide + f; - if (this.reverse) - var11 *= -1.0F; - float var12 = -var11 * 0.2F - MathHelper.floor_float(-var11 * 0.1F); - - GL11.glEnable(3042); - GL11.glBlendFunc(770, 1); - GL11.glDepthMask(false); - - float xx = (float) (this.prevPosX + (this.posX - this.prevPosX) * f - interpPosX); - float yy = (float) (this.prevPosY + (this.posY - this.prevPosY) * f - interpPosY); - float zz = (float) (this.prevPosZ + (this.posZ - this.prevPosZ) * f - interpPosZ); - GL11.glTranslated(xx, yy, zz); - - float ry = this.prevYaw + (this.rotYaw - this.prevYaw) * f; - float rp = this.prevPitch + (this.rotPitch - this.prevPitch) * f; - GL11.glRotatef(90.0F, 1.0F, 0.0F, 0.0F); - GL11.glRotatef(180.0F + ry, 0.0F, 0.0F, -1.0F); - GL11.glRotatef(rp, 1.0F, 0.0F, 0.0F); - - double var44 = -0.15D * size; - double var17 = 0.15D * size; - double var44b = -0.15D * size * this.endModifier; - double var17b = 0.15D * size * this.endModifier; - - GL11.glRotatef(rot, 0.0F, 1.0F, 0.0F); - for (int t = 0; t < 3; t++) - { - double var29 = this.length * size * var9; - double var31 = 0.0D; - double var33 = 1.0D; - double var35 = -1.0F + var12 + t / 3.0F; - double var37 = this.length * size * var9 + var35; - - GL11.glRotatef(60.0F, 0.0F, 1.0F, 0.0F); - tessellator.startDrawingQuads(); - tessellator.setBrightness(200); - tessellator.setColorRGBA_F(this.particleRed, this.particleGreen, this.particleBlue, op); - tessellator.addVertexWithUV(var44b, var29, 0.0D, var33, var37); - tessellator.addVertexWithUV(var44, 0.0D, 0.0D, var33, var35); - tessellator.addVertexWithUV(var17, 0.0D, 0.0D, var31, var35); - tessellator.addVertexWithUV(var17b, var29, 0.0D, var31, var37); - tessellator.draw(); - } - - GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); - GL11.glDepthMask(true); - GL11.glDisable(3042); - GL11.glEnable(2884); - - GL11.glPopMatrix(); - - tessellator.startDrawingQuads(); - this.prevSize = size; - - FMLClientHandler.instance().getClient().renderEngine.func_110577_a(new ResourceLocation("textures/particle/particles.png")); - } + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + GL11.glDepthMask(true); + GL11.glDisable(GL11.GL_BLEND); + GL11.glEnable(GL11.GL_CULL_FACE); + GL11.glPopMatrix(); + tessellator.startDrawingQuads(); + this.prevSize = size; + FMLClientHandler.instance().getClient().renderEngine.bindTexture(new ResourceLocation("textures/particle/particles.png")); + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/GenerateCommand.java b/src/cr0s/WarpDrive/GenerateCommand.java index 9cd5de31..dd7cddc1 100644 --- a/src/cr0s/WarpDrive/GenerateCommand.java +++ b/src/cr0s/WarpDrive/GenerateCommand.java @@ -11,67 +11,88 @@ import net.minecraft.util.MathHelper; * moon, ship, asteroid, astfield, gascloud, star */ -public class GenerateCommand extends CommandBase { - +public class GenerateCommand extends CommandBase +{ @Override - public String getCommandName() { + public String getCommandName() + { return "generate"; } @Override - public int getRequiredPermissionLevel() { + public int getRequiredPermissionLevel() + { return 2; } - + @Override - public String getCommandUsage(ICommandSender par1ICommandSender) { + public String getCommandUsage(ICommandSender par1ICommandSender) + { return "/" + getCommandName() + " <structure>\nPossible structures: moon, ship, asteroid, astfield, gascloud, star, jumpgate <name>"; } - + @Override - public void processCommand(ICommandSender icommandsender, String[] params) { + public void processCommand(ICommandSender icommandsender, String[] params) + { EntityPlayerMP player = (EntityPlayerMP)icommandsender; - String struct = params[0]; - + // Reject command, if player is not in space - if (player.dimension != WarpDrive.instance.spaceDimID && (!"ship".equals(struct))) { + if (player.dimension != WarpDrive.instance.spaceDimID && (!"ship".equals(struct))) + { player.addChatMessage("* generate: this structure generation allowed only in space!"); return; } - + int x = MathHelper.floor_double(player.posX); int y = MathHelper.floor_double(player.posY); int z = MathHelper.floor_double(player.posZ); - - if (struct.equals("moon")) { + + if (struct.equals("moon")) + { notifyAdmins(icommandsender, "/generate: generating moon at " + x + ", " + (y - 16) + ", " + z, new Object[0]); WarpDrive.instance.spaceWorldGenerator.generateMoon(player.worldObj, x, y - 16, z); - } else if (struct.equals("ship")) { + } + else if (struct.equals("ship")) + { notifyAdmins(icommandsender, "/generate: generating NPC ship at " + x + ", " + y + ", " + z, new Object[0]); new WorldGenSmallShip(false).generate(player.worldObj, player.worldObj.rand, x, y, z); - } else if (struct.equals("asteroid")) { + } + else if (struct.equals("asteroid")) + { notifyAdmins(icommandsender, "/generate: generating asteroid at " + x + ", " + (y - 10) + ", " + z, new Object[0]); - WarpDrive.instance.spaceWorldGenerator.generateAsteroid(player.worldObj, x, y - 10, z, 6, 11); - } else if (struct.equals("astfield")) { + WarpDrive.instance.spaceWorldGenerator.generateAsteroid(player.worldObj, x, y - 10, z, 6, 11); + } + else if (struct.equals("astfield")) + { notifyAdmins(icommandsender, "/generate: generating asteroid field at " + x + ", " + y + ", " + z, new Object[0]); - WarpDrive.instance.spaceWorldGenerator.generateAsteroidField(player.worldObj, x, y, z); - } else if (struct.equals("gascloud")) { + WarpDrive.instance.spaceWorldGenerator.generateAsteroidField(player.worldObj, x, y, z); + } + else if (struct.equals("gascloud")) + { notifyAdmins(icommandsender, "/generate: generating gas cloud at " + x + ", " + y + ", " + z, new Object[0]); WarpDrive.instance.spaceWorldGenerator.generateGasCloudOfColor(player.worldObj, x, y, z, 15, 20, player.worldObj.rand.nextInt(12)); - } else if (struct.equals("star")) { + } + else if (struct.equals("star")) + { notifyAdmins(icommandsender, "/generate: generating star at " + x + ", " + y + ", " + z, new Object[0]); - WarpDrive.instance.spaceWorldGenerator.generateStar(player.worldObj, x, y, z); - } else if (struct.equals("jumpgate")) { - if (params.length == 2) { + WarpDrive.instance.spaceWorldGenerator.generateStar(player.worldObj, x, y, z); + } + else if (struct.equals("jumpgate")) + { + if (params.length == 2) + { notifyAdmins(icommandsender, "/generate: creating jumpgate at " + x + ", " + y + ", " + z, new Object[0]); - if (WarpDrive.instance.jumpGates.addGate(params[1], x, y, z)){ + + if (WarpDrive.instance.jumpGates.addGate(params[1], x, y, z)) + { JumpGateGenerator.generate(player.worldObj, x, y, z); - } else { + } + else + { notifyAdmins(icommandsender, "/generate: jumpgate '" + params[1] + "' already exists.", new Object[0]); } } } } - } diff --git a/src/cr0s/WarpDrive/GravityManager.java b/src/cr0s/WarpDrive/GravityManager.java index 7414c0c2..ffae6b2d 100644 --- a/src/cr0s/WarpDrive/GravityManager.java +++ b/src/cr0s/WarpDrive/GravityManager.java @@ -7,47 +7,61 @@ import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.MathHelper; -public class GravityManager { - private static double SPACE_GRAVITY = 0.0001D; - private static double SPACE_GRAVITY_SNEAK = 0.01D; - +public class GravityManager +{ + private static double SPACE_GRAVITY = 0.0001D; + private static double SPACE_GRAVITY_SNEAK = 0.01D; + private static final int JETPACK_ID = 30210; private static final int ELECTRIC_JETPACK_ID = 30209; - - public static double getGravityForEntity(EntityLivingBase entity) { - // Is entity in space or hyper-space? - boolean inSpace = entity.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID || entity.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID; - if (inSpace) { - boolean insideGravField = isEntityInGraviField(entity); - - if (insideGravField) { - return 0.08D; - } else { - if (entity instanceof EntityPlayer) { - EntityPlayer player = (EntityPlayer)entity; - - if (player.isSneaking()) { - if (player.getCurrentArmor(2) != null && ((player.getCurrentArmor(2).itemID == JETPACK_ID) || player.getCurrentArmor(2).itemID == ELECTRIC_JETPACK_ID)) { - return SPACE_GRAVITY_SNEAK; - } - } - } - return SPACE_GRAVITY; - } - } - - return 0.08D; - } - + + public static double getGravityForEntity(EntityLivingBase entity) + { + // Is entity in space or hyper-space? + boolean inSpace = entity.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID || entity.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID; + + if (inSpace) + { + boolean insideGravField = isEntityInGraviField(entity); + + if (insideGravField) + { + return 0.08D; + } + else + { + if (entity instanceof EntityPlayer) + { + EntityPlayer player = (EntityPlayer)entity; + + if (player.isSneaking()) + { + if (player.getCurrentArmor(2) != null && ((player.getCurrentArmor(2).itemID == JETPACK_ID) || player.getCurrentArmor(2).itemID == ELECTRIC_JETPACK_ID)) + { + return SPACE_GRAVITY_SNEAK; + } + } + } + + return SPACE_GRAVITY; + } + } + + return 0.08D; + } + public static double getItemGravity(EntityItem entity) { if (entity.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID || entity.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) { - if (isEntityInGraviField(entity)) { - return 0.03999999910593033D; - } else { - return SPACE_GRAVITY; - } + if (isEntityInGraviField(entity)) + { + return 0.03999999910593033D; + } + else + { + return SPACE_GRAVITY; + } } else { @@ -59,32 +73,37 @@ public class GravityManager { { if (entity.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID || entity.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) { - if (isEntityInGraviField(entity)) { - return 0.9800000190734863D; - } else { - return SPACE_GRAVITY; - } + if (isEntityInGraviField(entity)) + { + return 0.9800000190734863D; + } + else + { + return SPACE_GRAVITY; + } } else { return 0.9800000190734863D; } } - - public static boolean isEntityInGraviField(Entity e) { - int y = MathHelper.floor_double(e.posY); - int x = MathHelper.floor_double(e.posX); - int z = MathHelper.floor_double(e.posZ); - + + public static boolean isEntityInGraviField(Entity e) + { + int y = MathHelper.floor_double(e.posY); + int x = MathHelper.floor_double(e.posX); + int z = MathHelper.floor_double(e.posZ); final int CHECK_DISTANCE = 20; - + // Search non-air blocks under player - for (int ny = y; ny > (y - CHECK_DISTANCE); ny--) { - if (!e.worldObj.isAirBlock(x, ny, z)) { + for (int ny = y; ny > (y - CHECK_DISTANCE); ny--) + { + if (!e.worldObj.isAirBlock(x, ny, z)) + { return true; } } - + return false; } } diff --git a/src/cr0s/WarpDrive/HyperSpaceGenerator.java b/src/cr0s/WarpDrive/HyperSpaceGenerator.java index 725a5d1a..c1f75fcb 100644 --- a/src/cr0s/WarpDrive/HyperSpaceGenerator.java +++ b/src/cr0s/WarpDrive/HyperSpaceGenerator.java @@ -11,8 +11,8 @@ import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.gen.ChunkProviderGenerate; -public class HyperSpaceGenerator extends ChunkProviderGenerate implements IChunkProvider { - +public class HyperSpaceGenerator extends ChunkProviderGenerate implements IChunkProvider +{ private Random rand; private BiomeGenBase[] biomesForGeneration = new BiomeGenBase[1]; @@ -21,54 +21,53 @@ public class HyperSpaceGenerator extends ChunkProviderGenerate implements IChunk */ private World worldObj; - - public HyperSpaceGenerator(World par1World, long par2) { + public HyperSpaceGenerator(World par1World, long par2) + { super(par1World, par2, false); - rand = new Random(); this.worldObj = par1World; } @Override - public Chunk provideChunk(int par1, int par2) { + public Chunk provideChunk(int par1, int par2) + { this.rand.setSeed((long) par1 * 341873128712L + (long) par2 * 132897987541L); byte[] var3 = new byte[32768]; generateTerrain(par1, par2, var3); //this.caveGenerator.generate(this, this.worldObj, par1, par2, var3); this.biomesForGeneration[0] = WarpDrive.spaceBiome; - Chunk var4 = new Chunk(this.worldObj, var3, par1, par2); - var4.generateSkylightMap(); return var4; } @Override - public Chunk loadChunk(int var1, int var2) { + public Chunk loadChunk(int var1, int var2) + { // TODO Auto-generated method stub return this.provideChunk(var1, var2); } @Override - public void populate(IChunkProvider var1, int var2, int var3) { + public void populate(IChunkProvider var1, int var2, int var3) + { //super.populate(var1, var2, var3); - // Generate chunk population - // GameRegistry.generateWorld(var2, var3, worldObj, var1, var1); + // GameRegistry.generateWorld(var2, var3, worldObj, var1, var1); } @Override - public boolean saveChunks(boolean var1, IProgressUpdate var2) { + public boolean saveChunks(boolean var1, IProgressUpdate var2) + { return super.saveChunks(var1, var2); } @Override - public void generateTerrain(int par1, int par2, byte[] par3ArrayOfByte) { + public void generateTerrain(int par1, int par2, byte[] par3ArrayOfByte) + { this.biomesForGeneration[0] = WarpDrive.spaceBiome; - - // if (!"Space".equals(worldObj.provider.getDimensionName())) { - // } - + // if (!"Space".equals(worldObj.provider.getDimensionName())) { + // } /*byte var4 = 4; byte var5 = 16; byte var6 = 16; @@ -139,39 +138,45 @@ public class HyperSpaceGenerator extends ChunkProviderGenerate implements IChunk } @Override - public boolean canSave() { + public boolean canSave() + { // TODO Auto-generated method stub return super.canSave(); } @Override - public String makeString() { + public String makeString() + { // TODO Auto-generated method stub return super.makeString(); } @Override public List getPossibleCreatures(EnumCreatureType var1, int var2, int var3, - int var4) { + int var4) + { // TODO Auto-generated method stub return null; } @Override public ChunkPosition findClosestStructure(World var1, String var2, - int var3, int var4, int var5) { + int var3, int var4, int var5) + { // TODO Auto-generated method stub return null; } @Override - public int getLoadedChunkCount() { + public int getLoadedChunkCount() + { // TODO Auto-generated method stub return super.getLoadedChunkCount(); } @Override - public void recreateStructures(int var1, int var2) { + public void recreateStructures(int var1, int var2) + { // TODO Auto-generated method stub } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/HyperSpaceProvider.java b/src/cr0s/WarpDrive/HyperSpaceProvider.java index f239b26d..4d8e3fbf 100644 --- a/src/cr0s/WarpDrive/HyperSpaceProvider.java +++ b/src/cr0s/WarpDrive/HyperSpaceProvider.java @@ -2,8 +2,6 @@ package cr0s.WarpDrive; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.CloudRenderBlank; -import cr0s.WarpDrive.WarpDrive; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayerMP; @@ -15,25 +13,28 @@ import net.minecraft.world.biome.WorldChunkManagerHell; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.IChunkProvider; -public class HyperSpaceProvider extends WorldProvider { - +public class HyperSpaceProvider extends WorldProvider +{ public int exitXCoord; public int exitYCoord; public int exitZCoord; public int exitDimID; - - public HyperSpaceProvider() { + + public HyperSpaceProvider() + { this.worldChunkMgr = new WorldChunkManagerHell(WarpDrive.spaceBiome, 0.0F, 0.0F); this.hasNoSky = false; } @Override - public String getDimensionName() { + public String getDimensionName() + { return "Hyperspace"; } - + @Override - public boolean canRespawnHere() { + public boolean canRespawnHere() + { return true; } @@ -42,55 +43,56 @@ public class HyperSpaceProvider extends WorldProvider { public float getStarBrightness(float par1) { return 0F; - } - + } + @Override public boolean isSurfaceWorld() { return true; - } - + } + @Override public int getAverageGroundLevel() { return 1; } - - + @Override public double getHorizon() { return 1; } - + @Override - public boolean canSnowAt(int x, int y, int z) { + public boolean canSnowAt(int x, int y, int z) + { return false; } - + @Override public void updateWeather() { super.resetRainAndThunder(); - } + } @Override public BiomeGenBase getBiomeGenForCoords(int x, int z) { return WarpDrive.spaceBiome; - } - - @Override - public void setAllowedSpawnTypes(boolean allowHostile, boolean allowPeaceful) { - super.setAllowedSpawnTypes(false, false); - } @Override - public float calculateCelestialAngle(long par1, float par3) { + public void setAllowedSpawnTypes(boolean allowHostile, boolean allowPeaceful) + { + super.setAllowedSpawnTypes(false, false); + } + + @Override + public float calculateCelestialAngle(long par1, float par3) + { return 0.5F; } - + @Override protected void generateLightBrightnessTable() { @@ -100,23 +102,26 @@ public class HyperSpaceProvider extends WorldProvider { { float var3 = 1.0F - (float)var2 / 15.0F; this.lightBrightnessTable[var2] = (1.0F - var3) / (var3 * 3.0F + 1.0F) * (1.0F - var1) + var1; - } - } + } + } @SideOnly(Side.CLIENT) @Override - public String getSaveFolder() { + public String getSaveFolder() + { return (dimensionId == 0 ? null : "WarpDrive/HyperSpace" + dimensionId); } @Override - public boolean canCoordinateBeSpawn(int par1, int par2) { + public boolean canCoordinateBeSpawn(int par1, int par2) + { int var3 = this.worldObj.getFirstUncoveredBlock(par1, par2); return var3 != 0; } @Override - public Vec3 getSkyColor(Entity cameraEntity, float partialTicks) { + public Vec3 getSkyColor(Entity cameraEntity, float partialTicks) + { setCloudRenderer(new CloudRenderBlank()); setSkyRenderer(new CloudRenderBlank()); return this.worldObj.getWorldVec3Pool().getVecFromPool((double) 1, (double) 0, (double) 0); @@ -124,7 +129,8 @@ public class HyperSpaceProvider extends WorldProvider { @SideOnly(Side.CLIENT) @Override - public Vec3 getFogColor(float par1, float par2) { + public Vec3 getFogColor(float par1, float par2) + { return this.worldObj.getWorldVec3Pool().getVecFromPool((double) 0.1, (double) 0, (double) 0); } @@ -133,76 +139,76 @@ public class HyperSpaceProvider extends WorldProvider { public boolean isSkyColored() { return true; - } - + } + @Override public ChunkCoordinates getEntrancePortalLocation() { return null; - } - + } + @Override - public int getRespawnDimension(EntityPlayerMP player) { + public int getRespawnDimension(EntityPlayerMP player) + { return WarpDrive.instance.hyperSpaceDimID; } @Override - public IChunkProvider createChunkGenerator() { + public IChunkProvider createChunkGenerator() + { return new HyperSpaceGenerator(worldObj, 46); } @Override - public boolean canBlockFreeze(int x, int y, int z, boolean byWater) { + public boolean canBlockFreeze(int x, int y, int z, boolean byWater) + { return false; } @Override - public ChunkCoordinates getRandomizedSpawnPoint() { + public ChunkCoordinates getRandomizedSpawnPoint() + { ChunkCoordinates var5 = new ChunkCoordinates(this.worldObj.getSpawnPoint()); - //boolean isAdventure = worldObj.getWorldInfo().getGameType() == EnumGameType.ADVENTURE; int spawnFuzz = 100; int spawnFuzzHalf = spawnFuzz / 2; - { var5.posX += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf; var5.posZ += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf; var5.posY = 200; } - if (worldObj.isAirBlock(var5.posX, var5.posY, var5.posZ)) { + if (worldObj.isAirBlock(var5.posX, var5.posY, var5.posZ)) + { worldObj.setBlock(var5.posX, var5.posY, var5.posZ, Block.stone.blockID, 0, 2); - worldObj.setBlock(var5.posX + 1, var5.posY + 1, var5.posZ, Block.glass.blockID, 0, 2); worldObj.setBlock(var5.posX + 1, var5.posY + 2, var5.posZ, Block.glass.blockID, 0, 2); - worldObj.setBlock(var5.posX - 1, var5.posY + 1, var5.posZ, Block.glass.blockID, 0, 2); - worldObj.setBlock(var5.posX - 1, var5.posY + 2, var5.posZ, Block.glass.blockID, 0, 2); - + worldObj.setBlock(var5.posX - 1, var5.posY + 2, var5.posZ, Block.glass.blockID, 0, 2); worldObj.setBlock(var5.posX, var5.posY + 1, var5.posZ + 1, Block.glass.blockID, 0, 2); - worldObj.setBlock(var5.posX, var5.posY + 2, var5.posZ + 1, Block.glass.blockID, 0, 2); - + worldObj.setBlock(var5.posX, var5.posY + 2, var5.posZ + 1, Block.glass.blockID, 0, 2); worldObj.setBlock(var5.posX, var5.posY + 1, var5.posZ - 1, Block.glass.blockID, 0, 2); - worldObj.setBlock(var5.posX, var5.posY + 2, var5.posZ - 1, Block.glass.blockID, 0, 2); - + worldObj.setBlock(var5.posX, var5.posY + 2, var5.posZ - 1, Block.glass.blockID, 0, 2); worldObj.setBlock(var5.posX, var5.posY + 3, var5.posZ, Block.glass.blockID, 0, 2); - - worldObj.setBlock(var5.posX, var5.posY, var5.posZ, WarpDrive.instance.config.airID, 15, 2); - worldObj.setBlock(var5.posX, var5.posY + 1, var5.posZ, WarpDrive.instance.config.airID, 15, 2); + worldObj.setBlock(var5.posX, var5.posY, var5.posZ, WarpDrive.instance.config.airID, 15, 2); + worldObj.setBlock(var5.posX, var5.posY + 1, var5.posZ, WarpDrive.instance.config.airID, 15, 2); } + return var5; } - + @Override - public boolean getWorldHasVoidParticles() { + public boolean getWorldHasVoidParticles() + { return false; } - + @Override - public boolean isDaytime() { + public boolean isDaytime() + { return true; } - + @Override public boolean canDoLightning(Chunk chunk) { @@ -213,5 +219,5 @@ public class HyperSpaceProvider extends WorldProvider { public boolean canDoRainSnowIce(Chunk chunk) { return false; - } + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/HyperSpaceSkyRenderer.java b/src/cr0s/WarpDrive/HyperSpaceSkyRenderer.java index ab4fbe69..6af75694 100644 --- a/src/cr0s/WarpDrive/HyperSpaceSkyRenderer.java +++ b/src/cr0s/WarpDrive/HyperSpaceSkyRenderer.java @@ -12,11 +12,11 @@ import net.minecraftforge.client.IRenderHandler; * * @author user */ -public class HyperSpaceSkyRenderer extends IRenderHandler { - +public class HyperSpaceSkyRenderer extends IRenderHandler +{ @Override - public void render(float partialTicks, WorldClient world, Minecraft mc) { + public void render(float partialTicks, WorldClient world, Minecraft mc) + { throw new UnsupportedOperationException("Not supported yet."); } - } diff --git a/src/cr0s/WarpDrive/HyperSpaceWorldGenerator.java b/src/cr0s/WarpDrive/HyperSpaceWorldGenerator.java index f37e0111..46169fde 100644 --- a/src/cr0s/WarpDrive/HyperSpaceWorldGenerator.java +++ b/src/cr0s/WarpDrive/HyperSpaceWorldGenerator.java @@ -1,7 +1,6 @@ package cr0s.WarpDrive; import cpw.mods.fml.common.IWorldGenerator; -import cr0s.WarpDrive.WarpDrive; import java.util.Random; import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; @@ -9,9 +8,8 @@ import net.minecraft.world.chunk.IChunkProvider; /** * @author Cr0s */ -public class HyperSpaceWorldGenerator implements IWorldGenerator { - - +public class HyperSpaceWorldGenerator implements IWorldGenerator +{ /** * Generator for chunk * @param random @@ -19,11 +17,13 @@ public class HyperSpaceWorldGenerator implements IWorldGenerator { * @param chunkZ * @param world * @param chunkGenerator - * @param chunkProvider + * @param chunkProvider */ @Override - public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { - if (world.provider.dimensionId != WarpDrive.instance.hyperSpaceDimID) { + public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) + { + if (world.provider.dimensionId != WarpDrive.instance.hyperSpaceDimID) + { // ... } } diff --git a/src/cr0s/WarpDrive/InvisibleCommand.java b/src/cr0s/WarpDrive/InvisibleCommand.java index 5e52caea..8ad020aa 100644 --- a/src/cr0s/WarpDrive/InvisibleCommand.java +++ b/src/cr0s/WarpDrive/InvisibleCommand.java @@ -7,40 +7,45 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.util.MathHelper; import net.minecraft.world.WorldServer; - -public class InvisibleCommand extends CommandBase { - +public class InvisibleCommand extends CommandBase +{ @Override - public int getRequiredPermissionLevel() { + public int getRequiredPermissionLevel() + { return 4; } - + @Override - public String getCommandName() { + public String getCommandName() + { return "invisible"; } @Override - public void processCommand(ICommandSender icommandsender, String[] astring) { + public void processCommand(ICommandSender icommandsender, String[] astring) + { EntityPlayerMP player = (EntityPlayerMP)icommandsender; MinecraftServer server = MinecraftServer.getServer(); int targetDim = WarpDrive.instance.spaceDimID; - if (astring.length >= 1) { - notifyAdmins(icommandsender, "/invisible: setting invisible to " + astring[0], new Object[0]); - player = MinecraftServer.getServer().getConfigurationManager().getPlayerForUsername(astring[0]); + + if (astring.length >= 1) + { + notifyAdmins(icommandsender, "/invisible: setting invisible to " + astring[0], new Object[0]); + player = MinecraftServer.getServer().getConfigurationManager().getPlayerForUsername(astring[0]); } - - if (player == null) { + + if (player == null) + { return; } - + // Toggle invisibility player.setInvisible(!player.isInvisible()); } @Override - public String getCommandUsage(ICommandSender icommandsender) { + public String getCommandUsage(ICommandSender icommandsender) + { return "/invisible [player]"; } - } diff --git a/src/cr0s/WarpDrive/JumpGate.java b/src/cr0s/WarpDrive/JumpGate.java index 90dceed5..cbbc2c52 100644 --- a/src/cr0s/WarpDrive/JumpGate.java +++ b/src/cr0s/WarpDrive/JumpGate.java @@ -2,20 +2,24 @@ package cr0s.WarpDrive; import net.minecraft.util.AxisAlignedBB; -public class JumpGate { +public class JumpGate +{ public String name; public int xCoord, yCoord, zCoord; - public JumpGate(String name, int x, int y, int z) { + public JumpGate(String name, int x, int y, int z) + { this.name = name; this.xCoord = x; this.yCoord = y; this.zCoord = z; } - public JumpGate(String line) { + public JumpGate(String line) + { String[] params = line.split(":"); - if (params.length < 4) { + if (params.length < 4) + { return; } @@ -25,28 +29,27 @@ public class JumpGate { zCoord = Integer.parseInt(params[3]); } - public AxisAlignedBB getGateAABB() { + public AxisAlignedBB getGateAABB() + { int xmin, ymin, zmin; int xmax, ymax, zmax; - xmin = xCoord - (JumpGateGenerator.GATE_LENGTH_HALF * 2); xmax = xCoord + (JumpGateGenerator.GATE_LENGTH_HALF * 2); - ymin = yCoord - (JumpGateGenerator.GATE_SIZE_HALF); ymax = yCoord + (JumpGateGenerator.GATE_SIZE_HALF); - zmin = zCoord - (JumpGateGenerator.GATE_SIZE_HALF); zmax = zCoord + (JumpGateGenerator.GATE_SIZE_HALF); - return AxisAlignedBB.getBoundingBox(xmin, ymin, zmin, xmax, ymax, zmax); } - + @Override - public String toString() { + public String toString() + { return name + ":" + xCoord + ":" + yCoord + ":" + zCoord; } - - public String toNiceString() { - return name + " (" + xCoord + "; " +yCoord + "; " + zCoord + ")"; + + public String toNiceString() + { + return name + " (" + xCoord + "; " + yCoord + "; " + zCoord + ")"; } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/JumpGateGenerator.java b/src/cr0s/WarpDrive/JumpGateGenerator.java index 308d3bc8..d10cc614 100644 --- a/src/cr0s/WarpDrive/JumpGateGenerator.java +++ b/src/cr0s/WarpDrive/JumpGateGenerator.java @@ -3,41 +3,45 @@ package cr0s.WarpDrive; import net.minecraft.block.Block; import net.minecraft.world.World; -public class JumpGateGenerator { +public class JumpGateGenerator +{ public static final int GATE_SIZE = 52; public static final int GATE_LENGTH = 37; - + public static final int GATE_LENGTH_HALF = GATE_LENGTH / 2; public static final int GATE_SIZE_HALF = GATE_SIZE / 2; - - - public static void generate (World worldObj, int x, int y, int z) { - for (int length = -GATE_LENGTH_HALF; length < GATE_LENGTH_HALF; length++) { - for (int newZ = z - GATE_SIZE_HALF; newZ <= z + GATE_SIZE_HALF; newZ++) { + + public static void generate(World worldObj, int x, int y, int z) + { + for (int length = -GATE_LENGTH_HALF; length < GATE_LENGTH_HALF; length++) + { + for (int newZ = z - GATE_SIZE_HALF; newZ <= z + GATE_SIZE_HALF; newZ++) + { worldObj.setBlock(x + (2 * length), y + GATE_SIZE_HALF, newZ, Block.bedrock.blockID); worldObj.setBlock(x + (2 * length), y - GATE_SIZE_HALF, newZ, Block.bedrock.blockID); } - - for (int newY = y - GATE_SIZE_HALF; newY <= y + GATE_SIZE_HALF; newY++) { + + for (int newY = y - GATE_SIZE_HALF; newY <= y + GATE_SIZE_HALF; newY++) + { worldObj.setBlock(x + (2 * length), newY, z + GATE_SIZE_HALF, Block.bedrock.blockID); worldObj.setBlock(x + (2 * length), newY, z - GATE_SIZE_HALF, Block.bedrock.blockID); - } + } } - - for (int length = -GATE_LENGTH; length < GATE_LENGTH; length++) { + + for (int length = -GATE_LENGTH; length < GATE_LENGTH; length++) + { worldObj.setBlock(x + length, y + GATE_SIZE_HALF, z, Block.bedrock.blockID); worldObj.setBlock(x + length, y - GATE_SIZE_HALF, z, Block.bedrock.blockID); worldObj.setBlock(x + length, y + GATE_SIZE_HALF, z + 1, Block.bedrock.blockID); worldObj.setBlock(x + length, y - GATE_SIZE_HALF, z - 1, Block.bedrock.blockID); worldObj.setBlock(x + length, y + GATE_SIZE_HALF, z + 2, Block.bedrock.blockID); - worldObj.setBlock(x + length, y - GATE_SIZE_HALF, z - 2, Block.bedrock.blockID); - + worldObj.setBlock(x + length, y - GATE_SIZE_HALF, z - 2, Block.bedrock.blockID); worldObj.setBlock(x + length, y, z - GATE_SIZE_HALF, Block.bedrock.blockID); worldObj.setBlock(x + length, y, z + GATE_SIZE_HALF, Block.bedrock.blockID); worldObj.setBlock(x + length, y + 1, z - GATE_SIZE_HALF, Block.bedrock.blockID); worldObj.setBlock(x + length, y - 1, z + GATE_SIZE_HALF, Block.bedrock.blockID); worldObj.setBlock(x + length, y + 2, z - GATE_SIZE_HALF, Block.bedrock.blockID); - worldObj.setBlock(x + length, y - 2, z + GATE_SIZE_HALF, Block.bedrock.blockID); + worldObj.setBlock(x + length, y - 2, z + GATE_SIZE_HALF, Block.bedrock.blockID); } } } diff --git a/src/cr0s/WarpDrive/JumpGatesRegistry.java b/src/cr0s/WarpDrive/JumpGatesRegistry.java index b1e5bebf..bec8d6ae 100644 --- a/src/cr0s/WarpDrive/JumpGatesRegistry.java +++ b/src/cr0s/WarpDrive/JumpGatesRegistry.java @@ -12,127 +12,154 @@ import java.util.logging.Logger; import net.minecraft.server.MinecraftServer; import net.minecraft.util.MathHelper; -public final class JumpGatesRegistry { +public final class JumpGatesRegistry +{ private File db; private ArrayList<JumpGate> gates = new ArrayList<JumpGate>(); - + //@SideOnly(Side.CLIENT) - public JumpGatesRegistry() { + public JumpGatesRegistry() + { db = MinecraftServer.getServer().getFile("gates.txt"); - try { + + try + { loadGates(); - } catch (IOException ex) { + } + catch (IOException ex) + { Logger.getLogger(JumpGatesRegistry.class.getName()).log(Level.SEVERE, null, ex); } } - - public void saveGates() throws IOException { - PrintWriter out = new PrintWriter(new FileWriter(db)); - // Write each string in the array on a separate line - for (JumpGate jg : gates) { - out.println(jg); - } + public void saveGates() throws IOException + { + PrintWriter out = new PrintWriter(new FileWriter(db)); - out.close(); + // Write each string in the array on a separate line + for (JumpGate jg : gates) + { + out.println(jg); + } + + out.close(); } - - public void loadGates() throws IOException { + + public void loadGates() throws IOException + { System.out.println("[JUMP GATES] Loading jump gates from gates.txt..."); - BufferedReader bufferedreader; bufferedreader = new BufferedReader(new FileReader(db)); - String s1; - while ((s1 = bufferedreader.readLine()) != null) { + + while ((s1 = bufferedreader.readLine()) != null) + { gates.add(new JumpGate(s1)); - } - + } + bufferedreader.close(); - System.out.println("[JUMP GATES] Loaded " + gates.size() + " jump gates."); } - - public void addGate(JumpGate jg) { + + public void addGate(JumpGate jg) + { gates.add(jg); } - - public boolean addGate(String name, int x, int y, int z) { + + public boolean addGate(String name, int x, int y, int z) + { // Gate already exists - if (findGateByName(name) != null) { + if (findGateByName(name) != null) + { return false; } - + addGate(new JumpGate(name, x, y, z)); - - try { + + try + { saveGates(); - } catch (IOException ex) { + } + catch (IOException ex) + { Logger.getLogger(JumpGatesRegistry.class.getName()).log(Level.SEVERE, null, ex); } - + return true; } - - public void removeGate(String name) { + + public void removeGate(String name) + { JumpGate jg; - - for (int i = 0; i < gates.size(); i++) { + + for (int i = 0; i < gates.size(); i++) + { jg = gates.get(i); - if (jg.name.equalsIgnoreCase(name)) { + + if (jg.name.equalsIgnoreCase(name)) + { gates.remove(i); return; } } - - try { + + try + { saveGates(); - } catch (IOException ex) { + } + catch (IOException ex) + { Logger.getLogger(JumpGatesRegistry.class.getName()).log(Level.SEVERE, null, ex); - } + } } - - public JumpGate findGateByName(String name) { - for (JumpGate jg : gates) { - if (jg.name.equalsIgnoreCase(name)) { + + public JumpGate findGateByName(String name) + { + for (JumpGate jg : gates) + { + if (jg.name.equalsIgnoreCase(name)) + { return jg; } } - + return null; } - - public String jumpGatesList() { + + public String jumpGatesList() + { String result = ""; - - for (JumpGate jg : gates) { + + for (JumpGate jg : gates) + { result += jg.toNiceString() + "\n"; } - + return result; } - - public JumpGate findNearestGate(int x, int y, int z) { + + public JumpGate findNearestGate(int x, int y, int z) + { System.out.println(jumpGatesList()); - double minDistance = -1; - JumpGate res = null; - for (JumpGate jg : gates) { + + for (JumpGate jg : gates) + { double d3 = jg.xCoord - x; double d4 = jg.yCoord - y; double d5 = jg.zCoord - z; - double distance = MathHelper.sqrt_double(d3 * d3 + d4 * d4 + d5 * d5); System.out.println("Checking gate: " + jg.name + ", distance: " + distance); - - if (minDistance == -1 || distance < minDistance) { + + if (minDistance == -1 || distance < minDistance) + { System.out.println("Setting " + jg.name + " as nearest"); minDistance = distance; res = jg; } } - + return res; } } diff --git a/src/cr0s/WarpDrive/LocalProfiler.java b/src/cr0s/WarpDrive/LocalProfiler.java index ec4fe760..e0e1ba87 100644 --- a/src/cr0s/WarpDrive/LocalProfiler.java +++ b/src/cr0s/WarpDrive/LocalProfiler.java @@ -2,8 +2,10 @@ package cr0s.WarpDrive; import java.util.Stack; -public class LocalProfiler { - private static class StackElement { +public class LocalProfiler +{ + private static class StackElement + { public long start; public long internal; public String name; @@ -11,7 +13,8 @@ public class LocalProfiler { private static Stack<StackElement> stack = new Stack<StackElement>(); - public static void start(String name) { + public static void start(String name) + { StackElement e = new StackElement(); e.start = System.nanoTime(); e.internal = 0; @@ -19,21 +22,25 @@ public class LocalProfiler { stack.push(e); } - public static void stop() { - if (stack.isEmpty()) return; + public static void stop() + { + if (stack.isEmpty()) + { + return; + } StackElement e = stack.pop(); long end = System.nanoTime(); long dt = end - e.start; - if (!stack.isEmpty()) { + if (!stack.isEmpty()) + { StackElement e2 = stack.peek(); e2.internal += dt; } long self = (dt - e.internal) / 1000; // in microseconds long total = dt / 1000; - - System.out.println("[PROF] {" + e.name + "} self: " + (self/1000F) + "ms, total: " + (total/1000F) + "ms"); + System.out.println("[PROF] {" + e.name + "} self: " + (self / 1000F) + "ms, total: " + (total / 1000F) + "ms"); } } diff --git a/src/cr0s/WarpDrive/MovingEntity.java b/src/cr0s/WarpDrive/MovingEntity.java index 4824d31d..f3948305 100644 --- a/src/cr0s/WarpDrive/MovingEntity.java +++ b/src/cr0s/WarpDrive/MovingEntity.java @@ -10,16 +10,17 @@ import net.minecraft.entity.Entity; * Класс объекта движущегося в корабле энтити * @author user */ -public class MovingEntity { +public class MovingEntity +{ public double oldX; public double oldY; public double oldZ; - + public Entity entity; - - public MovingEntity(Entity e) { + + public MovingEntity(Entity e) + { entity = e; - oldX = e.posX; oldY = e.posY; oldZ = e.posZ; diff --git a/src/cr0s/WarpDrive/PacketHandler.java b/src/cr0s/WarpDrive/PacketHandler.java index 1cb7fb1c..d76842d7 100644 --- a/src/cr0s/WarpDrive/PacketHandler.java +++ b/src/cr0s/WarpDrive/PacketHandler.java @@ -14,140 +14,154 @@ import net.minecraftforge.common.DimensionManager; import cpw.mods.fml.common.network.IPacketHandler; import cpw.mods.fml.common.network.Player; -public class PacketHandler implements IPacketHandler { +public class PacketHandler implements IPacketHandler +{ + @Override + public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) + { + if (packet.channel.equals("WarpDriveBeam")) + { + handleBeam(packet, (EntityPlayer)player); + } + else if (packet.channel.equals("WarpDriveFreq")) + { + handleFreqUpdate(packet, (EntityPlayer)player); + } + else if (packet.channel.equals("WarpDriveLaserT")) + { + handleLaserTargeting(packet, (EntityPlayer)player); + } + } - @Override - public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) { - if (packet.channel.equals("WarpDriveBeam")) { - handleBeam(packet, (EntityPlayer)player); - } else if (packet.channel.equals("WarpDriveFreq")) { - handleFreqUpdate(packet, (EntityPlayer)player); - } else if (packet.channel.equals("WarpDriveLaserT")) { - handleLaserTargeting(packet, (EntityPlayer)player); + public void handleLaserTargeting(Packet250CustomPayload packet, EntityPlayer player) + { + DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); + + try + { + int x = inputStream.readInt(); + int y = inputStream.readInt(); + int z = inputStream.readInt(); + float yaw = inputStream.readFloat(); + float pitch = inputStream.readFloat(); + System.out.println("Got target packet: (" + x + "; " + y + "; " + z + ") | yaw: " + yaw + " | pitch: " + pitch); + TileEntity te = player.worldObj.getBlockTileEntity(x, y, z); + + if (te != null) + { + System.out.println("TE is NULL"); + + if (te instanceof TileEntityLaser) + { + TileEntityLaser l = (TileEntityLaser)te; + l.yaw = yaw; + l.pitch = pitch; + l.delayTicks = 0; + l.isEmitting = true; } + } } - - public void handleLaserTargeting(Packet250CustomPayload packet, EntityPlayer player) { - DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); - - try { - int x = inputStream.readInt(); - int y = inputStream.readInt(); - int z = inputStream.readInt(); - - float yaw = inputStream.readFloat(); - float pitch = inputStream.readFloat(); - - System.out.println("Got target packet: (" + x + "; " + y + "; " + z + ") | yaw: " + yaw + " | pitch: " + pitch); - - TileEntity te = player.worldObj.getBlockTileEntity(x, y, z); - if (te != null) { - System.out.println("TE is NULL"); - if (te instanceof TileEntityLaser) { - TileEntityLaser l = (TileEntityLaser)te; - - l.yaw = yaw; - l.pitch = pitch; - - l.delayTicks = 0; - l.isEmitting = true; - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void handleFreqUpdate(Packet250CustomPayload packet, EntityPlayer player) { - DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); - - try { - int x = inputStream.readInt(); - int y = inputStream.readInt(); - int z = inputStream.readInt(); - - int freq = inputStream.readInt(); - - //System.out.println("Got freq packet: (" + x + "; " + y + "; " + z + ") | freq: " + freq); - - TileEntity te = player.worldObj.getBlockTileEntity(x, y, z); - if (te != null) { - if (te instanceof TileEntityMonitor) { - ((TileEntityMonitor)te).setFrequency(freq); - } else - if (te instanceof TileEntityCamera) { - ((TileEntityCamera)te).setFrequency(freq); - WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(freq, new ChunkPosition(x, y, z), player.worldObj).setType(0)); - } else - if (te instanceof TileEntityLaser) { - ((TileEntityLaser)te).camFreq = freq; - WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(freq, new ChunkPosition(x, y, z), player.worldObj).setType(1)); - } - } - } catch (Exception e) { - e.printStackTrace(); - } + catch (Exception e) + { + e.printStackTrace(); } - - private void handleBeam(Packet250CustomPayload packet, EntityPlayer player) { - DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); - - int dimID; - Vector3 source, target; - double sx, sy, sz; - double tx, ty, tz; - float r, g, b; - int age; - int energy; - - World worldObj = player.worldObj; - - try { - // Read source vector - sx = inputStream.readDouble(); - sy = inputStream.readDouble(); - sz = inputStream.readDouble(); - source = new Vector3(sx, sy, sz); - - // Read target vector - tx = inputStream.readDouble(); - ty = inputStream.readDouble(); - tz = inputStream.readDouble(); - target = new Vector3(tx, ty, tz); - - // Read r, g, b of laser - r = inputStream.readFloat(); - g = inputStream.readFloat(); - b = inputStream.readFloat(); - - // Read age - age = inputStream.readByte(); - - // Read energy value - energy = inputStream.readInt(); - - // Render beam - /*System.out.println("sx: " + sx + " sy: " + sy + " sz: " + sz); - System.out.println("tx: " + sx + " ty: " + sy + " tz: " + sz); - - System.out.println("source: " + source); - System.out.println("target: " + target); - System.out.println("r: " + r); - System.out.println("g: " + g); - System.out.println("b " + b); - System.out.println("age: " + age); - System.out.println("energy: " + energy);*/ - - // To avoid NPE at logging in - if (worldObj == null) { - System.out.println("WorldObj is null"); - return; - } - - WarpDrive.proxy.renderBeam(worldObj, source.clone(), target.clone(), r, g, b, age, energy); - } catch (IOException e) { - e.printStackTrace(); - return; + } + + public void handleFreqUpdate(Packet250CustomPayload packet, EntityPlayer player) + { + DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); + + try + { + int x = inputStream.readInt(); + int y = inputStream.readInt(); + int z = inputStream.readInt(); + int freq = inputStream.readInt(); + //System.out.println("Got freq packet: (" + x + "; " + y + "; " + z + ") | freq: " + freq); + TileEntity te = player.worldObj.getBlockTileEntity(x, y, z); + + if (te != null) + { + if (te instanceof TileEntityMonitor) + { + ((TileEntityMonitor)te).setFrequency(freq); } - } + else if (te instanceof TileEntityCamera) + { + ((TileEntityCamera)te).setFrequency(freq); + WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(freq, new ChunkPosition(x, y, z), player.worldObj).setType(0)); + } + else if (te instanceof TileEntityLaser) + { + ((TileEntityLaser)te).camFreq = freq; + WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(freq, new ChunkPosition(x, y, z), player.worldObj).setType(1)); + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + private void handleBeam(Packet250CustomPayload packet, EntityPlayer player) + { + DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); + int dimID; + Vector3 source, target; + double sx, sy, sz; + double tx, ty, tz; + float r, g, b; + int age; + int energy; + World worldObj = player.worldObj; + + try + { + // Read source vector + sx = inputStream.readDouble(); + sy = inputStream.readDouble(); + sz = inputStream.readDouble(); + source = new Vector3(sx, sy, sz); + // Read target vector + tx = inputStream.readDouble(); + ty = inputStream.readDouble(); + tz = inputStream.readDouble(); + target = new Vector3(tx, ty, tz); + // Read r, g, b of laser + r = inputStream.readFloat(); + g = inputStream.readFloat(); + b = inputStream.readFloat(); + // Read age + age = inputStream.readByte(); + // Read energy value + energy = inputStream.readInt(); + + // Render beam + /*System.out.println("sx: " + sx + " sy: " + sy + " sz: " + sz); + System.out.println("tx: " + sx + " ty: " + sy + " tz: " + sz); + + System.out.println("source: " + source); + System.out.println("target: " + target); + System.out.println("r: " + r); + System.out.println("g: " + g); + System.out.println("b " + b); + System.out.println("age: " + age); + System.out.println("energy: " + energy);*/ + + // To avoid NPE at logging in + if (worldObj == null) + { + System.out.println("WorldObj is null"); + return; + } + + WarpDrive.proxy.renderBeam(worldObj, source.clone(), target.clone(), r, g, b, age, energy); + } + catch (IOException e) + { + e.printStackTrace(); + return; + } + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/SoundHandler.java b/src/cr0s/WarpDrive/SoundHandler.java index 5dc4c5d1..c76e5814 100644 --- a/src/cr0s/WarpDrive/SoundHandler.java +++ b/src/cr0s/WarpDrive/SoundHandler.java @@ -14,11 +14,10 @@ public class SoundHandler try { System.out.println("[WarpDrive] Registering sound files..."); - event.manager.addSound("warpdrive:warp.ogg"); - - event.manager.addSound("warpdrive:hilaser.ogg"); - event.manager.addSound("warpdrive:midlaser.ogg"); - event.manager.addSound("warpdrive:lowlaser.ogg"); + event.manager.addSound("warpdrive:warp.ogg"); + event.manager.addSound("warpdrive:hilaser.ogg"); + event.manager.addSound("warpdrive:midlaser.ogg"); + event.manager.addSound("warpdrive:lowlaser.ogg"); } catch (Exception e) { diff --git a/src/cr0s/WarpDrive/SpaceEventHandler.java b/src/cr0s/WarpDrive/SpaceEventHandler.java index c85888ee..396a7746 100644 --- a/src/cr0s/WarpDrive/SpaceEventHandler.java +++ b/src/cr0s/WarpDrive/SpaceEventHandler.java @@ -15,97 +15,121 @@ import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; * Обработчик событий в мире Space * @author Cr0s */ -public class SpaceEventHandler { +public class SpaceEventHandler +{ private HashMap<String, Integer> vacuumPlayers; - - public SpaceEventHandler() { + + public SpaceEventHandler() + { vacuumPlayers = new HashMap<String, Integer>(); } - + @ForgeSubscribe - public void livingUpdate(LivingUpdateEvent event) { - EntityLivingBase entity = event.entityLiving; - - if (Math.abs(MathHelper.floor_double(entity.posX)) > WarpDrive.WORLD_LIMIT_BLOCKS || Math.abs(MathHelper.floor_double(entity.posZ)) > WarpDrive.WORLD_LIMIT_BLOCKS) { - if (entity instanceof EntityPlayerMP) { - if (((EntityPlayerMP)entity).capabilities.isCreativeMode) { + public void livingUpdate(LivingUpdateEvent event) + { + EntityLivingBase entity = event.entityLiving; + + if (Math.abs(MathHelper.floor_double(entity.posX)) > WarpDrive.WORLD_LIMIT_BLOCKS || Math.abs(MathHelper.floor_double(entity.posZ)) > WarpDrive.WORLD_LIMIT_BLOCKS) + { + if (entity instanceof EntityPlayerMP) + { + if (((EntityPlayerMP)entity).capabilities.isCreativeMode) + { return; } } + entity.attackEntityFrom(DamageSource.outOfWorld, 9000); return; - } - + } + final int HELMET_ID_SKUBA = 30082; final int HELMET_ID_HAZMAT = 14023; final int HELMET_ID_QUANTUM = 30174; final int AIR_CELL_ID = 30079; - + // Обновление происходит в космическом или гипер пространстве - if (entity.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID || entity.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) { + if (entity.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID || entity.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) + { boolean inVacuum = isEntityInVacuum(entity); - + // Damage entity if in vacuum without protection - if (inVacuum) { - if (entity instanceof EntityPlayerMP) { - if (((EntityPlayerMP)entity).getCurrentArmor(3) != null && ((((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_SKUBA || ((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_HAZMAT) || ((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_QUANTUM)) { + if (inVacuum) + { + if (entity instanceof EntityPlayerMP) + { + if (((EntityPlayerMP)entity).getCurrentArmor(3) != null && ((((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_SKUBA || ((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_HAZMAT) || ((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_QUANTUM)) + { Integer airValue = vacuumPlayers.get(((EntityPlayerMP)entity).username); - if (airValue == null) { + + if (airValue == null) + { vacuumPlayers.put(((EntityPlayerMP)entity).username, 300); airValue = 300; } - - if (airValue <= 0) { - if (((EntityPlayerMP)entity).inventory.consumeInventoryItem(AIR_CELL_ID)) { + + if (airValue <= 0) + { + if (((EntityPlayerMP)entity).inventory.consumeInventoryItem(AIR_CELL_ID)) + { setPlayerAirValue(entity, 300); - } else { - setPlayerAirValue(entity, 0); + } + else + { + setPlayerAirValue(entity, 0); entity.attackEntityFrom(DamageSource.drown, 1); } - } else { + } + else + { setPlayerAirValue(entity, airValue - 1); } - } else { + } + else + { entity.attackEntityFrom(DamageSource.drown, 1); } - + // Отправить назад на Землю - if (entity.posY < -10.0D) { + if (entity.posY < -10.0D) + { ((EntityPlayerMP)entity).mcServer.getConfigurationManager().transferPlayerToDimension(((EntityPlayerMP) entity), 0, new SpaceTeleporter(DimensionManager.getWorld(WarpDrive.instance.spaceDimID), 0, MathHelper.floor_double(entity.posX), 250, MathHelper.floor_double(entity.posZ))); ((EntityPlayerMP)entity).setFire(30); ((EntityPlayerMP)entity).setPositionAndUpdate(entity.posX, 250D, entity.posZ); } - } else { + } + else + { entity.attackEntityFrom(DamageSource.drown, 1); - } + } } } } - - private void setPlayerAirValue(EntityLivingBase entity, Integer air) { - vacuumPlayers.remove(((EntityPlayerMP)entity).username); - vacuumPlayers.put(((EntityPlayerMP)entity).username, air); + + private void setPlayerAirValue(EntityLivingBase entity, Integer air) + { + vacuumPlayers.remove(((EntityPlayerMP)entity).username); + vacuumPlayers.put(((EntityPlayerMP)entity).username, air); } - /** * Проверка, находится ли Entity в открытом космосе * @param e - * @return + * @return */ - private boolean isEntityInVacuum(Entity e) { - + private boolean isEntityInVacuum(Entity e) + { int x = MathHelper.floor_double(e.posX); int y = MathHelper.floor_double(e.posY); int z = MathHelper.floor_double(e.posZ); - int id1 = e.worldObj.getBlockId(x, y, z); int id2 = e.worldObj.getBlockId(x, y + 1, z); - - if (id1 == WarpDrive.instance.config.airID || id2 == WarpDrive.instance.config.airID) { + + if (id1 == WarpDrive.instance.config.airID || id2 == WarpDrive.instance.config.airID) + { return false; } - + return true; } } diff --git a/src/cr0s/WarpDrive/SpaceGenerator.java b/src/cr0s/WarpDrive/SpaceGenerator.java index 2a79787a..784e0cd5 100644 --- a/src/cr0s/WarpDrive/SpaceGenerator.java +++ b/src/cr0s/WarpDrive/SpaceGenerator.java @@ -4,7 +4,6 @@ */ package cr0s.WarpDrive; -import cr0s.WarpDrive.WarpDrive; import java.util.List; import java.util.Random; import net.minecraft.entity.EnumCreatureType; @@ -16,8 +15,8 @@ import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.gen.ChunkProviderGenerate; -public class SpaceGenerator extends ChunkProviderGenerate implements IChunkProvider { - +public class SpaceGenerator extends ChunkProviderGenerate implements IChunkProvider +{ private Random rand; private BiomeGenBase[] biomesForGeneration = new BiomeGenBase[1]; @@ -26,54 +25,53 @@ public class SpaceGenerator extends ChunkProviderGenerate implements IChunkProvi */ private World worldObj; - - public SpaceGenerator(World par1World, long par2) { + public SpaceGenerator(World par1World, long par2) + { super(par1World, par2, false); - rand = new Random(); this.worldObj = par1World; } @Override - public Chunk provideChunk(int par1, int par2) { + public Chunk provideChunk(int par1, int par2) + { this.rand.setSeed((long) par1 * 341873128712L + (long) par2 * 132897987541L); byte[] var3 = new byte[32768]; generateTerrain(par1, par2, var3); //this.caveGenerator.generate(this, this.worldObj, par1, par2, var3); this.biomesForGeneration[0] = WarpDrive.spaceBiome; - Chunk var4 = new Chunk(this.worldObj, var3, par1, par2); - var4.generateSkylightMap(); return var4; } @Override - public Chunk loadChunk(int var1, int var2) { + public Chunk loadChunk(int var1, int var2) + { // TODO Auto-generated method stub return this.provideChunk(var1, var2); } @Override - public void populate(IChunkProvider var1, int var2, int var3) { + public void populate(IChunkProvider var1, int var2, int var3) + { //super.populate(var1, var2, var3); - // Generate chunk population - // GameRegistry.generateWorld(var2, var3, worldObj, var1, var1); + // GameRegistry.generateWorld(var2, var3, worldObj, var1, var1); } @Override - public boolean saveChunks(boolean var1, IProgressUpdate var2) { + public boolean saveChunks(boolean var1, IProgressUpdate var2) + { return super.saveChunks(var1, var2); } @Override - public void generateTerrain(int par1, int par2, byte[] par3ArrayOfByte) { + public void generateTerrain(int par1, int par2, byte[] par3ArrayOfByte) + { this.biomesForGeneration[0] = WarpDrive.spaceBiome; - - // if (!"Space".equals(worldObj.provider.getDimensionName())) { - // } - + // if (!"Space".equals(worldObj.provider.getDimensionName())) { + // } /*byte var4 = 4; byte var5 = 16; byte var6 = 16; @@ -144,39 +142,45 @@ public class SpaceGenerator extends ChunkProviderGenerate implements IChunkProvi } @Override - public boolean canSave() { + public boolean canSave() + { // TODO Auto-generated method stub return super.canSave(); } @Override - public String makeString() { + public String makeString() + { // TODO Auto-generated method stub return super.makeString(); } @Override public List getPossibleCreatures(EnumCreatureType var1, int var2, int var3, - int var4) { + int var4) + { // TODO Auto-generated method stub return null; } @Override public ChunkPosition findClosestStructure(World var1, String var2, - int var3, int var4, int var5) { + int var3, int var4, int var5) + { // TODO Auto-generated method stub return null; } @Override - public int getLoadedChunkCount() { + public int getLoadedChunkCount() + { // TODO Auto-generated method stub return super.getLoadedChunkCount(); } @Override - public void recreateStructures(int var1, int var2) { + public void recreateStructures(int var1, int var2) + { // TODO Auto-generated method stub } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/SpaceProvider.java b/src/cr0s/WarpDrive/SpaceProvider.java index cafb0d8d..88ea3e0c 100644 --- a/src/cr0s/WarpDrive/SpaceProvider.java +++ b/src/cr0s/WarpDrive/SpaceProvider.java @@ -2,8 +2,6 @@ package cr0s.WarpDrive; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.CloudRenderBlank; -import cr0s.WarpDrive.WarpDrive; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayerMP; @@ -15,25 +13,28 @@ import net.minecraft.world.biome.WorldChunkManagerHell; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.IChunkProvider; -public class SpaceProvider extends WorldProvider { - +public class SpaceProvider extends WorldProvider +{ public int exitXCoord; public int exitYCoord; public int exitZCoord; public int exitDimID; - - public SpaceProvider() { + + public SpaceProvider() + { this.worldChunkMgr = new WorldChunkManagerHell(WarpDrive.spaceBiome, 0.0F, 0.0F); this.hasNoSky = false; } @Override - public String getDimensionName() { + public String getDimensionName() + { return "Space"; } - + @Override - public boolean canRespawnHere() { + public boolean canRespawnHere() + { return false; } @@ -42,32 +43,32 @@ public class SpaceProvider extends WorldProvider { public float getStarBrightness(float par1) { return 1.0F; - } - + } + @Override public boolean isSurfaceWorld() { return true; - } - + } + @Override public int getAverageGroundLevel() { return 1; } - - + @Override public double getHorizon() { return 1; } - + @Override - public boolean canSnowAt(int x, int y, int z) { + public boolean canSnowAt(int x, int y, int z) + { return false; } - + @Override public void updateWeather() { @@ -75,25 +76,26 @@ public class SpaceProvider extends WorldProvider { this.worldObj.getWorldInfo().setRaining(false); this.worldObj.getWorldInfo().setThunderTime(0); this.worldObj.getWorldInfo().setThundering(false); - } + } @Override public BiomeGenBase getBiomeGenForCoords(int x, int z) { return WarpDrive.spaceBiome; - } - - @Override - public void setAllowedSpawnTypes(boolean allowHostile, boolean allowPeaceful) { - super.setAllowedSpawnTypes(false, false); - } @Override - public float calculateCelestialAngle(long par1, float par3) { + public void setAllowedSpawnTypes(boolean allowHostile, boolean allowPeaceful) + { + super.setAllowedSpawnTypes(false, false); + } + + @Override + public float calculateCelestialAngle(long par1, float par3) + { return 0F; } - + @Override protected void generateLightBrightnessTable() { @@ -110,12 +112,13 @@ public class SpaceProvider extends WorldProvider { { float var3 = 1.0F - (float)var2 / 15.0F; this.lightBrightnessTable[var2] = (1.0F - var3) / (var3 * 3.0F + 1.0F) * (1.0F - var1) + var1; - } - } + } + } @SideOnly(Side.CLIENT) @Override - public String getSaveFolder() { + public String getSaveFolder() + { return (dimensionId == 0 ? null : "WarpDrive/Space" + dimensionId); } @@ -126,7 +129,8 @@ public class SpaceProvider extends WorldProvider { }*/ @Override - public Vec3 getSkyColor(Entity cameraEntity, float partialTicks) { + public Vec3 getSkyColor(Entity cameraEntity, float partialTicks) + { setCloudRenderer(new CloudRenderBlank()); //setSkyRenderer(new SpaceSkyRenderer()); return this.worldObj.getWorldVec3Pool().getVecFromPool((double) 0, (double) 0, (double) 0); @@ -134,7 +138,8 @@ public class SpaceProvider extends WorldProvider { @SideOnly(Side.CLIENT) @Override - public Vec3 getFogColor(float par1, float par2) { + public Vec3 getFogColor(float par1, float par2) + { return this.worldObj.getWorldVec3Pool().getVecFromPool((double) 0, (double) 0, (double) 0); } @@ -143,73 +148,78 @@ public class SpaceProvider extends WorldProvider { public boolean isSkyColored() { return false; - } - + } + @Override public ChunkCoordinates getEntrancePortalLocation() { return null; - } - + } + @Override - public int getRespawnDimension(EntityPlayerMP player) { + public int getRespawnDimension(EntityPlayerMP player) + { return 0; // respawn on Earth } @Override - public IChunkProvider createChunkGenerator() { + public IChunkProvider createChunkGenerator() + { return new SpaceGenerator(worldObj, 45); } @Override - public boolean canBlockFreeze(int x, int y, int z, boolean byWater) { + public boolean canBlockFreeze(int x, int y, int z, boolean byWater) + { return false; } -/* - @Override - public ChunkCoordinates getRandomizedSpawnPoint() { - ChunkCoordinates var5 = new ChunkCoordinates(this.worldObj.getSpawnPoint()); + /* + @Override + public ChunkCoordinates getRandomizedSpawnPoint() { + ChunkCoordinates var5 = new ChunkCoordinates(this.worldObj.getSpawnPoint()); - //boolean isAdventure = worldObj.getWorldInfo().getGameType() == EnumGameType.ADVENTURE; - int spawnFuzz = 1000; - int spawnFuzzHalf = spawnFuzz / 2; + //boolean isAdventure = worldObj.getWorldInfo().getGameType() == EnumGameType.ADVENTURE; + int spawnFuzz = 1000; + int spawnFuzzHalf = spawnFuzz / 2; - { - var5.posX += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf; - var5.posZ += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf; - var5.posY = 200; + { + var5.posX += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf; + var5.posZ += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf; + var5.posY = 200; + } + + if (worldObj.isAirBlock(var5.posX, var5.posY, var5.posZ)) { + worldObj.setBlock(var5.posX, var5.posY, var5.posZ, Block.stone.blockID, 0, 2); + + worldObj.setBlock(var5.posX + 1, var5.posY + 1, var5.posZ, Block.glass.blockID, 0, 2); + worldObj.setBlock(var5.posX + 1, var5.posY + 2, var5.posZ, Block.glass.blockID, 0, 2); + + worldObj.setBlock(var5.posX - 1, var5.posY + 1, var5.posZ, Block.glass.blockID, 0, 2); + worldObj.setBlock(var5.posX - 1, var5.posY + 2, var5.posZ, Block.glass.blockID, 0, 2); + + worldObj.setBlock(var5.posX, var5.posY + 1, var5.posZ + 1, Block.glass.blockID, 0, 2); + worldObj.setBlock(var5.posX, var5.posY + 2, var5.posZ + 1, Block.glass.blockID, 0, 2); + + worldObj.setBlock(var5.posX, var5.posY + 1, var5.posZ - 1, Block.glass.blockID, 0, 2); + worldObj.setBlock(var5.posX, var5.posY + 3, var5.posZ - 1, Block.glass.blockID, 0, 2); + + //worldObj.setBlockWithNotify(var5.posX, var5.posY + 3, var5.posZ, Block.glass.blockID); + } + return var5; } - - if (worldObj.isAirBlock(var5.posX, var5.posY, var5.posZ)) { - worldObj.setBlock(var5.posX, var5.posY, var5.posZ, Block.stone.blockID, 0, 2); - - worldObj.setBlock(var5.posX + 1, var5.posY + 1, var5.posZ, Block.glass.blockID, 0, 2); - worldObj.setBlock(var5.posX + 1, var5.posY + 2, var5.posZ, Block.glass.blockID, 0, 2); - - worldObj.setBlock(var5.posX - 1, var5.posY + 1, var5.posZ, Block.glass.blockID, 0, 2); - worldObj.setBlock(var5.posX - 1, var5.posY + 2, var5.posZ, Block.glass.blockID, 0, 2); - - worldObj.setBlock(var5.posX, var5.posY + 1, var5.posZ + 1, Block.glass.blockID, 0, 2); - worldObj.setBlock(var5.posX, var5.posY + 2, var5.posZ + 1, Block.glass.blockID, 0, 2); - - worldObj.setBlock(var5.posX, var5.posY + 1, var5.posZ - 1, Block.glass.blockID, 0, 2); - worldObj.setBlock(var5.posX, var5.posY + 3, var5.posZ - 1, Block.glass.blockID, 0, 2); - - //worldObj.setBlockWithNotify(var5.posX, var5.posY + 3, var5.posZ, Block.glass.blockID); - } - return var5; - } -*/ + */ @Override - public boolean getWorldHasVoidParticles() { + public boolean getWorldHasVoidParticles() + { return false; } - + @Override - public boolean isDaytime() { + public boolean isDaytime() + { return true; } - + @Override public boolean canDoLightning(Chunk chunk) { diff --git a/src/cr0s/WarpDrive/SpaceSkyRenderer.java b/src/cr0s/WarpDrive/SpaceSkyRenderer.java index 7498d5c4..70e4077b 100644 --- a/src/cr0s/WarpDrive/SpaceSkyRenderer.java +++ b/src/cr0s/WarpDrive/SpaceSkyRenderer.java @@ -23,7 +23,7 @@ public class SpaceSkyRenderer extends IRenderHandler public int glSkyList2; private final boolean MORE_STARS = false; - + public SpaceSkyRenderer() { GL11.glPushMatrix(); @@ -113,7 +113,6 @@ public class SpaceSkyRenderer extends IRenderHandler float var10; float var11; float var12; - float var20 = 0; if (spaceProvider != null) @@ -130,37 +129,30 @@ public class SpaceSkyRenderer extends IRenderHandler GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); GL11.glPushMatrix(); - GL11.glPopMatrix(); - GL11.glPushMatrix(); - GL11.glRotatef(-90.0F, 0.0F, 1.0F, 0.0F); GL11.glColor4f(1.0F, 1.0F, 1.0F, 5F); GL11.glRotatef(world.getCelestialAngle(partialTicks) * 360.0F, 1.0F, 0.0F, 0.0F); var12 = 30.0F; - FMLClientHandler.instance().getClient().renderEngine.func_110577_a(sunTexture); + FMLClientHandler.instance().getClient().renderEngine.bindTexture(sunTexture); var23.startDrawingQuads(); var23.addVertexWithUV(-var12, 150.0D, -var12, 0.0D, 0.0D); var23.addVertexWithUV(var12, 150.0D, -var12, 1.0D, 0.0D); var23.addVertexWithUV(var12, 150.0D, var12, 1.0D, 1.0D); var23.addVertexWithUV(-var12, 150.0D, var12, 0.0D, 1.0D); var23.draw(); - GL11.glPopMatrix(); - GL11.glPushMatrix(); - GL11.glDisable(GL11.GL_BLEND); - // HOME: var12 = 10.0F; - final float earthRotation = (float) (world.getSpawnPoint().posZ - mc.thePlayer.posZ) * 0.01F; + final float earthRotation = (float)(world.getSpawnPoint().posZ - mc.thePlayer.posZ) * 0.01F; GL11.glScalef(0.6F, 0.6F, 0.6F); GL11.glRotatef(earthRotation, 1.0F, 0.0F, 0.0F); GL11.glRotatef(200F, 1.0F, 0.0F, 0.0F); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1F); - FMLClientHandler.instance().getClient().renderEngine.func_110577_a(overworldTexture); + FMLClientHandler.instance().getClient().renderEngine.bindTexture(overworldTexture); world.getMoonPhase(); var23.startDrawingQuads(); var23.addVertexWithUV(-var12, -100.0D, var12, 0, 1); @@ -168,7 +160,6 @@ public class SpaceSkyRenderer extends IRenderHandler var23.addVertexWithUV(var12, -100.0D, -var12, 1, 0); var23.addVertexWithUV(-var12, -100.0D, -var12, 0, 0); var23.draw(); - GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); GL11.glDisable(GL11.GL_BLEND); GL11.glEnable(GL11.GL_ALPHA_TEST); @@ -185,7 +176,7 @@ public class SpaceSkyRenderer extends IRenderHandler GL11.glCallList(this.glSkyList2); GL11.glPopMatrix(); var10 = 1.0F; - var11 = -((float) (var25 + 65.0D)); + var11 = -((float)(var25 + 65.0D)); var12 = -var10; var23.startDrawingQuads(); var23.setColorRGBA_I(0, 255); @@ -213,9 +204,8 @@ public class SpaceSkyRenderer extends IRenderHandler } GL11.glColor3f(70F / 256F, 70F / 256F, 70F / 256F); - GL11.glPushMatrix(); - GL11.glTranslatef(0.0F, -((float) (var25 - 16.0D)), 0.0F); + GL11.glTranslatef(0.0F, -((float)(var25 - 16.0D)), 0.0F); GL11.glCallList(this.glSkyList2); GL11.glPopMatrix(); GL11.glEnable(GL11.GL_TEXTURE_2D); diff --git a/src/cr0s/WarpDrive/SpaceTeleporter.java b/src/cr0s/WarpDrive/SpaceTeleporter.java index cfbfea4c..7018e04a 100644 --- a/src/cr0s/WarpDrive/SpaceTeleporter.java +++ b/src/cr0s/WarpDrive/SpaceTeleporter.java @@ -5,13 +5,14 @@ import net.minecraft.world.Teleporter; import net.minecraft.world.World; import net.minecraft.world.WorldServer; -public class SpaceTeleporter extends Teleporter { - +public class SpaceTeleporter extends Teleporter +{ int x, y, z; int orientation; World world; - public SpaceTeleporter(WorldServer par1WorldServer, int orientation, int x, int y, int z) { + public SpaceTeleporter(WorldServer par1WorldServer, int orientation, int x, int y, int z) + { super(par1WorldServer); this.orientation = orientation; this.x = x; @@ -24,21 +25,22 @@ public class SpaceTeleporter extends Teleporter { * Create a new portal near an entity. */ @Override - public void placeInPortal(Entity par1Entity, double par2, double par4, double par6, float par8) { + public void placeInPortal(Entity par1Entity, double par2, double par4, double par6, float par8) + { //EntityPlayer player = (EntityPlayer) par1Entity; //player.setWorld(world); //player.setPositionAndUpdate(x, y, z); } - + @Override public boolean makePortal(Entity par1Entity) { return false; - } - + } + @Override public boolean placeInExistingPortal(Entity par1Entity, double par2, double par4, double par6, float par8) { return false; - } + } } diff --git a/src/cr0s/WarpDrive/SpaceTpCommand.java b/src/cr0s/WarpDrive/SpaceTpCommand.java index b477b437..c9c1e276 100644 --- a/src/cr0s/WarpDrive/SpaceTpCommand.java +++ b/src/cr0s/WarpDrive/SpaceTpCommand.java @@ -7,46 +7,53 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.util.MathHelper; import net.minecraft.world.WorldServer; - -public class SpaceTpCommand extends CommandBase { - +public class SpaceTpCommand extends CommandBase +{ @Override - public int getRequiredPermissionLevel() { + public int getRequiredPermissionLevel() + { return 2; } - + @Override - public String getCommandName() { + public String getCommandName() + { return "space"; } @Override - public void processCommand(ICommandSender icommandsender, String[] astring) { + public void processCommand(ICommandSender icommandsender, String[] astring) + { EntityPlayerMP player = (EntityPlayerMP)icommandsender; MinecraftServer server = MinecraftServer.getServer(); int targetDim = WarpDrive.instance.spaceDimID; - if (astring.length >= 1) { - if ("hyper".equals(astring[0])) { + + if (astring.length >= 1) + { + if ("hyper".equals(astring[0])) + { targetDim = WarpDrive.instance.hyperSpaceDimID; - } else { + } + else + { notifyAdmins(icommandsender, "/space: teleporting player " + astring[0] + " to space", new Object[0]); player = MinecraftServer.getServer().getConfigurationManager().getPlayerForUsername(astring[0]); } } - - if (player == null) { + + if (player == null) + { return; } - - WorldServer to = server.worldServerForDimension(targetDim); - SpaceTeleporter teleporter = new SpaceTeleporter(to, 0, MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ)); + WorldServer to = server.worldServerForDimension(targetDim); + SpaceTeleporter teleporter = new SpaceTeleporter(to, 0, MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ)); server.getConfigurationManager().transferPlayerToDimension(player, targetDim, teleporter); } @Override - public String getCommandUsage(ICommandSender icommandsender) { + public String getCommandUsage(ICommandSender icommandsender) + { return "/space [hyper|<player>]"; } - } diff --git a/src/cr0s/WarpDrive/SpaceWorldGenerator.java b/src/cr0s/WarpDrive/SpaceWorldGenerator.java index 6bc236d9..19acb5ec 100644 --- a/src/cr0s/WarpDrive/SpaceWorldGenerator.java +++ b/src/cr0s/WarpDrive/SpaceWorldGenerator.java @@ -2,7 +2,6 @@ package cr0s.WarpDrive; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.IWorldGenerator; -import cr0s.WarpDrive.WarpDrive; import java.util.Random; import java.util.List; import java.util.ArrayList; @@ -13,17 +12,17 @@ import net.minecraft.world.chunk.IChunkProvider; /** * @author Cr0s */ -public class SpaceWorldGenerator implements IWorldGenerator { - +public class SpaceWorldGenerator implements IWorldGenerator +{ // Radius of simple moon public final int MOON_RADIUS = 32; public final int MOON_CORE_RADIUS = 10; - + // Star radius public final int RED_DWARF_RADIUS = 42; public final int YELLOW_GIANT_RADIUS = 64; public final int YELLOW_SUPERGIANT_RADIUS = 80; - + // Upper than 128 almost nothing will be generated public final int Y_LIMIT = 128; // Lower limit @@ -31,7 +30,7 @@ public class SpaceWorldGenerator implements IWorldGenerator { public boolean isICBMLoaded = false; public boolean isAELoaded = false; - + /** * Generator for chunk * @param random @@ -39,207 +38,214 @@ public class SpaceWorldGenerator implements IWorldGenerator { * @param chunkZ * @param world * @param chunkGenerator - * @param chunkProvider + * @param chunkProvider */ @Override - public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { - if (world.provider.dimensionId != WarpDrive.instance.spaceDimID) { + public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) + { + if (world.provider.dimensionId != WarpDrive.instance.spaceDimID) + { return; } // Check for mods is present isICBMLoaded = Loader.isModLoaded("ICBM|Explosion"); isAELoaded = Loader.isModLoaded("AppliedEnergistics"); - int x = (chunkX * 16) + (5 - random.nextInt(10)); int z = (chunkZ * 16) + (5 - random.nextInt(10)); - if (Math.abs(x) > WarpDrive.WORLD_LIMIT_BLOCKS || Math.abs(z) > WarpDrive.WORLD_LIMIT_BLOCKS) { + if (Math.abs(x) > WarpDrive.WORLD_LIMIT_BLOCKS || Math.abs(z) > WarpDrive.WORLD_LIMIT_BLOCKS) + { return; } - + int y = Y_LIMIT_DOWN + random.nextInt(Y_LIMIT - Y_LIMIT_DOWN); - + // Moon setup - if (random.nextInt(8000) == 1) { + if (random.nextInt(8000) == 1) + { generateMoon(world, x, y, z); return; - } - + } + // Simple asteroids - if (random.nextInt(500) == 1) { + if (random.nextInt(500) == 1) + { System.out.println("Generating asteroid at " + x + " " + y + " " + z); generateAsteroid(world, x, y, z, 6, 11); return; } // Random asteroid of block - if (random.nextInt(1000) == 1) { + if (random.nextInt(1000) == 1) + { generateRandomAsteroid(world, x, y, z, 6, 11); - - if (random.nextBoolean()) { + + if (random.nextBoolean()) + { generateGasCloudOfColor(world, x, y, z, 6, 11, random.nextInt(12)); } - } + } // Ice asteroid - if (random.nextInt(2000) == 1) { + if (random.nextInt(2000) == 1) + { System.out.println("Generating ice asteroid at " + x + " " + y + " " + z); generateAsteroidOfBlock(world, x, y, z, 6, 11, Block.ice.blockID); - return; - } - + } + // Asteroid field - if (random.nextInt(3500) == 1) { + if (random.nextInt(3500) == 1) + { System.out.println("Generating asteroid field at " + x + " " + y + " " + z); generateAsteroidField(world, x, y, z); - return; - } - + } + // Diamond asteroid - if (random.nextInt(10000) == 1) { + if (random.nextInt(10000) == 1) + { System.out.println("Generating diamond asteroid at " + x + " " + y + " " + z); generateAsteroidOfBlock(world, x, y, z, 4, 6, Block.oreDiamond.blockID); - // Diamond block core - world.setBlock(x, y, z, Block.blockDiamond.blockID, 0, 2); - - if (random.nextBoolean()) { + world.setBlock(x, y, z, Block.blockDiamond.blockID, 0, 2); + + if (random.nextBoolean()) + { generateGasCloudOfColor(world, x, y, z, 6, 11, random.nextInt(12)); } - } + } } - public void generateMoon(World world, int x, int y, int z) { - System.out.println("Generating moon at " + x + " " + y + " " + z); - generateSphereEntity(world, x, y, z, MOON_RADIUS, false, 0, 0); - - // Generate moon's core - if (world.rand.nextInt(10) > 2) - { - generateSphere2(world, x, y, z, MOON_CORE_RADIUS, false, Block.lavaStill.blockID, false); // Lava core - generateSphere2(world, x, y, z, MOON_CORE_RADIUS + 1, false, Block.obsidian.blockID, true); // Obsidian shell - } else - { - generateSphere2(world, x, y, z, MOON_CORE_RADIUS, false, 0, false); - generateSmallShip(world, x, y, z); - } - - // Generate moon's atmosphere - if (world.rand.nextBoolean()) { - int gasColor = 1 + world.rand.nextInt(11); - generateGasSphereEntity(world, x, y, z, MOON_RADIUS + 5, true, gasColor); - } - - // Place bedrock blocks - world.setBlock(x, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x + MOON_CORE_RADIUS, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x - MOON_CORE_RADIUS, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y, z + MOON_CORE_RADIUS, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y, z - MOON_CORE_RADIUS, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y + MOON_CORE_RADIUS, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y - MOON_CORE_RADIUS, z, Block.bedrock.blockID, 0, 0); + public void generateMoon(World world, int x, int y, int z) + { + System.out.println("Generating moon at " + x + " " + y + " " + z); + generateSphereEntity(world, x, y, z, MOON_RADIUS, false, 0, 0); - world.setBlock(x + MOON_RADIUS / 2, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x - MOON_RADIUS / 2, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y, z + MOON_RADIUS / 2, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y, z - MOON_RADIUS / 2, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y + MOON_RADIUS / 2, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y - MOON_RADIUS / 2, z, Block.bedrock.blockID, 0, 0); - - world.setBlock(x + MOON_RADIUS - 10, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x - MOON_RADIUS - 10, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y, z + MOON_RADIUS - 10, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y, z - MOON_RADIUS - 10, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y + MOON_RADIUS - 10, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y - MOON_RADIUS - 10, z, Block.bedrock.blockID, 0, 0); - } - - - private void placeStarCore(World world, int x, int y, int z, int radius) { + // Generate moon's core + if (world.rand.nextInt(10) > 2) + { + generateSphere2(world, x, y, z, MOON_CORE_RADIUS, false, Block.lavaStill.blockID, false); // Lava core + generateSphere2(world, x, y, z, MOON_CORE_RADIUS + 1, false, Block.obsidian.blockID, true); // Obsidian shell + } + else + { + generateSphere2(world, x, y, z, MOON_CORE_RADIUS, false, 0, false); + generateSmallShip(world, x, y, z); + } + + // Generate moon's atmosphere + if (world.rand.nextBoolean()) + { + int gasColor = 1 + world.rand.nextInt(11); + generateGasSphereEntity(world, x, y, z, MOON_RADIUS + 5, true, gasColor); + } + + // Place bedrock blocks + world.setBlock(x, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x + MOON_CORE_RADIUS, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x - MOON_CORE_RADIUS, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y, z + MOON_CORE_RADIUS, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y, z - MOON_CORE_RADIUS, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y + MOON_CORE_RADIUS, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y - MOON_CORE_RADIUS, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x + MOON_RADIUS / 2, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x - MOON_RADIUS / 2, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y, z + MOON_RADIUS / 2, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y, z - MOON_RADIUS / 2, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y + MOON_RADIUS / 2, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y - MOON_RADIUS / 2, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x + MOON_RADIUS - 10, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x - MOON_RADIUS - 10, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y, z + MOON_RADIUS - 10, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y, z - MOON_RADIUS - 10, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y + MOON_RADIUS - 10, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y - MOON_RADIUS - 10, z, Block.bedrock.blockID, 0, 0); + } + + private void placeStarCore(World world, int x, int y, int z, int radius) + { EntityStarCore core = new EntityStarCore(world, x, y, z, radius); core.xCoord = x; core.yCoord = y; core.zCoord = z; - core.setPosition((double)x, (double)y, (double)z); world.spawnEntityInWorld(core); } - public void generateStar(World world, int x, int y, int z) { + public void generateStar(World world, int x, int y, int z) + { int starClass = world.rand.nextInt(3); System.out.println("Generating star (class " + starClass + ") at " + x + " " + y + " " + z); - - switch (starClass) { + + switch (starClass) + { case 0: // red dwarf generateSphereEntity(world, x, y, z, RED_DWARF_RADIUS, false, Block.blockRedstone.blockID, 0); - // Heliosphere of red gas generateGasSphereEntity(world, x, y, z, RED_DWARF_RADIUS + 6, true, 1); - placeStarCore(world, x, y, z, RED_DWARF_RADIUS + 6); break; - + case 1: // yellow giant generateSphereEntity(world, x, y, z, YELLOW_GIANT_RADIUS, false, Block.glowStone.blockID, 0); - // Heliosphere of yellow gas - generateGasSphereEntity(world, x, y, z, YELLOW_GIANT_RADIUS + 6, true, 3); + generateGasSphereEntity(world, x, y, z, YELLOW_GIANT_RADIUS + 6, true, 3); placeStarCore(world, x, y, z, YELLOW_GIANT_RADIUS + 6); break; + case 2: generateSphereEntity(world, x, y, z, YELLOW_SUPERGIANT_RADIUS, false, Block.glowStone.blockID, 0); - // Heliosphere of yellow gas - generateGasSphereEntity(world, x, y, z, YELLOW_SUPERGIANT_RADIUS + 6, true, 3); + generateGasSphereEntity(world, x, y, z, YELLOW_SUPERGIANT_RADIUS + 6, true, 3); placeStarCore(world, x, y, z, YELLOW_SUPERGIANT_RADIUS + 6); - break; - } - } - - private void generateSphereEntity(World world, int x, int y, int z, int radius, boolean hollow, int blockID, int blockMeta) { + break; + } + } + + private void generateSphereEntity(World world, int x, int y, int z, int radius, boolean hollow, int blockID, int blockMeta) + { boolean isSurface = (blockID == 0); EntitySphereGen esg = new EntitySphereGen(world, x, y, z, radius, blockID, blockMeta, hollow, false, isSurface); esg.xCoord = x; esg.yCoord = y; esg.zCoord = z; - - - world.spawnEntityInWorld(esg); + world.spawnEntityInWorld(esg); } - - private void generateGasSphereEntity(World world, int x, int y, int z, int radius, boolean hollow, int color) { + + private void generateGasSphereEntity(World world, int x, int y, int z, int radius, boolean hollow, int color) + { EntitySphereGen esg = new EntitySphereGen(world, x, y, z, radius, WarpDrive.instance.config.gasID, color, hollow, true, false); esg.xCoord = x; esg.yCoord = y; esg.zCoord = z; - - - world.spawnEntityInWorld(esg); - } - - private void generateSmallShip(World world, int x, int y, int z) { + world.spawnEntityInWorld(esg); + } + + private void generateSmallShip(World world, int x, int y, int z) + { x = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(10)); y = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(10)); z = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(10)); - System.out.println("Generating small ship at " + x + " " + y + " " + z); - new WorldGenSmallShip(world.rand.nextBoolean()).generate(world, world.rand, x, y, z); } - - private void generateRandomAsteroid(World world, int x, int y, int z, int asteroidSizeMax, int centerRadiusMax) { + + private void generateRandomAsteroid(World world, int x, int y, int z, int asteroidSizeMax, int centerRadiusMax) + { Random random = new Random(); - - if (random.nextInt(30) == 1) { + + if (random.nextInt(30) == 1) + { System.out.println("Generating random asteroid of block at " + x + "; " + y + "; " + z); - generateAsteroidOfBlock(world, x, y, z, asteroidSizeMax, centerRadiusMax, getRandomSurfaceBlockID(random, false, true)); - } else { + generateAsteroidOfBlock(world, x, y, z, asteroidSizeMax, centerRadiusMax, getRandomSurfaceBlockID(random, false, true)); + } + else + { generateAsteroid(world, x, y, z, asteroidSizeMax, centerRadiusMax); } } - + /** * Asteroid field generator * @param world мир @@ -247,53 +253,58 @@ public class SpaceWorldGenerator implements IWorldGenerator { * @param y координата центра поля * @param z координата центра поля */ - public void generateAsteroidField(World world, int x, int y, int z) { + public void generateAsteroidField(World world, int x, int y, int z) + { int numOfAsteroids = 15 + world.rand.nextInt(30); int numOfClouds = 5 + world.rand.nextInt(10); - // Minimal distance between asteroids in field final int FIELD_ASTEROID_MIN_DISTANCE = 5; - // Maximum distance final int FIELD_ASTEROID_MAX_DISTANCE = 100; - + // Setting up of big asteroids - for (int i = 1; i <= numOfAsteroids; i++) { + for (int i = 1; i <= numOfAsteroids; i++) + { int aX = x + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); int aY = y + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); int aZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); - // Place an asteroid generateRandomAsteroid(world, aX, aY, aZ, 4, 6); } - + // Setting up small asteroids - for (int i = 1; i <= numOfAsteroids; i++) { + for (int i = 1; i <= numOfAsteroids; i++) + { int aX = x + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); int aY = y + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); int aZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); - + // Placing - if (world.rand.nextInt(100) != 0) { + if (world.rand.nextInt(100) != 0) + { generateRandomAsteroid(world, aX, aY, aZ, 2, 2); - } else { + } + else + { generateSmallShip(world, aX, aY, aZ); } - } - + } + int gasColor = world.rand.nextInt(12); - + // Setting up gas clouds - for (int i = 1; i <= numOfClouds; i++) { + for (int i = 1; i <= numOfClouds; i++) + { int aX = x + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); int aY = y + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); int aZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); - + // Placing - if (world.rand.nextInt(10) != 0) { + if (world.rand.nextInt(10) != 0) + { generateGasCloudOfColor(world, aX, aY, aZ, 12, 15, gasColor); } - } + } } /** @@ -305,36 +316,37 @@ public class SpaceWorldGenerator implements IWorldGenerator { * @param cloudSizeMax maximum gas cloud size (by number of balls it consists) * @param centerRadiusMax maximum radius of central ball */ - public void generateGasCloudOfColor(World world, int x, int y, int z, int cloudSizeMax, int centerRadiusMax, int color) { + public void generateGasCloudOfColor(World world, int x, int y, int z, int cloudSizeMax, int centerRadiusMax, int color) + { int cloudSize = 1 + world.rand.nextInt(20); - - if (cloudSizeMax != 0) { + + if (cloudSizeMax != 0) + { cloudSize = Math.min(cloudSizeMax, cloudSize); - } + } int centerRadius = 1 + world.rand.nextInt(20); - if (centerRadiusMax != 0) { - centerRadius = Math.min(centerRadiusMax, centerRadius); - } - - - final int CENTER_SHIFT = 2; // Offset from center of central ball + if (centerRadiusMax != 0) + { + centerRadius = Math.min(centerRadiusMax, centerRadius); + } + + final int CENTER_SHIFT = 2; // Offset from center of central ball // Asteroid's center generateGasSphereEntity(world, x, y, z, centerRadius, false, color); // Asteroids knolls - for (int i = 1; i <= cloudSize; i++) { + for (int i = 1; i <= cloudSize; i++) + { int radius = 2 + world.rand.nextInt(centerRadius); - int newX = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); int newY = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); int newZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - generateGasSphereEntity(world, newX, newY, newZ, radius, false, color); } - } - + } + /** * Asteroid of block generator * @@ -344,36 +356,37 @@ public class SpaceWorldGenerator implements IWorldGenerator { * @param asteroidSizeMax maximum asteroid size (by number of balls it consists) * @param centerRadiusMax maximum radius of central ball */ - private void generateAsteroidOfBlock(World world, int x, int y, int z, int asteroidSizeMax, int centerRadiusMax, int blockID) { + private void generateAsteroidOfBlock(World world, int x, int y, int z, int asteroidSizeMax, int centerRadiusMax, int blockID) + { int asteroidSize = 1 + world.rand.nextInt(6); - - if (asteroidSizeMax != 0) { + + if (asteroidSizeMax != 0) + { asteroidSize = Math.min(asteroidSizeMax, asteroidSize); - } + } int centerRadius = 1 + world.rand.nextInt(6); - if (centerRadiusMax != 0) { - centerRadius = Math.min(centerRadiusMax, centerRadius); - } - - - final int CENTER_SHIFT = 2; // Offset from center of central ball + if (centerRadiusMax != 0) + { + centerRadius = Math.min(centerRadiusMax, centerRadius); + } + + final int CENTER_SHIFT = 2; // Offset from center of central ball // Asteroid's center generateSphere2(world, x, y, z, centerRadius, true, blockID, false); // Asteroids knolls - for (int i = 1; i <= asteroidSize; i++) { + for (int i = 1; i <= asteroidSize; i++) + { int radius = 2 + world.rand.nextInt(centerRadius); - int newX = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); int newY = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); int newZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - generateSphere2(world, newX, newY, newZ, radius, true, blockID, false); } - } - + } + /** * Asteroid generator * @@ -383,34 +396,35 @@ public class SpaceWorldGenerator implements IWorldGenerator { * @param asteroidSizeMax maximum asteroid size (by number of balls it consists) * @param centerRadiusMax maximum radius of central ball */ - public void generateAsteroid(World world, int x, int y, int z, int asteroidSizeMax, int centerRadiusMax) { + public void generateAsteroid(World world, int x, int y, int z, int asteroidSizeMax, int centerRadiusMax) + { int asteroidSize = 1 + world.rand.nextInt(6); - - if (asteroidSizeMax != 0) { + + if (asteroidSizeMax != 0) + { asteroidSize = Math.min(asteroidSizeMax, asteroidSize); - } + } int centerRadius = 1 + world.rand.nextInt(6); - if (centerRadiusMax != 0) { - centerRadius = Math.min(centerRadiusMax, centerRadius); - } - - - final int CENTER_SHIFT = 2; + if (centerRadiusMax != 0) + { + centerRadius = Math.min(centerRadiusMax, centerRadius); + } + + final int CENTER_SHIFT = 2; generateSphere2(world, x, y, z, centerRadius, true, -1, false); - for (int i = 1; i <= asteroidSize; i++) { + for (int i = 1; i <= asteroidSize; i++) + { int radius = 2 + world.rand.nextInt(centerRadius); - int newX = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); int newY = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); int newZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - generateSphere2(world, newX, newY, newZ, radius, true, -1, false); } } - + /** * Sphere generator * @param world target world @@ -420,66 +434,92 @@ public class SpaceWorldGenerator implements IWorldGenerator { * @param radius sphere radius * @param corrupted skip random blocks when generating (corrupted effect) * @param forcedID sphere of specified blocks or random blocks if not specified - * @return + * @return */ - public void generateSphere2(World world, int xCoord, int yCoord, int zCoord, double radius, boolean corrupted, int forcedID, boolean hollow) { - + public void generateSphere2(World world, int xCoord, int yCoord, int zCoord, double radius, boolean corrupted, int forcedID, boolean hollow) + { radius += 0.5D; // Radius from center of block double radiusSq = radius * radius; // Optimization to avoid sqrts... double radius1Sq = (radius - 1.0D) * (radius - 1.0D); // for hollow sphere - int ceilRadius = (int) Math.ceil(radius); - + // Pass the cube and check points for sphere equation x^2 + y^2 + z^2 = r^2 - for (int x = 0; x <= ceilRadius; x++) { - for (int y = 0; y <= ceilRadius; y++) { - for (int z = 0; z <= ceilRadius; z++) { + for (int x = 0; x <= ceilRadius; x++) + { + for (int y = 0; y <= ceilRadius; y++) + { + for (int z = 0; z <= ceilRadius; z++) + { double dSq = lengthSq(x, y, z); // Distance from current position to center // Skip too far blocks - if (dSq > radiusSq) { + if (dSq > radiusSq) + { continue; } // Hollow sphere condition if ((hollow) && ( - (dSq < radius1Sq) || ((lengthSq(x + 1, y, z) <= radiusSq) && (lengthSq(x, y + 1, z) <= radiusSq) && (lengthSq(x, y, z + 1) <= radiusSq)))) + (dSq < radius1Sq) || ((lengthSq(x + 1, y, z) <= radiusSq) && (lengthSq(x, y + 1, z) <= radiusSq) && (lengthSq(x, y, z + 1) <= radiusSq)))) { - continue; + continue; } - // Place blocks int blockID, meta = 0; - + if (!corrupted || world.rand.nextInt(10) != 1) { blockID = (forcedID == -1) ? getRandomSurfaceBlockID(world.rand, corrupted, false) : forcedID; - if (blockID == 39701) { meta = 1; blockID = 3970; } + + if (blockID == 39701) + { + meta = 1; + blockID = 3970; + } + world.setBlock(xCoord + x, yCoord + y, zCoord + z, blockID, meta, 2); world.setBlock(xCoord - x, yCoord + y, zCoord + z, blockID, meta, 2); } - + if (!corrupted || world.rand.nextInt(10) != 1) - { + { blockID = (forcedID == -1) ? getRandomSurfaceBlockID(world.rand, corrupted, false) : forcedID; - if (blockID == 39701) { meta = 1; blockID = 3970; } + + if (blockID == 39701) + { + meta = 1; + blockID = 3970; + } + world.setBlock(xCoord + x, yCoord - y, zCoord + z, blockID, meta, 2); world.setBlock(xCoord + x, yCoord + y, zCoord - z, blockID, meta, 2); } - + if (!corrupted || world.rand.nextInt(10) != 1) - { + { blockID = (forcedID == -1) ? getRandomSurfaceBlockID(world.rand, corrupted, false) : forcedID; - if (blockID == 39701) { meta = 1; blockID = 3970; } + + if (blockID == 39701) + { + meta = 1; + blockID = 3970; + } + world.setBlock(xCoord - x, yCoord - y, zCoord + z, blockID, meta, 2); world.setBlock(xCoord + x, yCoord - y, zCoord - z, blockID, meta, 2); } - + if (!corrupted || world.rand.nextInt(10) != 1) - { + { blockID = (forcedID == -1) ? getRandomSurfaceBlockID(world.rand, corrupted, false) : forcedID; - if (blockID == 39701) { meta = 1; blockID = 3970; } + + if (blockID == 39701) + { + meta = 1; + blockID = 3970; + } + world.setBlock(xCoord - x, yCoord + y, zCoord - z, blockID, meta, 2); world.setBlock(xCoord - x, yCoord - y, zCoord - z, blockID, meta, 2); } @@ -488,32 +528,43 @@ public class SpaceWorldGenerator implements IWorldGenerator { } } - private static double lengthSq(double x, double y, double z) { + private static double lengthSq(double x, double y, double z) + { return (x * x) + (y * y) + (z * z); } - public int getRandomSurfaceBlockID(Random random, boolean corrupted, boolean nocobble) { + public int getRandomSurfaceBlockID(Random random, boolean corrupted, boolean nocobble) + { List<Integer> ores = TileEntityMiningLaser.valuableOres; + if (isICBMLoaded) { ores.add(3880); ores.add(3970); ores.add(39701); } + int blockID = Block.stone.blockID; - if (corrupted) { + + if (corrupted) + { blockID = Block.cobblestone.blockID; } - if (random.nextInt(25) == 5 || nocobble) { + if (random.nextInt(25) == 5 || nocobble) + { blockID = ores.get(random.nextInt(ores.size())); - } - else if (random.nextInt(350) == 1 && isAELoaded) { + } + else if (random.nextInt(350) == 1 && isAELoaded) + { blockID = 902; // quarz (AE) } - else if (random.nextInt(500) == 1) { + else if (random.nextInt(500) == 1) + { blockID = Block.oreDiamond.blockID; - } else if (random.nextInt(10000) == 42) { + } + else if (random.nextInt(10000) == 42) + { blockID = WarpDrive.instance.config.iridiumID; } diff --git a/src/cr0s/WarpDrive/TileEntityAirGenerator.java b/src/cr0s/WarpDrive/TileEntityAirGenerator.java index 5e7ea59e..363274ce 100644 --- a/src/cr0s/WarpDrive/TileEntityAirGenerator.java +++ b/src/cr0s/WarpDrive/TileEntityAirGenerator.java @@ -1,8 +1,7 @@ package cr0s.WarpDrive; import cpw.mods.fml.common.FMLCommonHandler; -import cr0s.WarpDrive.WarpDrive; -import ic2.api.Direction; +import net.minecraftforge.common.ForgeDirection; import ic2.api.energy.event.EnergyTileLoadEvent; import ic2.api.energy.event.EnergyTileUnloadEvent; import ic2.api.energy.tile.IEnergySink; @@ -10,109 +9,126 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.MinecraftForge; -public class TileEntityAirGenerator extends TileEntity implements IEnergySink { - +public class TileEntityAirGenerator extends TileEntity implements IEnergySink +{ public boolean addedToEnergyNet = false; - + private final int EU_PER_AIRBLOCK = 10; private final int MAX_ENERGY_VALUE = 36 * EU_PER_AIRBLOCK; private int currentEnergyValue = 0; private int cooldownTicks = 0; private final float AIR_POLLUTION_INTERVAL = 10; - + private final int START_CONCENTRATION_VALUE = 15; @Override - public void updateEntity() { - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { + public void updateEntity() + { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { return; } - - if (!addedToEnergyNet && !this.tileEntityInvalid) { + + if (!addedToEnergyNet && !this.tileEntityInvalid) + { MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this)); addedToEnergyNet = true; } - + // Air generator works only in spaces - if (worldObj.provider.dimensionId != WarpDrive.instance.spaceDimID && worldObj.provider.dimensionId != WarpDrive.instance.hyperSpaceDimID) { + if (worldObj.provider.dimensionId != WarpDrive.instance.spaceDimID && worldObj.provider.dimensionId != WarpDrive.instance.hyperSpaceDimID) + { return; } - if (addedToEnergyNet && currentEnergyValue > EU_PER_AIRBLOCK) { - if (cooldownTicks++ > AIR_POLLUTION_INTERVAL) { + if (addedToEnergyNet && currentEnergyValue > EU_PER_AIRBLOCK) + { + if (cooldownTicks++ > AIR_POLLUTION_INTERVAL) + { cooldownTicks = 0; worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1, 2); // set enabled texture - releaseAir(); } - } else + } + else { - if (cooldownTicks++ > 20) { + if (cooldownTicks++ > 20) + { worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 2); // set disabled texture cooldownTicks = 0; } } } - - private void releaseAir() { - if (worldObj.isAirBlock(xCoord + 1, yCoord, zCoord) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) { + + private void releaseAir() + { + if (worldObj.isAirBlock(xCoord + 1, yCoord, zCoord) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) + { worldObj.setBlock(xCoord + 1, yCoord, zCoord, WarpDrive.instance.config.airID, START_CONCENTRATION_VALUE, 2); currentEnergyValue -= EU_PER_AIRBLOCK; } - - if (worldObj.isAirBlock(xCoord - 1, yCoord, zCoord) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) { + + if (worldObj.isAirBlock(xCoord - 1, yCoord, zCoord) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) + { worldObj.setBlock(xCoord - 1, yCoord, zCoord, WarpDrive.instance.config.airID, START_CONCENTRATION_VALUE, 2); currentEnergyValue -= EU_PER_AIRBLOCK; } - - if (worldObj.isAirBlock(xCoord, yCoord + 1, zCoord) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) { + + if (worldObj.isAirBlock(xCoord, yCoord + 1, zCoord) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) + { worldObj.setBlock(xCoord, yCoord + 1, zCoord, WarpDrive.instance.config.airID, START_CONCENTRATION_VALUE, 2); currentEnergyValue -= EU_PER_AIRBLOCK; } - - if (worldObj.isAirBlock(xCoord, yCoord - 1, zCoord) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) { + + if (worldObj.isAirBlock(xCoord, yCoord - 1, zCoord) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) + { worldObj.setBlock(xCoord, yCoord - 1, zCoord, WarpDrive.instance.config.airID, START_CONCENTRATION_VALUE, 2); currentEnergyValue -= EU_PER_AIRBLOCK; - } - - if (worldObj.isAirBlock(xCoord, yCoord, zCoord + 1) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) { + } + + if (worldObj.isAirBlock(xCoord, yCoord, zCoord + 1) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) + { worldObj.setBlock(xCoord, yCoord, zCoord + 1, WarpDrive.instance.config.airID, START_CONCENTRATION_VALUE, 2); currentEnergyValue -= EU_PER_AIRBLOCK; } - - if (worldObj.isAirBlock(xCoord, yCoord, zCoord - 1) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) { + + if (worldObj.isAirBlock(xCoord, yCoord, zCoord - 1) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) + { worldObj.setBlock(xCoord, yCoord, zCoord - 1, WarpDrive.instance.config.airID, START_CONCENTRATION_VALUE, 2); currentEnergyValue -= EU_PER_AIRBLOCK; - } + } } - + @Override - public void readFromNBT(NBTTagCompound tag) { + public void readFromNBT(NBTTagCompound tag) + { super.readFromNBT(tag); - this.currentEnergyValue = tag.getInteger("energy"); } @Override - public void writeToNBT(NBTTagCompound tag) { + public void writeToNBT(NBTTagCompound tag) + { super.writeToNBT(tag); - tag.setInteger("energy", this.getCurrentEnergyValue()); - } - + } + // IEnergySink methods implementation @Override - public int demandsEnergy() { + public double demandedEnergyUnits() + { return (MAX_ENERGY_VALUE - currentEnergyValue); } @Override - public int injectEnergy(Direction directionFrom, int amount) { - int leftover = 0; + public double injectEnergyUnits(ForgeDirection directionFrom, double amount) + { + double leftover = 0; + currentEnergyValue += Math.round(amount); - currentEnergyValue += amount; - if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) { + if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) + { leftover = (getCurrentEnergyValue() - MAX_ENERGY_VALUE); currentEnergyValue = MAX_ENERGY_VALUE; } @@ -121,42 +137,44 @@ public class TileEntityAirGenerator extends TileEntity implements IEnergySink { } @Override - public int getMaxSafeInput() { + public int getMaxSafeInput() + { return Integer.MAX_VALUE; } @Override - public boolean acceptsEnergyFrom(TileEntity emitter, Direction direction) { + public boolean acceptsEnergyFrom(TileEntity emitter, ForgeDirection direction) + { return true; } - @Override - public boolean isAddedToEnergyNet() { - return addedToEnergyNet; - } - /** * @return the currentEnergyValue */ - public int getCurrentEnergyValue() { + public int getCurrentEnergyValue() + { return currentEnergyValue; } - @Override - public void onChunkUnload() { - if (addedToEnergyNet) { + @Override + public void onChunkUnload() + { + if (addedToEnergyNet) + { MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); addedToEnergyNet = false; - } + } } - - @Override - public void invalidate() { - if (addedToEnergyNet) { + + @Override + public void invalidate() + { + if (addedToEnergyNet) + { MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); addedToEnergyNet = false; - } - + } + super.invalidate(); } } diff --git a/src/cr0s/WarpDrive/TileEntityCamera.java b/src/cr0s/WarpDrive/TileEntityCamera.java index 4413270f..23c48e0b 100644 --- a/src/cr0s/WarpDrive/TileEntityCamera.java +++ b/src/cr0s/WarpDrive/TileEntityCamera.java @@ -1,18 +1,11 @@ package cr0s.WarpDrive; -import cr0s.WarpDrive.TileEntityReactor; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.WarpDrive; import dan200.computer.api.IComputerAccess; import dan200.computer.api.ILuaContext; import dan200.computer.api.IPeripheral; -import ic2.api.Direction; -import ic2.api.energy.event.EnergyTileLoadEvent; -import ic2.api.energy.event.EnergyTileUnloadEvent; -import ic2.api.energy.tile.IEnergySink; -import ic2.api.item.Items; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -39,130 +32,149 @@ import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.MinecraftForge; -public class TileEntityCamera extends TileEntity implements IPeripheral{ - private int dx, dz, dy; - private float yaw, pitch; // laser direction - - private int frequency = -1; // beam frequency - private float r, g, b; // beam color (corresponds to frequency) - - private boolean isEmitting = false; - - private String[] methodsArray = { - "setFrequency", // 0 - "getFrequency" - }; - +public class TileEntityCamera extends TileEntity implements IPeripheral +{ + private int dx, dz, dy; + private float yaw, pitch; // laser direction + + private int frequency = -1; // beam frequency + private float r, g, b; // beam color (corresponds to frequency) + + private boolean isEmitting = false; + + private String[] methodsArray = + { + "setFrequency", // 0 + "getFrequency" + }; private final int REGISTRY_UPDATE_INTERVAL_SEC = 10; private int ticks = 0; - + private int packetSendTicks = 20; - + @Override - public void updateEntity() { - // Update frequency on clients - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { - if (packetSendTicks-- == 0) { - packetSendTicks = 20 * 5; - sendFreqPacket(); - } - - return; - } - - if (++ticks > 20 * REGISTRY_UPDATE_INTERVAL_SEC) { - ticks = 0; - WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(this.frequency, new ChunkPosition(xCoord, yCoord, zCoord), worldObj).setType(0)); - } + public void updateEntity() + { + // Update frequency on clients + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) + { + if (packetSendTicks-- == 0) + { + packetSendTicks = 20 * 5; + sendFreqPacket(); + } + + return; + } + + if (++ticks > 20 * REGISTRY_UPDATE_INTERVAL_SEC) + { + ticks = 0; + WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(this.frequency, new ChunkPosition(xCoord, yCoord, zCoord), worldObj).setType(0)); + } } - - public int getFrequency() { - return frequency; + + public int getFrequency() + { + return frequency; } - - public void setFrequency(int freq) { - frequency = freq; - } - + + public void setFrequency(int freq) + { + frequency = freq; + } + @Override - public void readFromNBT(NBTTagCompound tag) { + public void readFromNBT(NBTTagCompound tag) + { super.readFromNBT(tag); - frequency = tag.getInteger("frequency"); } @Override - public void writeToNBT(NBTTagCompound tag) { + public void writeToNBT(NBTTagCompound tag) + { super.writeToNBT(tag); - tag.setInteger("frequency", frequency); - } - - public void sendFreqPacket() { + } + + public void sendFreqPacket() + { Side side = FMLCommonHandler.instance().getEffectiveSide(); - if (side == Side.SERVER) { + + if (side == Side.SERVER) + { ByteArrayOutputStream bos = new ByteArrayOutputStream(8); DataOutputStream outputStream = new DataOutputStream(bos); - try { + + try + { // Write source vector - outputStream.writeInt(xCoord); - outputStream.writeInt(yCoord); - outputStream.writeInt(zCoord); - - outputStream.writeInt(this.frequency); - } catch (Exception ex) { - ex.printStackTrace(); + outputStream.writeInt(xCoord); + outputStream.writeInt(yCoord); + outputStream.writeInt(zCoord); + outputStream.writeInt(this.frequency); } - + catch (Exception ex) + { + ex.printStackTrace(); + } + Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "WarpDriveFreq"; packet.data = bos.toByteArray(); packet.length = bos.size(); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(xCoord, yCoord, zCoord, 100, worldObj.provider.dimensionId, packet); + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(xCoord, yCoord, zCoord, 100, worldObj.provider.dimensionId, packet); } - } - + } + // IPeripheral methods implementation @Override - public String getType() { + public String getType() + { return "camera"; } @Override - public String[] getMethodNames() { + public String[] getMethodNames() + { return methodsArray; } @Override - public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception { - switch (method) { + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception + { + switch (method) + { case 0: // setFrequency - if (arguments.length == 1) { - frequency = ((Double)arguments[0]).intValue(); - } - break; - + if (arguments.length == 1) + { + frequency = ((Double)arguments[0]).intValue(); + } + + break; + case 1: - return new Object[] { (Integer)frequency }; - + return new Object[] { (Integer)frequency }; } - + return new Object[] { 0 }; - } - + } + @Override - public boolean canAttachToSide(int side) { + public boolean canAttachToSide(int side) + { return true; } @Override - public void attach(IComputerAccess computer) { - + public void attach(IComputerAccess computer) + { } @Override - public void detach(IComputerAccess computer) { - + public void detach(IComputerAccess computer) + { } } diff --git a/src/cr0s/WarpDrive/TileEntityLaser.java b/src/cr0s/WarpDrive/TileEntityLaser.java index a39b8eed..78b0df0b 100644 --- a/src/cr0s/WarpDrive/TileEntityLaser.java +++ b/src/cr0s/WarpDrive/TileEntityLaser.java @@ -1,18 +1,11 @@ package cr0s.WarpDrive; -import cr0s.WarpDrive.TileEntityReactor; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.WarpDrive; import dan200.computer.api.IComputerAccess; import dan200.computer.api.ILuaContext; import dan200.computer.api.IPeripheral; -import ic2.api.Direction; -import ic2.api.energy.event.EnergyTileLoadEvent; -import ic2.api.energy.event.EnergyTileUnloadEvent; -import ic2.api.energy.tile.IEnergySink; -import ic2.api.item.Items; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -39,265 +32,311 @@ import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.MinecraftForge; -public class TileEntityLaser extends TileEntity implements IPeripheral{ - private final int MAX_BOOSTERS_NUMBER = 10; - private final int MAX_LASER_ENERGY = 4000000; - - private int dx, dz, dy; - public float yaw, pitch; // laser direction - - private int frequency = -1; // beam frequency - public int camFreq = -1; // camera frequency - private float r, g, b; // beam color (corresponds to frequency) - - public boolean isEmitting = false; - - private String[] methodsArray = { - "emitBeam", // 0 - "getX", "getY", "getZ", // 1, 2, 3 - "setFrequency", // 4 - "getFirstHit", // 5 - "getBoosterDXDZ", // 6 - "setCamFrequency" // 7 - }; - - public int delayTicks = 0; - private int energyFromOtherBeams = 0; - - private MovingObjectPosition firstHit; +public class TileEntityLaser extends TileEntity implements IPeripheral +{ + private final int MAX_BOOSTERS_NUMBER = 10; + private final int MAX_LASER_ENERGY = 4000000; + + private int dx, dz, dy; + public float yaw, pitch; // laser direction + + private int frequency = -1; // beam frequency + public int camFreq = -1; // camera frequency + private float r, g, b; // beam color (corresponds to frequency) + + public boolean isEmitting = false; + + private String[] methodsArray = + { + "emitBeam", // 0 + "getX", "getY", "getZ", // 1, 2, 3 + "setFrequency", // 4 + "getFirstHit", // 5 + "getBoosterDXDZ", // 6 + "setCamFrequency" // 7 + }; + + public int delayTicks = 0; + private int energyFromOtherBeams = 0; + + private MovingObjectPosition firstHit; + + private int camUpdateTicks = 20; + private int registryUpdateTicks = 20 * 10; - private int camUpdateTicks = 20; - private int registryUpdateTicks = 20 * 10; - @Override - public void updateEntity() { - // Frequency is not set - if (frequency == -1) { - return; - } - - if (isWithCamera()) { - if (registryUpdateTicks-- == 0 && FMLCommonHandler.instance().getEffectiveSide().isClient()) { - registryUpdateTicks = 20 * 10; - - WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(this.camFreq, new ChunkPosition(xCoord, yCoord, zCoord), worldObj).setType(1)); - } - - if (camUpdateTicks-- == 0) { - - camUpdateTicks = 20 * 5; // 5 seconds - sendFreqPacket(); // send own cam frequency to clients - } - } - - if (isEmitting && ++delayTicks > 20 * 3) { - delayTicks = 0; - isEmitting = false; - emitBeam(Math.min(this.collectEnergyFromBoosters() + MathHelper.floor_double(energyFromOtherBeams * 0.60D), MAX_LASER_ENERGY)); - energyFromOtherBeams = 0; - } + public void updateEntity() + { + // Frequency is not set + if (frequency == -1) + { + return; + } + + if (isWithCamera()) + { + if (registryUpdateTicks-- == 0 && FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + registryUpdateTicks = 20 * 10; + WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(this.camFreq, new ChunkPosition(xCoord, yCoord, zCoord), worldObj).setType(1)); + } + + if (camUpdateTicks-- == 0) + { + camUpdateTicks = 20 * 5; // 5 seconds + sendFreqPacket(); // send own cam frequency to clients + } + } + + if (isEmitting && ++delayTicks > 20 * 3) + { + delayTicks = 0; + isEmitting = false; + emitBeam(Math.min(this.collectEnergyFromBoosters() + MathHelper.floor_double(energyFromOtherBeams * 0.60D), MAX_LASER_ENERGY)); + energyFromOtherBeams = 0; + } } - - public void addBeamEnergy(int amount) { - if (isEmitting) { - energyFromOtherBeams += amount; - System.out.println("[EL] Added energy: " + amount); - } else { - System.out.println("[EL] Ignored energy: " + amount); - } + + public void addBeamEnergy(int amount) + { + if (isEmitting) + { + energyFromOtherBeams += amount; + System.out.println("[EL] Added energy: " + amount); + } + else + { + System.out.println("[EL] Ignored energy: " + amount); + } } - - private int collectEnergyFromBoosters() { - int energyCollected = 0; - - if (findFirstBooster() != null) { - for (int shift = 1; shift <= MAX_BOOSTERS_NUMBER; shift++) { - int newX = xCoord + (dx * shift); - int newY = yCoord + (dy * shift); - int newZ = zCoord + (dz * shift); - - TileEntity te = worldObj.getBlockTileEntity(newX, newY, newZ); - - if (te != null && te instanceof TileEntityParticleBooster) { - energyCollected += ((TileEntityParticleBooster)te).collectAllEnergy(); - } else { - break; - } - } - } - - return energyCollected; + + private int collectEnergyFromBoosters() + { + int energyCollected = 0; + + if (findFirstBooster() != null) + { + for (int shift = 1; shift <= MAX_BOOSTERS_NUMBER; shift++) + { + int newX = xCoord + (dx * shift); + int newY = yCoord + (dy * shift); + int newZ = zCoord + (dz * shift); + TileEntity te = worldObj.getBlockTileEntity(newX, newY, newZ); + + if (te != null && te instanceof TileEntityParticleBooster) + { + energyCollected += ((TileEntityParticleBooster)te).collectAllEnergy(); + } + else + { + break; + } + } + } + + return energyCollected; } - + // TODO refactor me - private void emitBeam(int energy) { - // Beam power calculations - int beamLengthBlocks = energy / 5000; - - System.out.println("Energy: " + energy + " | beamLengthBlocks: " + beamLengthBlocks); - - if (energy == 0 || beamLengthBlocks < 1) { - return; - } - - Vector3 beamVector = new Vector3(this).add(0.5); - System.out.println("beamVector: " + beamVector); - - float yawz = MathHelper.cos(-yaw * 0.017453292F - (float) Math.PI); + private void emitBeam(int energy) + { + // Beam power calculations + int beamLengthBlocks = energy / 5000; + System.out.println("Energy: " + energy + " | beamLengthBlocks: " + beamLengthBlocks); + + if (energy == 0 || beamLengthBlocks < 1) + { + return; + } + + Vector3 beamVector = new Vector3(this).add(0.5); + System.out.println("beamVector: " + beamVector); + float yawz = MathHelper.cos(-yaw * 0.017453292F - (float) Math.PI); float yawx = MathHelper.sin(-yaw * 0.017453292F - (float) Math.PI); float pitchhorizontal = -MathHelper.cos(-pitch * 0.017453292F); float pitchvertical = MathHelper.sin(-pitch * 0.017453292F); float directionx = yawx * pitchhorizontal; float directionz = yawz * pitchhorizontal; Vector3 lookVector = new Vector3((double) directionx, (double) pitchvertical, (double) directionz); - Vector3.translate(beamVector, lookVector); - - Vector3 reachPoint = beamVector.clone().translate(beamVector.clone(), beamVector.clone().scale(lookVector.clone(), beamLengthBlocks)); - - System.out.println("Look vector: " + lookVector); - System.out.println("reachPoint: " + reachPoint); - System.out.println("translatedBeamVector: " + beamVector); - Vector3 endPoint = reachPoint.clone(); - - playSoundCorrespondsEnergy(energy); - - // This is scanning beam, do not deal damage to blocks - if (frequency == 1420) { - firstHit = worldObj.rayTraceBlocks_do_do(beamVector.toVec3(), reachPoint.toVec3(), false, false); - if (firstHit != null) - sendLaserPacket(beamVector, new Vector3(firstHit), r, g, b, 50, energy, 200); - - return; - } - - for (int passedBlocks = 0; passedBlocks < beamLengthBlocks; ++passedBlocks) { - // Get next block hit - MovingObjectPosition hit = worldObj.rayTraceBlocks_do_do(beamVector.toVec3(), reachPoint.toVec3(), true, false); - - // FIXME entity ray-tracing - MovingObjectPosition entityHit = raytraceEntities(beamVector.clone(), lookVector.clone(), true, beamLengthBlocks); - if (entityHit == null) { - System.out.println("Entity hit is null."); - } else { - System.out.println("Entity hit: " + entityHit); - } - - if (entityHit != null && entityHit.entityHit instanceof EntityLivingBase) { - EntityLivingBase e = (EntityLivingBase)entityHit.entityHit; - double distanceToEntity = entityHit.hitVec.distanceTo(beamVector.clone().toVec3()); - if (hit == null || (hit != null && hit.hitVec.distanceTo(beamVector.clone().toVec3()) > distanceToEntity)) { - if (distanceToEntity <= beamLengthBlocks) { - ((EntityLivingBase)e).setFire(100); - ((EntityLivingBase)e).attackEntityFrom(DamageSource.inFire, energy / 10000); - if (energy > 1000000) { - worldObj.newExplosion(null, e.posX, e.posY, e.posZ, 4F, true, true); - } - - // consume energy - energy -= 10000 + (10 * distanceToEntity); - - endPoint = new Vector3(entityHit.hitVec); - break; - } - } - } - - // Laser is missed - if (hit == null && entityHit == null) { - endPoint = reachPoint; - break; - } else if (hit != null) { - // We got a hit block - int distance = (int) new Vector3(hit.hitVec).distanceTo(beamVector); - - // Laser gone too far - if (distance >= beamLengthBlocks) { - endPoint = reachPoint; - break; - } - - int blockID = worldObj.getBlockId(hit.blockX, hit.blockY, hit.blockZ); - int blockMeta = worldObj.getBlockMetadata(hit.blockX, hit.blockY, hit.blockZ); - float resistance = Block.blocksList[blockID].blockResistance; - - if (blockID == Block.bedrock.blockID) { - endPoint = new Vector3(hit.hitVec); - break; - } - - // Hit is a laser head - if (blockID == WarpDrive.instance.config.laserID || blockID == WarpDrive.instance.config.laserCamID) { - // Compare frequencies - TileEntityLaser tel = (TileEntityLaser)worldObj.getBlockTileEntity(hit.blockX, hit.blockY, hit.blockZ); - if (tel != null && tel.getFrequency() == frequency) { - tel.addBeamEnergy(energy); - endPoint = new Vector3(hit.hitVec); - break; - } - } - - if (Block.blocksList[blockID].blockMaterial == Material.glass) { - worldObj.destroyBlock(hit.blockX, hit.blockY, hit.blockZ, (worldObj.rand.nextInt(20) == 0)); - endPoint = new Vector3(hit.hitVec); - } - - energy -= 70000 + (resistance * 1000) + (distance * 10); - endPoint = new Vector3(hit.hitVec); - - if (energy <= 0) { - break; - } - - - if (resistance >= Block.obsidian.blockResistance) { - worldObj.newExplosion(null, hit.blockX, hit.blockY, hit.blockZ, 4F * (2 + (energy / 500000)), true, true); - worldObj.setBlock(hit.blockX, hit.blockY, hit.blockZ, (worldObj.rand.nextBoolean()) ? Block.fire.blockID : 0); - } else{ - worldObj.destroyBlock(hit.blockX, hit.blockY, hit.blockZ, (worldObj.rand.nextInt(20) == 0)); - } - } - } - - sendLaserPacket(beamVector, endPoint, r, g, b, 50, energy, beamLengthBlocks); - } - - public MovingObjectPosition raytraceEntities(Vector3 beamVec, Vector3 lookVec, boolean collisionFlag, double reachDistance) { + Vector3.translate(beamVector, lookVector); + Vector3 reachPoint = beamVector.clone().translate(beamVector.clone(), beamVector.clone().scale(lookVector.clone(), beamLengthBlocks)); + System.out.println("Look vector: " + lookVector); + System.out.println("reachPoint: " + reachPoint); + System.out.println("translatedBeamVector: " + beamVector); + Vector3 endPoint = reachPoint.clone(); + playSoundCorrespondsEnergy(energy); + // This is scanning beam, do not deal damage to blocks + if (frequency == 1420) + { + firstHit = worldObj.rayTraceBlocks_do_do(beamVector.toVec3(), reachPoint.toVec3(), false, false); + + if (firstHit != null) + { + sendLaserPacket(beamVector, new Vector3(firstHit), r, g, b, 50, energy, 200); + } + + return; + } + + for (int passedBlocks = 0; passedBlocks < beamLengthBlocks; ++passedBlocks) + { + // Get next block hit + MovingObjectPosition hit = worldObj.rayTraceBlocks_do_do(beamVector.toVec3(), reachPoint.toVec3(), true, false); + // FIXME entity ray-tracing + MovingObjectPosition entityHit = raytraceEntities(beamVector.clone(), lookVector.clone(), true, beamLengthBlocks); + + if (entityHit == null) + { + System.out.println("Entity hit is null."); + } + else + { + System.out.println("Entity hit: " + entityHit); + } + + if (entityHit != null && entityHit.entityHit instanceof EntityLivingBase) + { + EntityLivingBase e = (EntityLivingBase)entityHit.entityHit; + double distanceToEntity = entityHit.hitVec.distanceTo(beamVector.clone().toVec3()); + + if (hit == null || (hit != null && hit.hitVec.distanceTo(beamVector.clone().toVec3()) > distanceToEntity)) + { + if (distanceToEntity <= beamLengthBlocks) + { + ((EntityLivingBase)e).setFire(100); + ((EntityLivingBase)e).attackEntityFrom(DamageSource.inFire, energy / 10000); + + if (energy > 1000000) + { + worldObj.newExplosion(null, e.posX, e.posY, e.posZ, 4F, true, true); + } + + // consume energy + energy -= 10000 + (10 * distanceToEntity); + endPoint = new Vector3(entityHit.hitVec); + break; + } + } + } + + // Laser is missed + if (hit == null && entityHit == null) + { + endPoint = reachPoint; + break; + } + else if (hit != null) + { + // We got a hit block + int distance = (int) new Vector3(hit.hitVec).distanceTo(beamVector); + + // Laser gone too far + if (distance >= beamLengthBlocks) + { + endPoint = reachPoint; + break; + } + + int blockID = worldObj.getBlockId(hit.blockX, hit.blockY, hit.blockZ); + int blockMeta = worldObj.getBlockMetadata(hit.blockX, hit.blockY, hit.blockZ); + float resistance = Block.blocksList[blockID].blockResistance; + + if (blockID == Block.bedrock.blockID) + { + endPoint = new Vector3(hit.hitVec); + break; + } + + // Hit is a laser head + if (blockID == WarpDrive.instance.config.laserID || blockID == WarpDrive.instance.config.laserCamID) + { + // Compare frequencies + TileEntityLaser tel = (TileEntityLaser)worldObj.getBlockTileEntity(hit.blockX, hit.blockY, hit.blockZ); + + if (tel != null && tel.getFrequency() == frequency) + { + tel.addBeamEnergy(energy); + endPoint = new Vector3(hit.hitVec); + break; + } + } + + if (Block.blocksList[blockID].blockMaterial == Material.glass) + { + worldObj.destroyBlock(hit.blockX, hit.blockY, hit.blockZ, (worldObj.rand.nextInt(20) == 0)); + endPoint = new Vector3(hit.hitVec); + } + + energy -= 70000 + (resistance * 1000) + (distance * 10); + endPoint = new Vector3(hit.hitVec); + + if (energy <= 0) + { + break; + } + + if (resistance >= Block.obsidian.blockResistance) + { + worldObj.newExplosion(null, hit.blockX, hit.blockY, hit.blockZ, 4F * (2 + (energy / 500000)), true, true); + worldObj.setBlock(hit.blockX, hit.blockY, hit.blockZ, (worldObj.rand.nextBoolean()) ? Block.fire.blockID : 0); + } + else + { + worldObj.destroyBlock(hit.blockX, hit.blockY, hit.blockZ, (worldObj.rand.nextInt(20) == 0)); + } + } + } + + sendLaserPacket(beamVector, endPoint, r, g, b, 50, energy, beamLengthBlocks); + } + + public MovingObjectPosition raytraceEntities(Vector3 beamVec, Vector3 lookVec, boolean collisionFlag, double reachDistance) + { MovingObjectPosition pickedEntity = null; Vec3 playerPosition = beamVec.toVec3(); Vec3 playerLook = lookVec.toVec3(); - Vec3 playerViewOffset = Vec3.createVectorHelper(playerPosition.xCoord + playerLook.xCoord * reachDistance, playerPosition.yCoord - + playerLook.yCoord * reachDistance, playerPosition.zCoord + playerLook.zCoord * reachDistance); - + + playerLook.yCoord * reachDistance, playerPosition.zCoord + playerLook.zCoord * reachDistance); double playerBorder = 1.1 * reachDistance; AxisAlignedBB boxToScan = WarpDrive.laserBlock.getCollisionBoundingBoxFromPool(worldObj, xCoord, yCoord, zCoord).expand(playerBorder, playerBorder, playerBorder); - List entitiesHit = worldObj.getEntitiesWithinAABBExcludingEntity(null, boxToScan); double closestEntity = reachDistance; - if (entitiesHit == null || entitiesHit.isEmpty()) { + if (entitiesHit == null || entitiesHit.isEmpty()) + { return null; } - for (Entity entityHit : (Iterable<Entity>) entitiesHit) { - if (entityHit != null && entityHit.canBeCollidedWith() && entityHit.boundingBox != null) { + + for (Entity entityHit : (Iterable<Entity>) entitiesHit) + { + if (entityHit != null && entityHit.canBeCollidedWith() && entityHit.boundingBox != null) + { float border = entityHit.getCollisionBorderSize(); AxisAlignedBB aabb = entityHit.boundingBox.expand((double) border, (double) border, (double) border); MovingObjectPosition hitMOP = aabb.calculateIntercept(playerPosition, playerViewOffset); - if (hitMOP != null) { - if (aabb.isVecInside(playerPosition)) { - if (0.0D < closestEntity || closestEntity == 0.0D) { + if (hitMOP != null) + { + if (aabb.isVecInside(playerPosition)) + { + if (0.0D < closestEntity || closestEntity == 0.0D) + { pickedEntity = new MovingObjectPosition(entityHit); - if (pickedEntity != null) { + + if (pickedEntity != null) + { pickedEntity.hitVec = hitMOP.hitVec; closestEntity = 0.0D; } } - } else { + } + else + { double distance = playerPosition.distanceTo(hitMOP.hitVec); - if (distance < closestEntity || closestEntity == 0.0D) { + if (distance < closestEntity || closestEntity == 0.0D) + { pickedEntity = new MovingObjectPosition(entityHit); pickedEntity.hitVec = hitMOP.hitVec; closestEntity = distance; @@ -306,22 +345,27 @@ public class TileEntityLaser extends TileEntity implements IPeripheral{ } } } - return pickedEntity; - } - - public boolean isWithCamera() { - return (worldObj.getBlockId(xCoord, yCoord, zCoord) == WarpDrive.instance.config.laserCamID); - } - - public int getFrequency() { - return frequency; - } - - private TileEntityParticleBooster findFirstBooster() { - TileEntity result; + return pickedEntity; + } + + public boolean isWithCamera() + { + return (worldObj.getBlockId(xCoord, yCoord, zCoord) == WarpDrive.instance.config.laserCamID); + } + + public int getFrequency() + { + return frequency; + } + + private TileEntityParticleBooster findFirstBooster() + { + TileEntity result; result = worldObj.getBlockTileEntity(xCoord + 1, yCoord, zCoord); - if (result != null && result instanceof TileEntityParticleBooster) { + + if (result != null && result instanceof TileEntityParticleBooster) + { dx = 1; dz = 0; dy = 0; @@ -329,7 +373,9 @@ public class TileEntityLaser extends TileEntity implements IPeripheral{ } result = worldObj.getBlockTileEntity(xCoord - 1, yCoord, zCoord); - if (result != null && result instanceof TileEntityParticleBooster) { + + if (result != null && result instanceof TileEntityParticleBooster) + { dx = -1; dz = 0; dy = 0; @@ -337,304 +383,356 @@ public class TileEntityLaser extends TileEntity implements IPeripheral{ } result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord + 1); - if (result != null && result instanceof TileEntityParticleBooster) { - dx = 0; + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = 0; dz = 1; dy = 0; return (TileEntityParticleBooster) result; } result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord - 1); - if (result != null && result instanceof TileEntityParticleBooster) { + + if (result != null && result instanceof TileEntityParticleBooster) + { dx = 0; dz = -1; dy = 0; return (TileEntityParticleBooster) result; } - + result = worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord); - if (result != null && result instanceof TileEntityParticleBooster) { - dx = 0; + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = 0; dz = 0; dy = 1; return (TileEntityParticleBooster) result; } result = worldObj.getBlockTileEntity(xCoord, yCoord - 1, zCoord); - if (result != null && result instanceof TileEntityParticleBooster) { + + if (result != null && result instanceof TileEntityParticleBooster) + { dx = 0; dz = 0; dy = -1; return (TileEntityParticleBooster) result; - } + } return null; } - - public void sendLaserPacket(Vector3 source, Vector3 dest, float r, float g, float b, int age, int energy, int radius) { + + public void sendLaserPacket(Vector3 source, Vector3 dest, float r, float g, float b, int age, int energy, int radius) + { Side side = FMLCommonHandler.instance().getEffectiveSide(); - if (side == Side.SERVER) { + + if (side == Side.SERVER) + { ByteArrayOutputStream bos = new ByteArrayOutputStream(8); DataOutputStream outputStream = new DataOutputStream(bos); - try { + + try + { // Write source vector - outputStream.writeDouble(source.x); - outputStream.writeDouble(source.y); - outputStream.writeDouble(source.z); - - // Write target vector - outputStream.writeDouble(dest.x); - outputStream.writeDouble(dest.y); - outputStream.writeDouble(dest.z); - - // Write r, g, b of laser - outputStream.writeFloat(r); - outputStream.writeFloat(g); - outputStream.writeFloat(b); - - // Write age - outputStream.writeByte(age); - - // Write energy value - outputStream.writeInt(energy); - } catch (Exception ex) { - ex.printStackTrace(); + outputStream.writeDouble(source.x); + outputStream.writeDouble(source.y); + outputStream.writeDouble(source.z); + // Write target vector + outputStream.writeDouble(dest.x); + outputStream.writeDouble(dest.y); + outputStream.writeDouble(dest.z); + // Write r, g, b of laser + outputStream.writeFloat(r); + outputStream.writeFloat(g); + outputStream.writeFloat(b); + // Write age + outputStream.writeByte(age); + // Write energy value + outputStream.writeInt(energy); } - + catch (Exception ex) + { + ex.printStackTrace(); + } + Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "WarpDriveBeam"; packet.data = bos.toByteArray(); packet.length = bos.size(); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(source.intX(), source.intY(), source.intZ(), radius, worldObj.provider.dimensionId, packet); - - ByteArrayOutputStream bos2 = new ByteArrayOutputStream(8); + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(source.intX(), source.intY(), source.intZ(), radius, worldObj.provider.dimensionId, packet); + ByteArrayOutputStream bos2 = new ByteArrayOutputStream(8); DataOutputStream outputStream2 = new DataOutputStream(bos2); - try { + + try + { // Write source vector - outputStream2.writeDouble(source.x); - outputStream2.writeDouble(source.y); - outputStream2.writeDouble(source.z); - - // Write target vector - outputStream2.writeDouble(dest.x); - outputStream2.writeDouble(dest.y); - outputStream2.writeDouble(dest.z); - - // Write r, g, b of laser - outputStream2.writeFloat(r); - outputStream2.writeFloat(g); - outputStream2.writeFloat(b); - - // Write age - outputStream2.writeByte(age); - - // Write energy value - outputStream2.writeInt(energy); - } catch (Exception ex) { - ex.printStackTrace(); + outputStream2.writeDouble(source.x); + outputStream2.writeDouble(source.y); + outputStream2.writeDouble(source.z); + // Write target vector + outputStream2.writeDouble(dest.x); + outputStream2.writeDouble(dest.y); + outputStream2.writeDouble(dest.z); + // Write r, g, b of laser + outputStream2.writeFloat(r); + outputStream2.writeFloat(g); + outputStream2.writeFloat(b); + // Write age + outputStream2.writeByte(age); + // Write energy value + outputStream2.writeInt(energy); } - + catch (Exception ex) + { + ex.printStackTrace(); + } + Packet250CustomPayload packet2 = new Packet250CustomPayload(); packet.channel = "WarpDriveBeam"; packet.data = bos.toByteArray(); packet.length = bos.size(); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(dest.intX(), dest.intY(), dest.intZ(), radius, worldObj.provider.dimensionId, packet); - } + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(dest.intX(), dest.intY(), dest.intZ(), radius, worldObj.provider.dimensionId, packet); + } } - - private void playSoundCorrespondsEnergy(int energy) { - if (energy <= 500000) { - worldObj.playSoundEffect(xCoord + 0.5f, yCoord - 0.5f, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F); - } else - if (energy > 500000 && energy <= 1000000) { - worldObj.playSoundEffect(xCoord + 0.5f, yCoord - 0.5f, zCoord + 0.5f, "warpdrive:midlaser", 4F, 1F); - } else if (energy > 1000000){ - worldObj.playSoundEffect(xCoord + 0.5f, yCoord - 0.5f, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); - } + + private void playSoundCorrespondsEnergy(int energy) + { + if (energy <= 500000) + { + worldObj.playSoundEffect(xCoord + 0.5f, yCoord - 0.5f, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F); + } + else if (energy > 500000 && energy <= 1000000) + { + worldObj.playSoundEffect(xCoord + 0.5f, yCoord - 0.5f, zCoord + 0.5f, "warpdrive:midlaser", 4F, 1F); + } + else if (energy > 1000000) + { + worldObj.playSoundEffect(xCoord + 0.5f, yCoord - 0.5f, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); + } } - - private boolean parseFrequency(int freq) { - if (freq > 65000 || freq < 0) { // Invalid frequency - r = 1; g = 0; b = 0; - return false; - } - - if (freq > 0 && freq < 10000) { // red - r = 1; g = 0; b = 0; - } else - if (freq > 10000 && freq <= 20000) { // orange - r = 1; g = 0; b = 0.5f; - } else - if (freq > 20000 && freq <= 30000) { // yellow - r = 1; g = 1; b = 0; - } else - if (freq > 30000 && freq <= 40000) { // green - r = 0; g = 1; b = 0; - } else - if (freq > 50000 && freq <= 60000) { // blue - r = 0; g = 0; b = 1; - } else - if (freq > 60000 && freq <= 65000) { // violet - r = 0.5f; g = 0; b = 0.5f; - } else { // impossible frequency - r = 1; g = 0; b = 0; - } - - return true; + + private boolean parseFrequency(int freq) + { + if (freq > 65000 || freq < 0) // Invalid frequency + { + r = 1; + g = 0; + b = 0; + return false; + } + + if (freq > 0 && freq < 10000) // red + { + r = 1; + g = 0; + b = 0; + } + else if (freq > 10000 && freq <= 20000) // orange + { + r = 1; + g = 0; + b = 0.5f; + } + else if (freq > 20000 && freq <= 30000) // yellow + { + r = 1; + g = 1; + b = 0; + } + else if (freq > 30000 && freq <= 40000) // green + { + r = 0; + g = 1; + b = 0; + } + else if (freq > 50000 && freq <= 60000) // blue + { + r = 0; + g = 0; + b = 1; + } + else if (freq > 60000 && freq <= 65000) // violet + { + r = 0.5f; + g = 0; + b = 0.5f; + } + else // impossible frequency + { + r = 1; + g = 0; + b = 0; + } + + return true; } - + @Override - public void readFromNBT(NBTTagCompound tag) { + public void readFromNBT(NBTTagCompound tag) + { super.readFromNBT(tag); - frequency = tag.getInteger("frequency"); camFreq = tag.getInteger("camfreq"); } @Override - public void writeToNBT(NBTTagCompound tag) { + public void writeToNBT(NBTTagCompound tag) + { super.writeToNBT(tag); - tag.setInteger("frequency", frequency); tag.setInteger("camFreq", camFreq); - } - + } + // IPeripheral methods implementation @Override - public String getType() { + public String getType() + { return "laser"; } @Override - public String[] getMethodNames() { + public String[] getMethodNames() + { return methodsArray; } @Override - public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception { - switch (method) { + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception + { + switch (method) + { case 0: // emitBeam(yaw, pitch) - // emitBeam(dx, dy, dz) - if (arguments.length == 2) { - yaw = ((Double)arguments[0]).floatValue(); - pitch = ((Double)arguments[1]).floatValue(); - - isEmitting = true; - delayTicks = 0; - } else - if (arguments.length == 3) { - double dx = (Double)arguments[0]; - double dy = (Double)arguments[1]; - double dz = (Double)arguments[2]; - - double targetX = xCoord + dx; - double targetY = yCoord + dy; - double targetZ = zCoord + dz; - - float xd = (float) (xCoord - targetX); - float yd = (float) (yCoord - targetY); - float zd = (float) (zCoord - targetZ); - - double var7 = MathHelper.sqrt_double(xd * xd + zd * zd); - - yaw = ((float) (Math.atan2(xd, zd) * 180.0D / 3.141592653589793D)); - pitch = ((float) (Math.atan2(yd, var7) * 180.0D / 3.141592653589793D)); - - isEmitting = true; - delayTicks = 0; + // emitBeam(dx, dy, dz) + if (arguments.length == 2) + { + yaw = ((Double)arguments[0]).floatValue(); + pitch = ((Double)arguments[1]).floatValue(); + isEmitting = true; + delayTicks = 0; } - + else if (arguments.length == 3) + { + double dx = (Double)arguments[0]; + double dy = (Double)arguments[1]; + double dz = (Double)arguments[2]; + double targetX = xCoord + dx; + double targetY = yCoord + dy; + double targetZ = zCoord + dz; + float xd = (float)(xCoord - targetX); + float yd = (float)(yCoord - targetY); + float zd = (float)(zCoord - targetZ); + double var7 = MathHelper.sqrt_double(xd * xd + zd * zd); + yaw = ((float)(Math.atan2(xd, zd) * 180.0D / Math.PI)); + pitch = ((float)(Math.atan2(yd, var7) * 180.0D / Math.PI)); + isEmitting = true; + delayTicks = 0; + } + return new Object[] { 0 }; - + case 1: // getX return new Integer[] { this.xCoord }; - case 2: // getY return new Integer[] { this.yCoord }; - case 3: // getZ return new Integer[] { this.zCoord }; - case 4: // setFrequency(freq) - if (arguments.length == 1) { - int freq = ((Double)arguments[0]).intValue(); - this.frequency = freq; - if (parseFrequency(freq)) { - return new Object[] { 0 }; - } else { - return new Object[] { -1 }; - } - } - + if (arguments.length == 1) + { + int freq = ((Double)arguments[0]).intValue(); + this.frequency = freq; + + if (parseFrequency(freq)) + { + return new Object[] { 0 }; + } + else + { + return new Object[] { -1 }; + } + } + case 5: // getFirstHit() - if (firstHit != null) { - int blockID = worldObj.getBlockId(firstHit.blockX, firstHit.blockY, firstHit.blockZ); - int blockMeta = worldObj.getBlockMetadata(firstHit.blockX, firstHit.blockY, firstHit.blockZ); - float blockResistance = Block.blocksList[blockID].blockResistance; - - Object[] info = { (Integer)firstHit.blockX, (Integer)firstHit.blockY, (Integer)firstHit.blockZ, blockID, blockMeta, (Float)blockResistance }; - firstHit = null; - - return info; - } else { - return new Object[] { -1, 0, 0, 0, 0, 0, -1 }; - } - + if (firstHit != null) + { + int blockID = worldObj.getBlockId(firstHit.blockX, firstHit.blockY, firstHit.blockZ); + int blockMeta = worldObj.getBlockMetadata(firstHit.blockX, firstHit.blockY, firstHit.blockZ); + float blockResistance = Block.blocksList[blockID].blockResistance; + Object[] info = { (Integer)firstHit.blockX, (Integer)firstHit.blockY, (Integer)firstHit.blockZ, blockID, blockMeta, (Float)blockResistance }; + firstHit = null; + return info; + } + else + { + return new Object[] { -1, 0, 0, 0, 0, 0, -1 }; + } + case 6: // getBoosterDXDZ - findFirstBooster(); - return new Object[] { (Integer)dx, (Integer)dz }; - + findFirstBooster(); + return new Object[] { (Integer)dx, (Integer)dz }; + case 7: // setCamFrequency (only for lasers with cam) - if (arguments.length == 1) { - if (isWithCamera()) { - int freq = ((Double)arguments[0]).intValue(); - this.camFreq = freq; - } - } - + if (arguments.length == 1) + { + if (isWithCamera()) + { + int freq = ((Double)arguments[0]).intValue(); + this.camFreq = freq; + } + } } - + return new Object[] { 0 }; } // Camera frequency refresh to clients packet - public void sendFreqPacket() { + public void sendFreqPacket() + { Side side = FMLCommonHandler.instance().getEffectiveSide(); - if (side == Side.SERVER) { + + if (side == Side.SERVER) + { ByteArrayOutputStream bos = new ByteArrayOutputStream(8); DataOutputStream outputStream = new DataOutputStream(bos); - try { + + try + { // Write source vector - outputStream.writeInt(xCoord); - outputStream.writeInt(yCoord); - outputStream.writeInt(zCoord); - - outputStream.writeInt(this.camFreq); - } catch (Exception ex) { - ex.printStackTrace(); + outputStream.writeInt(xCoord); + outputStream.writeInt(yCoord); + outputStream.writeInt(zCoord); + outputStream.writeInt(this.camFreq); } - + catch (Exception ex) + { + ex.printStackTrace(); + } + Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "WarpDriveFreq"; packet.data = bos.toByteArray(); packet.length = bos.size(); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(xCoord, yCoord, zCoord, 100, worldObj.provider.dimensionId, packet); + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(xCoord, yCoord, zCoord, 100, worldObj.provider.dimensionId, packet); } - } - + } + @Override - public boolean canAttachToSide(int side) { + public boolean canAttachToSide(int side) + { return true; } @Override - public void attach(IComputerAccess computer) { - + public void attach(IComputerAccess computer) + { } @Override - public void detach(IComputerAccess computer) { - + public void detach(IComputerAccess computer) + { } } diff --git a/src/cr0s/WarpDrive/TileEntityLift.java b/src/cr0s/WarpDrive/TileEntityLift.java index 6e0b0d71..e99f5aa4 100644 --- a/src/cr0s/WarpDrive/TileEntityLift.java +++ b/src/cr0s/WarpDrive/TileEntityLift.java @@ -1,14 +1,12 @@ package cr0s.WarpDrive; -import cr0s.WarpDrive.TileEntityReactor; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.WarpDrive; import dan200.computer.api.IComputerAccess; import dan200.computer.api.ILuaContext; import dan200.computer.api.IPeripheral; -import ic2.api.Direction; +import net.minecraftforge.common.ForgeDirection; import ic2.api.energy.event.EnergyTileLoadEvent; import ic2.api.energy.event.EnergyTileUnloadEvent; import ic2.api.energy.tile.IEnergySink; @@ -28,85 +26,101 @@ import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.DamageSource; import net.minecraftforge.common.MinecraftForge; -public class TileEntityLift extends TileEntity implements IEnergySink { - - public boolean addedToEnergyNet = false; - +public class TileEntityLift extends TileEntity implements IEnergySink +{ + public boolean addedToEnergyNet = false; + private final int MAX_ENERGY_VALUE = 2048; // eU private int currentEnergyValue = 0; - + private int mode = 0; // 0 - inactive, 1 - up, 2 - down private int firstUncoveredY; - + private boolean isEnabled = false; - + int ticks = 0; - + @Override - public void updateEntity() { + public void updateEntity() + { if (FMLCommonHandler.instance().getEffectiveSide().isClient()) - return; - - if (!addedToEnergyNet && !this.tileEntityInvalid) { + { + return; + } + + if (!addedToEnergyNet && !this.tileEntityInvalid) + { MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this)); addedToEnergyNet = true; } - - if (++ticks > 40) { - ticks = 0; - - // Switching mode - if (worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord)) { - mode = 2; // down - } else { - mode = 1; // up - } - - isEnabled = (worldObj.isAirBlock(xCoord, yCoord + 1, zCoord) && worldObj.isAirBlock(xCoord, yCoord + 2, zCoord)); - - if (currentEnergyValue != MAX_ENERGY_VALUE || !isEnabled) { - mode = 0; - worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 2); // disabled - return; - } - - worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, mode, 2); // current mode - - // Launch a beam - if (isEnabled) { + + if (++ticks > 40) + { + ticks = 0; + + // Switching mode + if (worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord)) + { + mode = 2; // down + } + else + { + mode = 1; // up + } + + isEnabled = (worldObj.isAirBlock(xCoord, yCoord + 1, zCoord) && worldObj.isAirBlock(xCoord, yCoord + 2, zCoord)); + + if (currentEnergyValue != MAX_ENERGY_VALUE || !isEnabled) + { + mode = 0; + worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 2); // disabled + return; + } + + worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, mode, 2); // current mode + + // Launch a beam + if (isEnabled) + { // Search non-air blocks under lift - for (int ny = yCoord - 1; ny > 0; ny--) { - if (!worldObj.isAirBlock(xCoord, ny, zCoord)) { + for (int ny = yCoord - 1; ny > 0; ny--) + { + if (!worldObj.isAirBlock(xCoord, ny, zCoord)) + { firstUncoveredY = ny; break; } - } - - if (yCoord - firstUncoveredY > 0) - if (mode == 1) { - sendLaserPacket(new Vector3(this).add(0.5), new Vector3(xCoord, firstUncoveredY, zCoord).add(0.5), 0f, 1f, 0f, 40, 0, 100); - } else if (mode == 2) { - sendLaserPacket(new Vector3(this).add(0.5), new Vector3(xCoord, firstUncoveredY, zCoord).add(0.5), 0f, 0f, 1f, 40, 0, 100); - } - - liftEntity(); + } + + if (yCoord - firstUncoveredY > 0) + if (mode == 1) + { + sendLaserPacket(new Vector3(this).add(0.5), new Vector3(xCoord, firstUncoveredY, zCoord).add(0.5), 0f, 1f, 0f, 40, 0, 100); + } + else if (mode == 2) + { + sendLaserPacket(new Vector3(this).add(0.5), new Vector3(xCoord, firstUncoveredY, zCoord).add(0.5), 0f, 0f, 1f, 40, 0, 100); + } + + liftEntity(); } } } - - public void liftEntity() { + + public void liftEntity() + { int xmax, zmax, x1, x2, z1, z2; int xmin, zmin; - final int CUBE_SIDE = 2; - x1 = xCoord + CUBE_SIDE / 2; x2 = xCoord - CUBE_SIDE / 2; - - if (x1 < x2) { + + if (x1 < x2) + { xmin = x1; xmax = x2; - } else + } + else { xmin = x2; xmax = x1; @@ -114,151 +128,163 @@ public class TileEntityLift extends TileEntity implements IEnergySink { z1 = zCoord + CUBE_SIDE / 2; z2 = zCoord - CUBE_SIDE / 2; - - if (z1 < z2) { + + if (z1 < z2) + { zmin = z1; zmax = z2; - } else + } + else { zmin = z2; zmax = z1; } - - // Lift up - if (mode == 1) { - AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(xmin + 0.3, firstUncoveredY, zmin + 0.3, xmax - 0.3, yCoord, zmax - 0.3); - - List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, aabb); - if (list != null) { // up - for (Object o : list) { - if (o != null && o instanceof EntityLivingBase) { - ((EntityLivingBase)o).setPositionAndUpdate(xCoord + 0.5f, yCoord + 1, zCoord + 0.5f); - sendLaserPacket(new Vector3(this).add(0.5), new Vector3(xCoord, firstUncoveredY, zCoord).add(0.5), 1, 1, 0, 40, 0, 100); - worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); - - currentEnergyValue = 0; - return; - } - } - } - } else if (mode == 2) { // down - AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(xmin + 0.3, yCoord, zmin + 0.3, xmax - 0.3, yCoord + 2, zmax - 0.3); - List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, aabb); - if (list != null) { - for (Object o : list) { - if (o != null && o instanceof EntityLivingBase) { - ((EntityLivingBase)o).setPositionAndUpdate(xCoord + 0.5f, firstUncoveredY + 1, zCoord + 0.5f); - - sendLaserPacket(new Vector3(this).add(0.5), new Vector3(xCoord, firstUncoveredY + 1, zCoord).add(0.5), 1, 1, 0, 40, 0, 100); - worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); - - currentEnergyValue = 0; - return; - } - } - } + // Lift up + if (mode == 1) + { + AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(xmin + 0.3, firstUncoveredY, zmin + 0.3, xmax - 0.3, yCoord, zmax - 0.3); + List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, aabb); + + if (list != null) // up + { + for (Object o : list) + { + if (o != null && o instanceof EntityLivingBase) + { + ((EntityLivingBase)o).setPositionAndUpdate(xCoord + 0.5f, yCoord + 1, zCoord + 0.5f); + sendLaserPacket(new Vector3(this).add(0.5), new Vector3(xCoord, firstUncoveredY, zCoord).add(0.5), 1, 1, 0, 40, 0, 100); + worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); + currentEnergyValue = 0; + return; + } + } + } + } + else if (mode == 2) // down + { + AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(xmin + 0.3, yCoord, zmin + 0.3, xmax - 0.3, yCoord + 2, zmax - 0.3); + List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, aabb); + + if (list != null) + { + for (Object o : list) + { + if (o != null && o instanceof EntityLivingBase) + { + ((EntityLivingBase)o).setPositionAndUpdate(xCoord + 0.5f, firstUncoveredY + 1, zCoord + 0.5f); + sendLaserPacket(new Vector3(this).add(0.5), new Vector3(xCoord, firstUncoveredY + 1, zCoord).add(0.5), 1, 1, 0, 40, 0, 100); + worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); + currentEnergyValue = 0; + return; + } + } + } } } - - public void sendLaserPacket(Vector3 source, Vector3 dest, float r, float g, float b, int age, int energy, int radius) { + + public void sendLaserPacket(Vector3 source, Vector3 dest, float r, float g, float b, int age, int energy, int radius) + { Side side = FMLCommonHandler.instance().getEffectiveSide(); - if (side == Side.SERVER) { + + if (side == Side.SERVER) + { ByteArrayOutputStream bos = new ByteArrayOutputStream(8); DataOutputStream outputStream = new DataOutputStream(bos); - try { + + try + { // Write source vector - outputStream.writeDouble(source.x); - outputStream.writeDouble(source.y); - outputStream.writeDouble(source.z); - - // Write target vector - outputStream.writeDouble(dest.x); - outputStream.writeDouble(dest.y); - outputStream.writeDouble(dest.z); - - // Write r, g, b of laser - outputStream.writeFloat(r); - outputStream.writeFloat(g); - outputStream.writeFloat(b); - - // Write age - outputStream.writeByte(age); - - // Write energy value - outputStream.writeInt(energy); - } catch (Exception ex) { - ex.printStackTrace(); + outputStream.writeDouble(source.x); + outputStream.writeDouble(source.y); + outputStream.writeDouble(source.z); + // Write target vector + outputStream.writeDouble(dest.x); + outputStream.writeDouble(dest.y); + outputStream.writeDouble(dest.z); + // Write r, g, b of laser + outputStream.writeFloat(r); + outputStream.writeFloat(g); + outputStream.writeFloat(b); + // Write age + outputStream.writeByte(age); + // Write energy value + outputStream.writeInt(energy); } - + catch (Exception ex) + { + ex.printStackTrace(); + } + Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "WarpDriveBeam"; packet.data = bos.toByteArray(); packet.length = bos.size(); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(source.intX(), source.intY(), source.intZ(), radius, worldObj.provider.dimensionId, packet); - - ByteArrayOutputStream bos2 = new ByteArrayOutputStream(8); + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(source.intX(), source.intY(), source.intZ(), radius, worldObj.provider.dimensionId, packet); + ByteArrayOutputStream bos2 = new ByteArrayOutputStream(8); DataOutputStream outputStream2 = new DataOutputStream(bos2); - try { + + try + { // Write source vector - outputStream2.writeDouble(source.x); - outputStream2.writeDouble(source.y); - outputStream2.writeDouble(source.z); - - // Write target vector - outputStream2.writeDouble(dest.x); - outputStream2.writeDouble(dest.y); - outputStream2.writeDouble(dest.z); - - // Write r, g, b of laser - outputStream2.writeFloat(r); - outputStream2.writeFloat(g); - outputStream2.writeFloat(b); - - // Write age - outputStream2.writeByte(age); - - // Write energy value - outputStream2.writeInt(energy); - } catch (Exception ex) { - ex.printStackTrace(); + outputStream2.writeDouble(source.x); + outputStream2.writeDouble(source.y); + outputStream2.writeDouble(source.z); + // Write target vector + outputStream2.writeDouble(dest.x); + outputStream2.writeDouble(dest.y); + outputStream2.writeDouble(dest.z); + // Write r, g, b of laser + outputStream2.writeFloat(r); + outputStream2.writeFloat(g); + outputStream2.writeFloat(b); + // Write age + outputStream2.writeByte(age); + // Write energy value + outputStream2.writeInt(energy); } - + catch (Exception ex) + { + ex.printStackTrace(); + } + Packet250CustomPayload packet2 = new Packet250CustomPayload(); packet.channel = "WarpDriveBeam"; packet.data = bos.toByteArray(); packet.length = bos.size(); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(dest.intX(), dest.intY(), dest.intZ(), radius, worldObj.provider.dimensionId, packet); - } + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(dest.intX(), dest.intY(), dest.intZ(), radius, worldObj.provider.dimensionId, packet); + } } - + @Override - public void readFromNBT(NBTTagCompound tag) { + public void readFromNBT(NBTTagCompound tag) + { super.readFromNBT(tag); - this.currentEnergyValue = tag.getInteger("energy"); } @Override - public void writeToNBT(NBTTagCompound tag) { + public void writeToNBT(NBTTagCompound tag) + { super.writeToNBT(tag); - tag.setInteger("energy", this.getCurrentEnergyValue()); - } - + } + // IEnergySink methods implementation @Override - public int demandsEnergy() { + public double demandedEnergyUnits() + { return (MAX_ENERGY_VALUE - currentEnergyValue); } @Override - public int injectEnergy(Direction directionFrom, int amount) { - // Р�збыток энергии - int leftover = 0; + public double injectEnergyUnits(ForgeDirection directionFrom, double amount) + { + double leftover = 0; + currentEnergyValue += Math.round(amount); - currentEnergyValue += amount; - if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) { + if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) + { leftover = (getCurrentEnergyValue() - MAX_ENERGY_VALUE); currentEnergyValue = MAX_ENERGY_VALUE; } @@ -267,48 +293,51 @@ public class TileEntityLift extends TileEntity implements IEnergySink { } @Override - public int getMaxSafeInput() { + public int getMaxSafeInput() + { return Integer.MAX_VALUE; } @Override - public boolean acceptsEnergyFrom(TileEntity emitter, Direction direction) { + public boolean acceptsEnergyFrom(TileEntity emitter, ForgeDirection direction) + { return true; } - @Override - public boolean isAddedToEnergyNet() { - return addedToEnergyNet; - } - /** * @return the currentEnergyValue */ - public int getCurrentEnergyValue() { + public int getCurrentEnergyValue() + { return currentEnergyValue; } - - public int collectAllEnergy() { - int energy = currentEnergyValue; - currentEnergyValue = 0; - return energy; - } - @Override - public void onChunkUnload() { - if (addedToEnergyNet) { - MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); - addedToEnergyNet = false; - } + public int collectAllEnergy() + { + int energy = currentEnergyValue; + currentEnergyValue = 0; + return energy; } - - @Override - public void invalidate() { - if (addedToEnergyNet) { + + @Override + public void onChunkUnload() + { + if (addedToEnergyNet) + { MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); addedToEnergyNet = false; - } - + } + } + + @Override + public void invalidate() + { + if (addedToEnergyNet) + { + MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); + addedToEnergyNet = false; + } + super.invalidate(); - } + } } diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index 14c5720b..6f958507 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -1,17 +1,11 @@ package cr0s.WarpDrive; -import cr0s.WarpDrive.TileEntityReactor; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.WarpDrive; import dan200.computer.api.IComputerAccess; import dan200.computer.api.ILuaContext; import dan200.computer.api.IPeripheral; -import ic2.api.Direction; -import ic2.api.energy.event.EnergyTileLoadEvent; -import ic2.api.energy.event.EnergyTileUnloadEvent; -import ic2.api.energy.tile.IEnergySink; import ic2.api.item.Items; import java.io.ByteArrayOutputStream; @@ -29,7 +23,7 @@ import net.minecraft.network.packet.Packet250CustomPayload; import net.minecraft.network.packet.Packet62LevelSound; import net.minecraft.server.MinecraftServer; import net.minecraft.tileentity.TileEntity; -import net.minecraft.tileentity.TileEntityChest; +import net.minecraft.inventory.IInventory; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.DamageSource; import net.minecraft.util.MovingObjectPosition; @@ -37,303 +31,365 @@ import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.MinecraftForge; -public class TileEntityMiningLaser extends TileEntity implements IPeripheral{ - private final int MAX_BOOSTERS_NUMBER = 1; - - private int dx, dz, dy; - private boolean isMining = false; - private boolean isQuarry = false; - - private String[] methodsArray = { - "startMining", "stop", // 0, 1 - "isMining", // 2 - "startQuarry", // 3 - "getMinerState", // 4 - "setStartLayerOffset" // 5 - }; - - public static final ArrayList<Integer> valuableOres = new ArrayList<Integer>(Arrays.asList( - Block.oreIron.blockID, - Block.oreGold.blockID, - Block.oreCoal.blockID, - Block.oreEmerald.blockID, - Block.oreLapis.blockID, - Block.oreRedstoneGlowing.blockID, - Block.oreRedstone.blockID, - Block.oreNetherQuartz.blockID, - Items.getItem("uraniumOre").itemID, // IC - Items.getItem("copperOre").itemID, // IC - Items.getItem("tinOre").itemID, // IC - 4095 // AS uranus - )); - - public static final ArrayList<Integer> otherValuables = new ArrayList<Integer>(Arrays.asList( - Block.wood.blockID, - Block.planks.blockID, - Items.getItem("rubberWood").itemID, - Block.rail.blockID, - 902, // Quarz (AE), - Block.oreDiamond.blockID, - Block.obsidian.blockID, - Block.web.blockID, - Block.fence.blockID, - Block.torchWood.blockID - )); - - private final int SCAN_DELAY = 20 * 5; - private int delayTicksScan = 0; - - private final int MINE_DELAY = 10; - private int delayTicksMine = 0; - - private final int EU_PER_LAYER_SPACE = 500; - private final int EU_PER_LAYER_EARTH = 5000; - - private int currentMode = 0; // 0 - scan next layer, 1 - collect valuables +public class TileEntityMiningLaser extends TileEntity implements IPeripheral +{ + private final int MAX_BOOSTERS_NUMBER = 1; - private int currentLayer; - - private ArrayList<Vector3> valuablesInLayer = new ArrayList<Vector3>(); - private int valuableIndex = 0; - - private int layerOffset = 1; - - private Vector3 minerVector; - //private long uid = 0; - - TileEntityParticleBooster booster = null; + private int dx, dz, dy; + private boolean isMining = false; + private boolean isQuarry = false; - private final int MFFS_FIELD_BLOCKID = 1681; - - private boolean isOnEarth = false; - //int t = 20; + private String[] methodsArray = + { + "startMining", "stop", // 0, 1 + "isMining", // 2 + "startQuarry", // 3 + "getMinerState", // 4 + "setStartLayerOffset" // 5 + }; + + public static final ArrayList<Integer> valuableOres = new ArrayList<Integer>(Arrays.asList( + Block.oreIron.blockID, + Block.oreGold.blockID, + Block.oreCoal.blockID, + Block.oreEmerald.blockID, + Block.oreLapis.blockID, + Block.oreRedstoneGlowing.blockID, + Block.oreRedstone.blockID, + Block.oreNetherQuartz.blockID, + Items.getItem("uraniumOre").itemID, // IC + Items.getItem("copperOre").itemID, // IC + Items.getItem("tinOre").itemID, // IC + 4095 // AS uranus + )); + + public static final ArrayList<Integer> otherValuables = new ArrayList<Integer>(Arrays.asList( + Block.wood.blockID, + Block.planks.blockID, + Items.getItem("rubberWood").itemID, + Block.rail.blockID, + 902, // Quarz (AE), + Block.oreDiamond.blockID, + Block.obsidian.blockID, + Block.web.blockID, + Block.fence.blockID, + Block.torchWood.blockID + )); + + private final int SCAN_DELAY = 20 * 5; + private int delayTicksScan = 0; + + private final int MINE_DELAY = 10; + private int delayTicksMine = 0; + + private final int EU_PER_LAYER_SPACE = 500; + private final int EU_PER_LAYER_EARTH = 5000; + + private int currentMode = 0; // 0 - scan next layer, 1 - collect valuables + + private int currentLayer; + + private ArrayList<Vector3> valuablesInLayer = new ArrayList<Vector3>(); + private int valuableIndex = 0; + + private int layerOffset = 1; + + private Vector3 minerVector; + //private long uid = 0; + + TileEntityParticleBooster booster = null; + + private final int MFFS_FIELD_BLOCKID = 1681; + + private boolean isOnEarth = false; + //int t = 20; @Override - public void updateEntity() { - /*if (uid == 0) { - uid = worldObj.rand.nextInt(99999); - } - if (--t == 0) { - t = 20; - System.out.println("[MINER] Ticked: " + uid + " | " + xCoord + "; " + yCoord + "; " + zCoord); - }*/ - - + public void updateEntity() + { + /*if (uid == 0) { + uid = worldObj.rand.nextInt(99999); + } + if (--t == 0) { + t = 20; + System.out.println("[MINER] Ticked: " + uid + " | " + xCoord + "; " + yCoord + "; " + zCoord); + }*/ isOnEarth = (worldObj.provider.dimensionId == 0); - - if (isMining) { - if (minerVector != null) { - minerVector.x = xCoord; - minerVector.y = yCoord - 1; - minerVector.z = zCoord; - - minerVector = minerVector.add(0.5); - } - - if (currentMode == 0) { - if (++delayTicksScan > SCAN_DELAY) { - delayTicksScan = 0; - currentMode = 1; - - if (currentLayer <= 0) { - isMining = false; - return; - } - - int blockID = worldObj.getBlockId(xCoord, currentLayer, zCoord); - int blockMeta = worldObj.getBlockMetadata(xCoord, currentLayer, zCoord); - - // That block is too hard - if (blockID == Block.bedrock.blockID || blockID == MFFS_FIELD_BLOCKID || !canDigDown()) { - isMining = false; - return; - } - if (blockID != 0 && worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && Block.blocksList[blockID].blockResistance > Block.obsidian.blockResistance) { - isMining = false; - return; - } - - sendLaserPacket(minerVector, new Vector3(xCoord, currentLayer, zCoord).add(0.5), 0, 0, 1, 20, 0, 50); - worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); - - harvestBlock(new Vector3(xCoord, currentLayer, zCoord)); - - if (collectEnergyPacketFromBooster((isOnEarth) ? EU_PER_LAYER_EARTH : EU_PER_LAYER_SPACE)) { - scanLayer(); - } else { - isMining = false; - } - - currentLayer--; - } - } else { - if (++delayTicksMine > MINE_DELAY) { - delayTicksMine = 0; - if (valuableIndex < valuablesInLayer.size()) { - //System.out.println("[ML] Mining: " + (valuableIndex + 1) + "/" + valuablesInLayer.size()); - Vector3 valuable = valuablesInLayer.get(valuableIndex++); - - // Mine valuable ore - int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); - // Skip if block is too hard or its empty block - if (worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && (worldObj.isAirBlock(valuable.intX(), valuable.intY(), valuable.intZ()) || Block.blocksList[blockID].blockResistance > Block.obsidian.blockResistance)) { - return; - } - - sendLaserPacket(minerVector, new Vector3(valuable.intX(), valuable.intY(), valuable.intZ()).add(0.5), 1, 1, 0, 2 * MINE_DELAY, 0, 50); - - worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F); - - harvestBlock(valuable); - } else { - currentMode = 0; - } - } - } - } - } - - private boolean canDigDown() { - for (int newY = yCoord - 1; newY > 0; newY--) { - int blockID = worldObj.getBlockId(xCoord, newY, zCoord); - - if (!worldObj.isAirBlock(xCoord, newY, zCoord)) { - if (blockID == MFFS_FIELD_BLOCKID || (blockID != Block.bedrock.blockID && Block.blocksList[blockID] != null && Block.blocksList[blockID].blockResistance > Block.obsidian.blockResistance)) { - if (currentLayer > newY) { - currentLayer = newY; - } - - return false; - } - } - } - - return true; - } - - private void harvestBlock(Vector3 valuable) { - int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); - int blockMeta = worldObj.getBlockMetadata(valuable.intX(), valuable.intY(), valuable.intZ()); - - if (blockID != Block.waterMoving.blockID && blockID != Block.waterStill.blockID && blockID != Block.lavaMoving.blockID && blockID != Block.lavaStill.blockID) { - List<ItemStack> stacks = getItemStackFromBlock(valuable.intX(), valuable.intY(), valuable.intZ(), blockID, blockMeta); - - if (stacks != null) { - for (ItemStack stack : stacks) { - putInChest(findChest(), stack); - } - } - - worldObj.playAuxSFXAtEntity(null, 2001, valuable.intX(), valuable.intY(), valuable.intZ(), blockID + (blockMeta << 12)); - // Evaporate water - } else if (blockID == Block.waterMoving.blockID || blockID == Block.waterStill.blockID) { - worldObj.playSoundEffect((double)((float)valuable.intX() + 0.5F), (double)((float)valuable.intY() + 0.5F), (double)((float)valuable.intZ() + 0.5F), "random.fizz", 0.5F, 2.6F + (worldObj.rand.nextFloat() - worldObj.rand.nextFloat()) * 0.8F); - } + if (isMining) + { + if (minerVector != null) + { + minerVector.x = xCoord; + minerVector.y = yCoord - 1; + minerVector.z = zCoord; + minerVector = minerVector.add(0.5); + } - worldObj.setBlockToAir(valuable.intX(), valuable.intY(), valuable.intZ()); + if (currentMode == 0) + { + if (++delayTicksScan > SCAN_DELAY) + { + delayTicksScan = 0; + currentMode = 1; + + if (currentLayer <= 0) + { + isMining = false; + return; + } + + int blockID = worldObj.getBlockId(xCoord, currentLayer, zCoord); + int blockMeta = worldObj.getBlockMetadata(xCoord, currentLayer, zCoord); + + // That block is too hard + if (blockID == Block.bedrock.blockID || blockID == MFFS_FIELD_BLOCKID || !canDigDown()) + { + isMining = false; + return; + } + + if (blockID != 0 && worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && Block.blocksList[blockID].blockResistance > Block.obsidian.blockResistance) + { + isMining = false; + return; + } + + sendLaserPacket(minerVector, new Vector3(xCoord, currentLayer, zCoord).add(0.5), 0, 0, 1, 20, 0, 50); + worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); + harvestBlock(new Vector3(xCoord, currentLayer, zCoord)); + + if (collectEnergyPacketFromBooster((isOnEarth) ? EU_PER_LAYER_EARTH : EU_PER_LAYER_SPACE)) + { + scanLayer(); + } + else + { + isMining = false; + } + + currentLayer--; + } + } + else + { + if (++delayTicksMine > MINE_DELAY) + { + delayTicksMine = 0; + + if (valuableIndex < valuablesInLayer.size()) + { + //System.out.println("[ML] Mining: " + (valuableIndex + 1) + "/" + valuablesInLayer.size()); + Vector3 valuable = valuablesInLayer.get(valuableIndex++); + // Mine valuable ore + int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); + + // Skip if block is too hard or its empty block + if (worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && (worldObj.isAirBlock(valuable.intX(), valuable.intY(), valuable.intZ()) || Block.blocksList[blockID].blockResistance > Block.obsidian.blockResistance)) + { + return; + } + + sendLaserPacket(minerVector, new Vector3(valuable.intX(), valuable.intY(), valuable.intZ()).add(0.5), 1, 1, 0, 2 * MINE_DELAY, 0, 50); + worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F); + harvestBlock(valuable); + } + else + { + currentMode = 0; + } + } + } + } } - - private TileEntityChest findChest() { - TileEntity result = null; + + private boolean canDigDown() + { + for (int newY = yCoord - 1; newY > 0; newY--) + { + int blockID = worldObj.getBlockId(xCoord, newY, zCoord); + + if (!worldObj.isAirBlock(xCoord, newY, zCoord)) + { + if (blockID == MFFS_FIELD_BLOCKID || (blockID != Block.bedrock.blockID && Block.blocksList[blockID] != null && Block.blocksList[blockID].blockResistance > Block.obsidian.blockResistance)) + { + if (currentLayer > newY) + { + currentLayer = newY; + } + + return false; + } + } + } + + return true; + } + + private void harvestBlock(Vector3 valuable) + { + int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); + int blockMeta = worldObj.getBlockMetadata(valuable.intX(), valuable.intY(), valuable.intZ()); + + if (blockID != Block.waterMoving.blockID && blockID != Block.waterStill.blockID && blockID != Block.lavaMoving.blockID && blockID != Block.lavaStill.blockID) + { + List<ItemStack> stacks = getItemStackFromBlock(valuable.intX(), valuable.intY(), valuable.intZ(), blockID, blockMeta); + + if (stacks != null) + { + for (ItemStack stack : stacks) + { + putInChest(findChest(), stack); + } + } + + worldObj.playAuxSFXAtEntity(null, 2001, valuable.intX(), valuable.intY(), valuable.intZ(), blockID + (blockMeta << 12)); + // Evaporate water + } + else if (blockID == Block.waterMoving.blockID || blockID == Block.waterStill.blockID) + { + worldObj.playSoundEffect((double)((float)valuable.intX() + 0.5F), (double)((float)valuable.intY() + 0.5F), (double)((float)valuable.intZ() + 0.5F), "random.fizz", 0.5F, 2.6F + (worldObj.rand.nextFloat() - worldObj.rand.nextFloat()) * 0.8F); + } + + worldObj.setBlockToAir(valuable.intX(), valuable.intY(), valuable.intZ()); + } + + private IInventory findChest() + { + TileEntity result = null; result = worldObj.getBlockTileEntity(xCoord + 1, yCoord, zCoord); - if (result != null && result instanceof TileEntityChest) { - return (TileEntityChest) result; + + if (result != null && result instanceof IInventory) + { + return (IInventory) result; } result = worldObj.getBlockTileEntity(xCoord - 1, yCoord, zCoord); - if (result != null && result instanceof TileEntityChest) { - return (TileEntityChest) result; + + if (result != null && result instanceof IInventory) + { + return (IInventory) result; } result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord + 1); - if (result != null && result instanceof TileEntityChest) { - return (TileEntityChest) result; + + if (result != null && result instanceof IInventory) + { + return (IInventory) result; } result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord - 1); - if (result != null && result instanceof TileEntityChest) { - return (TileEntityChest) result; + + if (result != null && result instanceof IInventory) + { + return (IInventory) result; } - + result = worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord); - if (result != null && result instanceof TileEntityChest) { - return (TileEntityChest) result; + + if (result != null && result instanceof IInventory) + { + return (IInventory) result; } return null; } - - public List<ItemStack> getItemStackFromBlock(int i, int j, int k, int blockID, int blockMeta) { - Block block = Block.blocksList[blockID]; - - if (block == null) - return null; - - return block.getBlockDropped(worldObj, i, j, k, blockMeta, 0); - } - - public static int putInChest(TileEntityChest inventory, ItemStack itemStackSource) + + public List<ItemStack> getItemStackFromBlock(int i, int j, int k, int blockID, int blockMeta) { - if (inventory == null || itemStackSource == null) { - return 0; - } - - int transferred = 0; - for(int i = 0; i < inventory.getSizeInventory(); i++) + Block block = Block.blocksList[blockID]; + + if (block == null) { - if(!inventory.isItemValidForSlot(i, itemStackSource)) + return null; + } + + return block.getBlockDropped(worldObj, i, j, k, blockMeta, 0); + } + + public static int putInChest(IInventory inventory, ItemStack itemStackSource) + { + if (inventory == null || itemStackSource == null) + { + return 0; + } + + int transferred = 0; + + for (int i = 0; i < inventory.getSizeInventory(); i++) + { + if (!inventory.isItemValidForSlot(i, itemStackSource)) + { continue; + } + ItemStack itemStack = inventory.getStackInSlot(i); - if(itemStack == null || !itemStack.isItemEqual(itemStackSource)) + + if (itemStack == null || !itemStack.isItemEqual(itemStackSource)) + { continue; + } + int transfer = Math.min(itemStackSource.stackSize - transferred, itemStack.getMaxStackSize() - itemStack.stackSize); itemStack.stackSize += transfer; transferred += transfer; - if(transferred == itemStackSource.stackSize) + + if (transferred == itemStackSource.stackSize) + { return transferred; + } } - for(int i = 0; i < inventory.getSizeInventory(); i++) + for (int i = 0; i < inventory.getSizeInventory(); i++) { - if(!inventory.isItemValidForSlot(i, itemStackSource)) + if (!inventory.isItemValidForSlot(i, itemStackSource)) + { continue; + } + ItemStack itemStack = inventory.getStackInSlot(i); - if(itemStack != null) + + if (itemStack != null) + { continue; + } + int transfer = Math.min(itemStackSource.stackSize - transferred, itemStackSource.getMaxStackSize()); ItemStack dest = copyWithSize(itemStackSource, transfer); inventory.setInventorySlotContents(i, dest); transferred += transfer; - if(transferred == itemStackSource.stackSize) + + if (transferred == itemStackSource.stackSize) + { return transferred; + } } return transferred; - } - + } + public static ItemStack copyWithSize(ItemStack itemStack, int newSize) { ItemStack ret = itemStack.copy(); ret.stackSize = newSize; return ret; - } - - private void scanLayer() { - //System.out.println("Scanning layer"); - valuablesInLayer.clear(); - + } + + private void scanLayer() + { + //System.out.println("Scanning layer"); + valuablesInLayer.clear(); int xmax, zmax, x1, x2, z1, z2; int xmin, zmin; - final int CUBE_SIDE = 8; - x1 = xCoord + CUBE_SIDE / 2; x2 = xCoord - CUBE_SIDE / 2; - - if (x1 < x2) { + + if (x1 < x2) + { xmin = x1; xmax = x2; - } else + } + else { xmin = x2; xmax = x1; @@ -341,57 +397,75 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral{ z1 = zCoord + CUBE_SIDE / 2; z2 = zCoord - CUBE_SIDE / 2; - - if (z1 < z2) { + + if (z1 < z2) + { zmin = z1; zmax = z2; - } else + } + else { zmin = z2; zmax = z1; } - + //System.out.println("Layer: xmax: " + xmax + ", xmin: " + xmin); //System.out.println("Layer: zmax: " + zmax + ", zmin: " + zmin); - + // Search for valuable blocks - for (int x = xmin; x <= xmax; x++) { - for (int z = zmin; z <= zmax; z++) { - if (isQuarry) { // Quarry collects all blocks - int blockID = worldObj.getBlockId(x, currentLayer, z); - if (blockID == Block.bedrock.blockID || blockID == MFFS_FIELD_BLOCKID) { - continue; - } - if (!worldObj.isAirBlock(x, currentLayer, z) && blockID != Block.lavaMoving.blockID && blockID != Block.lavaStill.blockID && (Block.blocksList[blockID].blockResistance <= Block.obsidian.blockResistance)) - valuablesInLayer.add(new Vector3(x, currentLayer, z)); - } else // Not-quarry collect only valuables blocks - if (valuableOres.contains((worldObj.getBlockId(x, currentLayer, z))) || otherValuables.contains((worldObj.getBlockId(x, currentLayer, z)))) { - valuablesInLayer.add(new Vector3(x, currentLayer, z)); + for (int x = xmin; x <= xmax; x++) + { + for (int z = zmin; z <= zmax; z++) + { + if (isQuarry) // Quarry collects all blocks + { + int blockID = worldObj.getBlockId(x, currentLayer, z); + + if (blockID == Block.bedrock.blockID || blockID == MFFS_FIELD_BLOCKID) + { + continue; + } + + if (!worldObj.isAirBlock(x, currentLayer, z) && blockID != Block.lavaMoving.blockID && blockID != Block.lavaStill.blockID && (Block.blocksList[blockID].blockResistance <= Block.obsidian.blockResistance)) + { + valuablesInLayer.add(new Vector3(x, currentLayer, z)); + } } + else // Not-quarry collect only valuables blocks + if (valuableOres.contains((worldObj.getBlockId(x, currentLayer, z))) || otherValuables.contains((worldObj.getBlockId(x, currentLayer, z)))) + { + valuablesInLayer.add(new Vector3(x, currentLayer, z)); + } } } - + valuableIndex = 0; //System.out.println("[ML] Found " + valuablesInLayer.size() + " valuables"); - } - private boolean collectEnergyPacketFromBooster(int packet) { - int energyCollected = 0; - if (booster == null) - booster = findFirstBooster(); - - if (booster != null) { - return booster.consumeEnergy(packet); - } - - return false; - } - - private TileEntityParticleBooster findFirstBooster() { - TileEntity result; + private boolean collectEnergyPacketFromBooster(int packet) + { + int energyCollected = 0; + if (booster == null) + { + booster = findFirstBooster(); + } + + if (booster != null) + { + return booster.consumeEnergy(packet); + } + + return false; + } + + private TileEntityParticleBooster findFirstBooster() + { + TileEntity result; result = worldObj.getBlockTileEntity(xCoord + 1, yCoord, zCoord); - if (result != null && result instanceof TileEntityParticleBooster) { + + if (result != null && result instanceof TileEntityParticleBooster) + { dx = 1; dz = 0; dy = 0; @@ -399,7 +473,9 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral{ } result = worldObj.getBlockTileEntity(xCoord - 1, yCoord, zCoord); - if (result != null && result instanceof TileEntityParticleBooster) { + + if (result != null && result instanceof TileEntityParticleBooster) + { dx = -1; dz = 0; dy = 0; @@ -407,24 +483,30 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral{ } result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord + 1); - if (result != null && result instanceof TileEntityParticleBooster) { - dx = 0; + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = 0; dz = 1; dy = 0; return (TileEntityParticleBooster) result; } result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord - 1); - if (result != null && result instanceof TileEntityParticleBooster) { + + if (result != null && result instanceof TileEntityParticleBooster) + { dx = 0; dz = -1; dy = 0; return (TileEntityParticleBooster) result; } - + result = worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord); - if (result != null && result instanceof TileEntityParticleBooster) { - dx = 0; + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = 0; dz = 0; dy = 1; return (TileEntityParticleBooster) result; @@ -432,163 +514,178 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral{ return null; } - - public void sendLaserPacket(Vector3 source, Vector3 dest, float r, float g, float b, int age, int energy, int radius) { + + public void sendLaserPacket(Vector3 source, Vector3 dest, float r, float g, float b, int age, int energy, int radius) + { Side side = FMLCommonHandler.instance().getEffectiveSide(); - if (side == Side.SERVER) { - if (source == null || dest == null || worldObj == null) { - return; - } - + + if (side == Side.SERVER) + { + if (source == null || dest == null || worldObj == null) + { + return; + } + ByteArrayOutputStream bos = new ByteArrayOutputStream(8); DataOutputStream outputStream = new DataOutputStream(bos); - try { + + try + { // Write source vector - outputStream.writeDouble(source.x); - outputStream.writeDouble(source.y); - outputStream.writeDouble(source.z); - - // Write target vector - outputStream.writeDouble(dest.x); - outputStream.writeDouble(dest.y); - outputStream.writeDouble(dest.z); - - // Write r, g, b of laser - outputStream.writeFloat(r); - outputStream.writeFloat(g); - outputStream.writeFloat(b); - - // Write age - outputStream.writeByte(age); - - // Write energy value - outputStream.writeInt(0); - } catch (Exception ex) { - ex.printStackTrace(); + outputStream.writeDouble(source.x); + outputStream.writeDouble(source.y); + outputStream.writeDouble(source.z); + // Write target vector + outputStream.writeDouble(dest.x); + outputStream.writeDouble(dest.y); + outputStream.writeDouble(dest.z); + // Write r, g, b of laser + outputStream.writeFloat(r); + outputStream.writeFloat(g); + outputStream.writeFloat(b); + // Write age + outputStream.writeByte(age); + // Write energy value + outputStream.writeInt(0); } - + catch (Exception ex) + { + ex.printStackTrace(); + } + Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "WarpDriveBeam"; packet.data = bos.toByteArray(); packet.length = bos.size(); - - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(source.intX(), source.intY(), source.intZ(), radius, worldObj.provider.dimensionId, packet); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(dest.intX(), dest.intY(), dest.intZ(), radius, worldObj.provider.dimensionId, packet); - } + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(source.intX(), source.intY(), source.intZ(), radius, worldObj.provider.dimensionId, packet); + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(dest.intX(), dest.intY(), dest.intZ(), radius, worldObj.provider.dimensionId, packet); + } } - + @Override - public void readFromNBT(NBTTagCompound tag) { + public void readFromNBT(NBTTagCompound tag) + { super.readFromNBT(tag); - isMining = tag.getBoolean("isMining"); isQuarry = tag.getBoolean("isQuarry"); currentLayer = tag.getInteger("currentLayer"); - minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); } @Override - public void writeToNBT(NBTTagCompound tag) { + public void writeToNBT(NBTTagCompound tag) + { super.writeToNBT(tag); - tag.setBoolean("isMining", isMining); tag.setBoolean("isQuarry", isQuarry); - tag.setInteger("currentLayer", currentLayer); - } - + tag.setInteger("currentLayer", currentLayer); + } + // IPeripheral methods implementation @Override - public String getType() { + public String getType() + { return "mininglaser"; } @Override - public String[] getMethodNames() { + public String[] getMethodNames() + { return methodsArray; } @Override - public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception { - switch (method) { + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception + { + switch (method) + { case 0: // startMining() - isMining = true; - isQuarry = false; - delayTicksScan = 0; - currentMode = 0; - - minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); - currentLayer = yCoord - layerOffset; - + isMining = true; + isQuarry = false; + delayTicksScan = 0; + currentMode = 0; + minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); + currentLayer = yCoord - layerOffset; return new Object[] { 0 }; - + case 1: // stop() - isMining = false; - break; - - case 2: // isMining() - return new Boolean[] { isMining }; - + isMining = false; + break; + + case 2: // isMining() + return new Boolean[] { isMining }; case 3: // startQuarry() - if (isMining) { - return new Object[] { -1 }; - } - isMining = true; - isQuarry = true; - delayTicksScan = 0; - currentMode = 0; - - minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); - currentLayer = yCoord - layerOffset; - - return new Object[] { 0 }; - - // State is: state, energy, currentLayer, valuablesMined, valuablesInLayer = getMinerState() + if (isMining) + { + return new Object[] { -1 }; + } + + isMining = true; + isQuarry = true; + delayTicksScan = 0; + currentMode = 0; + minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); + currentLayer = yCoord - layerOffset; + return new Object[] { 0 }; + + // State is: state, energy, currentLayer, valuablesMined, valuablesInLayer = getMinerState() case 4: // getMinerState() - int energy = 0; - if (booster != null) { - energy = booster.getCurrentEnergyValue(); - } - - String state = "not mining"; - Integer valuablesInLayer, valuablesMined; - - if (isMining) { - valuablesInLayer = this.valuablesInLayer.size(); - valuablesMined = this.valuableIndex; - - state = "mining" + ((isQuarry) ? " (quarry mode)" : ""); - if (energy < 0) - state = "out of energy"; - - return new Object[] {state, energy, currentLayer, valuablesMined, valuablesInLayer}; - } - - return new Object[] {state, energy, currentLayer, 0, 0}; + int energy = 0; + + if (booster != null) + { + energy = booster.getCurrentEnergyValue(); + } + + String state = "not mining"; + Integer valuablesInLayer, valuablesMined; + + if (isMining) + { + valuablesInLayer = this.valuablesInLayer.size(); + valuablesMined = this.valuableIndex; + state = "mining" + ((isQuarry) ? " (quarry mode)" : ""); + + if (energy < 0) + { + state = "out of energy"; + } + + return new Object[] {state, energy, currentLayer, valuablesMined, valuablesInLayer}; + } + + return new Object[] {state, energy, currentLayer, 0, 0}; + case 5: // setStartLayerOffset - if (arguments.length == 1) { - int a = ((Double)arguments[0]).intValue(); - if (a < 1) { a = 1; } - - layerOffset = a; - } + if (arguments.length == 1) + { + int a = ((Double)arguments[0]).intValue(); + + if (a < 1) + { + a = 1; + } + + layerOffset = a; + } } - + return new Object[] { 0 }; } @Override - public boolean canAttachToSide(int side) { + public boolean canAttachToSide(int side) + { return true; } @Override - public void attach(IComputerAccess computer) { - + public void attach(IComputerAccess computer) + { } @Override - public void detach(IComputerAccess computer) { - + public void detach(IComputerAccess computer) + { } } diff --git a/src/cr0s/WarpDrive/TileEntityMonitor.java b/src/cr0s/WarpDrive/TileEntityMonitor.java index 6359fae8..8813ad23 100644 --- a/src/cr0s/WarpDrive/TileEntityMonitor.java +++ b/src/cr0s/WarpDrive/TileEntityMonitor.java @@ -1,18 +1,11 @@ package cr0s.WarpDrive; -import cr0s.WarpDrive.TileEntityReactor; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.WarpDrive; import dan200.computer.api.IComputerAccess; import dan200.computer.api.ILuaContext; import dan200.computer.api.IPeripheral; -import ic2.api.Direction; -import ic2.api.energy.event.EnergyTileLoadEvent; -import ic2.api.energy.event.EnergyTileUnloadEvent; -import ic2.api.energy.tile.IEnergySink; -import ic2.api.item.Items; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -39,114 +32,133 @@ import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.MinecraftForge; -public class TileEntityMonitor extends TileEntity implements IPeripheral { - private int frequency; - - private String[] methodsArray = { - "setFrequency", // 0 - "getFrequency" - }; - +public class TileEntityMonitor extends TileEntity implements IPeripheral +{ + private int frequency; + + private String[] methodsArray = + { + "setFrequency", // 0 + "getFrequency" + }; + private int packetSendTicks = 20; - + @Override - public void updateEntity() { - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { - if (packetSendTicks-- == 0) { - packetSendTicks = 20 * 5; - sendFreqPacket(); - } - - return; - } - } - - public int getFrequency() { - return frequency; + public void updateEntity() + { + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) + { + if (packetSendTicks-- == 0) + { + packetSendTicks = 20 * 5; + sendFreqPacket(); + } + + return; + } + } + + public int getFrequency() + { + return frequency; + } + + public void setFrequency(int freq) + { + frequency = freq; } - public void setFrequency(int freq) { - frequency = freq; - } - @Override - public void readFromNBT(NBTTagCompound tag) { + public void readFromNBT(NBTTagCompound tag) + { super.readFromNBT(tag); - frequency = tag.getInteger("frequency"); } @Override - public void writeToNBT(NBTTagCompound tag) { + public void writeToNBT(NBTTagCompound tag) + { super.writeToNBT(tag); - tag.setInteger("frequency", frequency); - } - + } + // IPeripheral methods implementation @Override - public String getType() { + public String getType() + { return "monitor"; } @Override - public String[] getMethodNames() { + public String[] getMethodNames() + { return methodsArray; } @Override - public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception { - switch (method) { + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception + { + switch (method) + { case 0: // setFrequency - if (arguments.length == 1) { - frequency = ((Double)arguments[0]).intValue(); - } - break; - + if (arguments.length == 1) + { + frequency = ((Double)arguments[0]).intValue(); + } + + break; + case 1: - return new Object[] { (Integer)frequency }; - + return new Object[] { (Integer)frequency }; } - + return new Object[] { 0 }; } - public void sendFreqPacket() { + public void sendFreqPacket() + { Side side = FMLCommonHandler.instance().getEffectiveSide(); - if (side == Side.SERVER) { + + if (side == Side.SERVER) + { ByteArrayOutputStream bos = new ByteArrayOutputStream(8); DataOutputStream outputStream = new DataOutputStream(bos); - try { + + try + { // Write source vector - outputStream.writeInt(xCoord); - outputStream.writeInt(yCoord); - outputStream.writeInt(zCoord); - - outputStream.writeInt(this.frequency); - } catch (Exception ex) { - ex.printStackTrace(); + outputStream.writeInt(xCoord); + outputStream.writeInt(yCoord); + outputStream.writeInt(zCoord); + outputStream.writeInt(this.frequency); } - + catch (Exception ex) + { + ex.printStackTrace(); + } + Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "WarpDriveFreq"; packet.data = bos.toByteArray(); packet.length = bos.size(); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(xCoord, yCoord, zCoord, 100, worldObj.provider.dimensionId, packet); + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(xCoord, yCoord, zCoord, 100, worldObj.provider.dimensionId, packet); } - } - + } + @Override - public boolean canAttachToSide(int side) { + public boolean canAttachToSide(int side) + { return true; } @Override - public void attach(IComputerAccess computer) { - + public void attach(IComputerAccess computer) + { } @Override - public void detach(IComputerAccess computer) { - + public void detach(IComputerAccess computer) + { } } diff --git a/src/cr0s/WarpDrive/TileEntityParticleBooster.java b/src/cr0s/WarpDrive/TileEntityParticleBooster.java index 3e17b834..98074bec 100644 --- a/src/cr0s/WarpDrive/TileEntityParticleBooster.java +++ b/src/cr0s/WarpDrive/TileEntityParticleBooster.java @@ -1,14 +1,12 @@ package cr0s.WarpDrive; -import cr0s.WarpDrive.TileEntityReactor; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.WarpDrive; import dan200.computer.api.IComputerAccess; import dan200.computer.api.ILuaContext; import dan200.computer.api.IPeripheral; -import ic2.api.Direction; +import net.minecraftforge.common.ForgeDirection; import ic2.api.energy.event.EnergyTileLoadEvent; import ic2.api.energy.event.EnergyTileUnloadEvent; import ic2.api.energy.tile.IEnergySink; @@ -24,58 +22,66 @@ import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.DamageSource; import net.minecraftforge.common.MinecraftForge; -public class TileEntityParticleBooster extends TileEntity implements IEnergySink { - +public class TileEntityParticleBooster extends TileEntity implements IEnergySink +{ public boolean addedToEnergyNet = false; - + private final int MAX_ENERGY_VALUE = 100000; // eU private int currentEnergyValue = 0; - + int ticks = 0; - + @Override - public void updateEntity() { + public void updateEntity() + { if (FMLCommonHandler.instance().getEffectiveSide().isClient()) - return; - - if (!addedToEnergyNet && !this.tileEntityInvalid) { + { + return; + } + + if (!addedToEnergyNet && !this.tileEntityInvalid) + { MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this)); addedToEnergyNet = true; } - - if (++ticks > 40) { - ticks = 0; - currentEnergyValue = Math.min(currentEnergyValue, MAX_ENERGY_VALUE); - worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, currentEnergyValue / 10000, 2); + + if (++ticks > 40) + { + ticks = 0; + currentEnergyValue = Math.min(currentEnergyValue, MAX_ENERGY_VALUE); + worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, currentEnergyValue / 10000, 2); } } - + @Override - public void readFromNBT(NBTTagCompound tag) { + public void readFromNBT(NBTTagCompound tag) + { super.readFromNBT(tag); - this.currentEnergyValue = tag.getInteger("energy"); } @Override - public void writeToNBT(NBTTagCompound tag) { + public void writeToNBT(NBTTagCompound tag) + { super.writeToNBT(tag); - tag.setInteger("energy", this.getCurrentEnergyValue()); - } - + } + // IEnergySink methods implementation @Override - public int demandsEnergy() { + public double demandedEnergyUnits() + { return (MAX_ENERGY_VALUE - currentEnergyValue); } @Override - public int injectEnergy(Direction directionFrom, int amount) { - int leftover = 0; + public double injectEnergyUnits(ForgeDirection directionFrom, double amount) + { + double leftover = 0; + currentEnergyValue += Math.round(amount); - currentEnergyValue += amount; - if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) { + if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) + { leftover = (getCurrentEnergyValue() - MAX_ENERGY_VALUE); currentEnergyValue = MAX_ENERGY_VALUE; } @@ -84,56 +90,62 @@ public class TileEntityParticleBooster extends TileEntity implements IEnergySink } @Override - public int getMaxSafeInput() { + public int getMaxSafeInput() + { return Integer.MAX_VALUE; } @Override - public boolean acceptsEnergyFrom(TileEntity emitter, Direction direction) { + public boolean acceptsEnergyFrom(TileEntity emitter, ForgeDirection direction) + { return true; } - @Override - public boolean isAddedToEnergyNet() { - return addedToEnergyNet; - } - /** * @return the currentEnergyValue */ - public int getCurrentEnergyValue() { + public int getCurrentEnergyValue() + { return currentEnergyValue; } - - public boolean consumeEnergy(int amount) { - if (currentEnergyValue - amount < 0) - return false; - - currentEnergyValue -= amount; - return true; - } - - public int collectAllEnergy() { - int energy = currentEnergyValue; - currentEnergyValue = 0; - return energy; - } - @Override - public void onChunkUnload() { - if (addedToEnergyNet) { - MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); - addedToEnergyNet = false; - } + public boolean consumeEnergy(int amount) + { + if (currentEnergyValue - amount < 0) + { + return false; + } + + currentEnergyValue -= amount; + return true; } - - @Override - public void invalidate() { - if (addedToEnergyNet) { + + public int collectAllEnergy() + { + int energy = currentEnergyValue; + currentEnergyValue = 0; + return energy; + } + + @Override + public void onChunkUnload() + { + if (addedToEnergyNet) + { MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); addedToEnergyNet = false; - } - + } + } + + @Override + public void invalidate() + { + if (addedToEnergyNet) + { + MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); + addedToEnergyNet = false; + } + super.invalidate(); - } + } } diff --git a/src/cr0s/WarpDrive/TileEntityProtocol.java b/src/cr0s/WarpDrive/TileEntityProtocol.java index 2d3dda6c..f1b1a6df 100644 --- a/src/cr0s/WarpDrive/TileEntityProtocol.java +++ b/src/cr0s/WarpDrive/TileEntityProtocol.java @@ -14,413 +14,473 @@ import net.minecraft.util.DamageSource; * Protocol block tile entity * @author Cr0s */ -public class TileEntityProtocol extends TileEntity implements IPeripheral { - +public class TileEntityProtocol extends TileEntity implements IPeripheral +{ // Variables private int distance = 0; private int direction = 0; private int mode = 0; - + private boolean jumpFlag = false; private boolean summonFlag = false; private String toSummon = ""; - + private String targetJumpgateName = ""; - + // Gabarits private int front, right, up; private int back, left, down; - + // Player attaching public ArrayList<String> players = new ArrayList(); public String playersString = ""; - + private String beaconFrequency = ""; - + boolean ready = false; // Ready to operate (valid assembly) - - public String[] methodsArray = { - "dim_getp", "dim_setp", // 0, 1 - "dim_getn", "dim_setn", // 2, 3 - "set_mode", "set_distance", "set_direction", // 4, 5, 6 - "get_attached_players", "summon", "summon_all", // 7, 8, 9 - "get_x", "get_y", "get_z", // 10, 11, 12 - "get_energy_level", "do_jump", "get_ship_size", // 13, 14, 15 - "set_beacon_frequency", "get_dx", "get_dz", // 16, 17, 18 - "set_core_frequency", "is_in_space", "is_in_hyperspace", // 19, 20, 21 - "set_target_jumpgate", // 22 - }; - + + public String[] methodsArray = + { + "dim_getp", "dim_setp", // 0, 1 + "dim_getn", "dim_setn", // 2, 3 + "set_mode", "set_distance", "set_direction", // 4, 5, 6 + "get_attached_players", "summon", "summon_all", // 7, 8, 9 + "get_x", "get_y", "get_z", // 10, 11, 12 + "get_energy_level", "do_jump", "get_ship_size", // 13, 14, 15 + "set_beacon_frequency", "get_dx", "get_dz", // 16, 17, 18 + "set_core_frequency", "is_in_space", "is_in_hyperspace", // 19, 20, 21 + "set_target_jumpgate", // 22 + }; + private int ticks = 0; private final int BLOCK_UPDATE_INTERVAL = 20 * 3; // 3 seconds - private TileEntity core; - + private TileEntity core; + @Override - public void updateEntity() { + public void updateEntity() + { if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { return; - if (++ticks >= BLOCK_UPDATE_INTERVAL){ + } + + if (++ticks >= BLOCK_UPDATE_INTERVAL) + { findCoreBlock(); - - if (core != null) { + + if (core != null) + { worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, this.mode, 1 + 2); // Activated - } else + } + else { worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 1 + 2); // Inactive - } + } ticks = 0; } - } - - private void setJumpDistance(int distance) { + + private void setJumpDistance(int distance) + { System.out.println("Setting jump distance: " + distance); this.distance = distance; } - private void setMode(int mode) { - // System.out.println("Setting mode: " + mode); + private void setMode(int mode) + { + // System.out.println("Setting mode: " + mode); this.mode = mode; - } - - private void setDirection(int dir) { - if (dir == 1) { dir = -1; } else if (dir == 2) { dir = -2; } else if (dir == 255) { dir = 270; } + } + + private void setDirection(int dir) + { + if (dir == 1) + { + dir = -1; + } + else if (dir == 2) + { + dir = -2; + } + else if (dir == 255) + { + dir = 270; + } + System.out.println("Setting direction: " + dir); this.direction = dir; } - - private void doJump() { - if (core != null && core instanceof TileEntityReactor) { - ((TileEntityReactor)core).randomCooldownAddition = worldObj.rand.nextInt(60); // Adding random ticks to cooldown + + private void doJump() + { + if (core != null && core instanceof TileEntityReactor) + { + ((TileEntityReactor)core).randomCooldownAddition = worldObj.rand.nextInt(60); // Adding random ticks to cooldown } + setJumpFlag(true); } - + @Override - public void readFromNBT(NBTTagCompound tag) { + public void readFromNBT(NBTTagCompound tag) + { super.readFromNBT(tag); - setMode(tag.getInteger("mode")); - setFront(tag.getInteger("front")); setRight(tag.getInteger("right")); setUp(tag.getInteger("up")); - setBack(tag.getInteger("back")); setLeft(tag.getInteger("left")); setDown(tag.getInteger("down")); - setDistance(tag.getInteger("distance")); - playersString = tag.getString("players"); - updatePlayersList(); - + updatePlayersList(); setBeaconFrequency(tag.getString("bfreq")); } @Override - public void writeToNBT(NBTTagCompound tag) { + public void writeToNBT(NBTTagCompound tag) + { super.writeToNBT(tag); - updatePlayersString(); - tag.setString("players", playersString); - + tag.setString("players", playersString); tag.setInteger("mode", this.mode); - tag.setInteger("front", this.front); tag.setInteger("right", this.right); tag.setInteger("up", this.up); - tag.setInteger("back", this.back); tag.setInteger("left", this.left); tag.setInteger("down", this.down); - tag.setInteger("distance", this.distance); - tag.setString("bfreq", getBeaconFrequency()); - } - - public void attachPlayer(EntityPlayer ep) { - for (int i = 0; i < players.size(); i++) { + } + + public void attachPlayer(EntityPlayer ep) + { + for (int i = 0; i < players.size(); i++) + { String nick = players.get(i); - - if (ep.username.equals(nick)) { + + if (ep.username.equals(nick)) + { ep.addChatMessage("[WarpCtrlr] Detached."); players.remove(i); return; } } - + ep.attackEntityFrom(DamageSource.generic, 1); ep.addChatMessage("[WarpCtrlr] Successfully attached."); players.add(ep.username); updatePlayersString(); } - - public void updatePlayersString() { + + public void updatePlayersString() + { String nick; this.playersString = ""; - - for (int i = 0; i < players.size(); i++) { + + for (int i = 0; i < players.size(); i++) + { nick = players.get(i); - this.playersString += nick + "|"; } } - - public void updatePlayersList() { + + public void updatePlayersList() + { String[] playersArray = playersString.split("\\|"); - for (int i = 0; i < playersArray.length; i++) { + for (int i = 0; i < playersArray.length; i++) + { String nick = playersArray[i]; - - if (!nick.isEmpty()) { + + if (!nick.isEmpty()) + { players.add(nick); } } } - - public String getAttachedPlayersList() { + + public String getAttachedPlayersList() + { String list = ""; - - for (int i = 0; i < this.players.size(); i++) { + + for (int i = 0; i < this.players.size(); i++) + { String nick = this.players.get(i); - - list += nick + ((i == this.players.size() - 1)? "" : ", "); + list += nick + ((i == this.players.size() - 1) ? "" : ", "); } - - if (players.isEmpty()) { + + if (players.isEmpty()) + { list = "<nobody>"; } - + return list; - } + } /** * @return the jumpFlag */ - public boolean isJumpFlag() { + public boolean isJumpFlag() + { return jumpFlag; } /** * @param jumpFlag the jumpFlag to set */ - public void setJumpFlag(boolean jumpFlag) { + public void setJumpFlag(boolean jumpFlag) + { this.jumpFlag = jumpFlag; } /** * @return the front */ - public int getFront() { + public int getFront() + { return front; } /** * @param front the front to set */ - public void setFront(int front) { + public void setFront(int front) + { this.front = front; } /** * @return the right */ - public int getRight() { + public int getRight() + { return right; } /** * @param right the right to set */ - public void setRight(int right) { + public void setRight(int right) + { this.right = right; } /** * @return the up */ - public int getUp() { + public int getUp() + { return up; } /** * @param up the up to set */ - public void setUp(int up) { + public void setUp(int up) + { this.up = up; } /** * @return the back */ - public int getBack() { + public int getBack() + { return back; } /** * @param back the back to set */ - public void setBack(int back) { + public void setBack(int back) + { this.back = back; } /** * @return the left */ - public int getLeft() { + public int getLeft() + { return left; } /** * @param left the left to set */ - public void setLeft(int left) { + public void setLeft(int left) + { this.left = left; } /** * @return the down */ - public int getDown() { + public int getDown() + { return down; } /** * @param down the down to set */ - public void setDown(int down) { + public void setDown(int down) + { this.down = down; } - - public void setDistance(int distance) { + + public void setDistance(int distance) + { this.distance = distance; } - - public int getDistance() { + + public int getDistance() + { return this.distance; } /** * @return the mode */ - public int getMode() { + public int getMode() + { return mode; } /** * @return the direction */ - public int getDirection() { + public int getDirection() + { return direction; } /** * @return the summonFlag */ - public boolean isSummonAllFlag() { + public boolean isSummonAllFlag() + { return summonFlag; } /** * @param summonFlag the summonFlag to set */ - public void setSummonAllFlag(boolean summonFlag) { + public void setSummonAllFlag(boolean summonFlag) + { this.summonFlag = summonFlag; } @Override - public String getType() { + public String getType() + { return "warpcore"; } @Override - public String[] getMethodNames() { + public String[] getMethodNames() + { return (methodsArray); } @Override - public boolean canAttachToSide(int side) { + public boolean canAttachToSide(int side) + { return true; } @Override - public void attach(IComputerAccess computer) { - + public void attach(IComputerAccess computer) + { } @Override - public void detach(IComputerAccess computer) { - + public void detach(IComputerAccess computer) + { } /** * @return the toSummon */ - public String getToSummon() { + public String getToSummon() + { return toSummon; } /** * @param toSummon the toSummon to set */ - public void setToSummon(String toSummon) { + public void setToSummon(String toSummon) + { this.toSummon = toSummon; } /** * @return the beaconFrequency */ - public String getBeaconFrequency() { + public String getBeaconFrequency() + { return beaconFrequency; } /** * @param beaconFrequency the beaconFrequency to set */ - public void setBeaconFrequency(String beaconFrequency) { + public void setBeaconFrequency(String beaconFrequency) + { //System.out.println("Setting beacon freqency: " + beaconFrequency); this.beaconFrequency = beaconFrequency; } - - public TileEntity findCoreBlock() { + + public TileEntity findCoreBlock() + { this.core = worldObj.getBlockTileEntity(xCoord + 1, yCoord, zCoord); - if (this.core != null && this.core instanceof TileEntityReactor) { + + if (this.core != null && this.core instanceof TileEntityReactor) + { return this.core; } this.core = worldObj.getBlockTileEntity(xCoord - 1, yCoord, zCoord); - if (this.core != null && this.core instanceof TileEntityReactor) { + + if (this.core != null && this.core instanceof TileEntityReactor) + { return this.core; } this.core = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord + 1); - if (this.core != null && this.core instanceof TileEntityReactor) { + + if (this.core != null && this.core instanceof TileEntityReactor) + { return this.core; } this.core = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord - 1); - if (this.core != null && this.core instanceof TileEntityReactor) { + + if (this.core != null && this.core instanceof TileEntityReactor) + { return this.core; } return null; - } + } @Override - public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception { + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception + { //System.out.println("[ProtoBlock] Method " + method + " " + methodsArray[method] + " called!"); - switch (method) { case 0: // dim_getp () - return new Integer[] { getFront(), getRight(), getUp() }; - + return new Integer[] { getFront(), getRight(), getUp() }; case 1: // dim_setp (front, right, up) - if (arguments.length != 3 || (((Double)arguments[0]).intValue() < 0 || ((Double)arguments[1]).intValue() < 0 || ((Double)arguments[2]).intValue() < 0)) { + if (arguments.length != 3 || (((Double)arguments[0]).intValue() < 0 || ((Double)arguments[1]).intValue() < 0 || ((Double)arguments[2]).intValue() < 0)) + { return new Integer[] { -1 }; } @@ -428,17 +488,14 @@ public class TileEntityProtocol extends TileEntity implements IPeripheral { setFront(((Double)arguments[0]).intValue()); setRight(((Double)arguments[1]).intValue()); setUp(((Double)arguments[2]).intValue()); - WarpDrive.instance.registry.removeDeadCores(); break; - - case 2: // dim_getn () - return new Integer[] { getBack(), getLeft(), getDown() }; - + return new Integer[] { getBack(), getLeft(), getDown() }; case 3: // dim_setn (back, left, down) - if (arguments.length != 3 || (((Double)arguments[0]).intValue() < 0 || ((Double)arguments[1]).intValue() < 0 || ((Double)arguments[2]).intValue() < 0)) { + if (arguments.length != 3 || (((Double)arguments[0]).intValue() < 0 || ((Double)arguments[1]).intValue() < 0 || ((Double)arguments[2]).intValue() < 0)) + { return new Integer[] { -1 }; } @@ -446,132 +503,147 @@ public class TileEntityProtocol extends TileEntity implements IPeripheral { setBack(((Double)arguments[0]).intValue()); setLeft(((Double)arguments[1]).intValue()); setDown(((Double)arguments[2]).intValue()); - WarpDrive.instance.registry.removeDeadCores(); - - break; - - - + break; + case 4: // set_mode (mode) - if (arguments.length != 1) { - return new Integer[] { -1 }; + if (arguments.length != 1) + { + return new Integer[] { -1 }; } setMode(((Double)arguments[0]).intValue()); break; - + case 5: // set_distance (distance) - if (arguments.length != 1) { - return new Integer[] { -1 }; + if (arguments.length != 1) + { + return new Integer[] { -1 }; } setJumpDistance(((Double)arguments[0]).intValue()); - break; - + break; + case 6: // set_direction (dir) - if (arguments.length != 1) { - return new Integer[] { -1 }; + if (arguments.length != 1) + { + return new Integer[] { -1 }; } setDirection(((Double)arguments[0]).intValue()); break; - + case 7: // get_attached_players String list = ""; - for (int i = 0; i < this.players.size(); i++) { + for (int i = 0; i < this.players.size(); i++) + { String nick = this.players.get(i); - - list += nick + ((i == this.players.size() - 1)? "" : ","); + list += nick + ((i == this.players.size() - 1) ? "" : ","); } - if (players.isEmpty()) { + if (players.isEmpty()) + { list = ""; } - + return new Object[] { (String)list }; - + case 8: // summon - if (arguments.length != 1) { + if (arguments.length != 1) + { return new Integer[] { -1 }; } - + int playerID = ((Double)arguments[0]).intValue(); - - if (playerID >= 0 && playerID < players.size()) { + + if (playerID >= 0 && playerID < players.size()) + { setToSummon(players.get(playerID)); } - + break; - + case 9: // summon_all this.setSummonAllFlag(true); - + case 10: // get_x - if (core == null) { + if (core == null) + { return null; } + return new Object[] { (Integer)core.xCoord }; case 11: // get_y - if (core == null) { + if (core == null) + { return null; } + return new Object[] { (Integer)core.yCoord }; - + case 12: // get_z - if (core == null) { + if (core == null) + { return null; - } - return new Object[] { (Integer)core.zCoord }; - + } + + return new Object[] { (Integer)core.zCoord }; + case 13: - if (core != null) + if (core != null) { return new Object[] { (Integer)((TileEntityReactor)core).currentEnergyValue }; } - - return null; - + + return null; + case 14: // do_jump doJump(); break; - + case 15: // get_ship_size - if (core != null) + if (core != null) { ((TileEntityReactor)core).calculateSpatialShipParameters(); return new Object[] { (Integer)((TileEntityReactor)core).getRealShipVolume() }; } + break; - + case 16: // set_beacon_frequency if (arguments.length == 1) { setBeaconFrequency((String)arguments[0]); } + break; - + case 17: // get_dx - if (core != null && core instanceof TileEntityReactor) { - return new Object[] { (Integer)(((TileEntityReactor)core).dx) }; + if (core != null && core instanceof TileEntityReactor) + { + return new Object[] { (Integer)(((TileEntityReactor)core).dx) }; } + break; case 18: // get_dz - if (core != null && core instanceof TileEntityReactor) { - return new Object[] { (Integer)(((TileEntityReactor)core).dz) }; + if (core != null && core instanceof TileEntityReactor) + { + return new Object[] { (Integer)(((TileEntityReactor)core).dz) }; } - break; + + break; case 19: // set_core_frequency if (arguments.length == 1 && (core != null && core instanceof TileEntityReactor)) { ((TileEntityReactor)core).coreFrequency = ((String)arguments[0]); } - break; - + + break; + case 20: // is_in_space return new Boolean[] { worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID }; case 21: // is_in_hyperspace @@ -581,24 +653,26 @@ public class TileEntityProtocol extends TileEntity implements IPeripheral { { setTargetJumpgateName((String)arguments[0]); } - break; - + + break; } - + return new Integer[] { 0 }; } /** * @return the targetJumpgateName */ - public String getTargetJumpgateName() { + public String getTargetJumpgateName() + { return targetJumpgateName; } /** * @param targetJumpgateName the targetJumpgateName to set */ - public void setTargetJumpgateName(String targetJumpgateName) { + public void setTargetJumpgateName(String targetJumpgateName) + { this.targetJumpgateName = targetJumpgateName; } } diff --git a/src/cr0s/WarpDrive/TileEntityRadar.java b/src/cr0s/WarpDrive/TileEntityRadar.java index a879424d..3b04ea9b 100644 --- a/src/cr0s/WarpDrive/TileEntityRadar.java +++ b/src/cr0s/WarpDrive/TileEntityRadar.java @@ -1,14 +1,12 @@ package cr0s.WarpDrive; -import cr0s.WarpDrive.TileEntityReactor; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cr0s.WarpDrive.WarpDrive; import dan200.computer.api.IComputerAccess; import dan200.computer.api.ILuaContext; import dan200.computer.api.IPeripheral; -import ic2.api.Direction; +import net.minecraftforge.common.ForgeDirection; import ic2.api.energy.event.EnergyTileLoadEvent; import ic2.api.energy.event.EnergyTileUnloadEvent; import ic2.api.energy.tile.IEnergySink; @@ -24,185 +22,217 @@ import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.DamageSource; import net.minecraftforge.common.MinecraftForge; -public class TileEntityRadar extends TileEntity implements IPeripheral, IEnergySink { - +public class TileEntityRadar extends TileEntity implements IPeripheral, IEnergySink +{ public boolean addedToEnergyNet = false; - + private final int MAX_ENERGY_VALUE = 100 * (1000 * 1000); // 100 000 000 Eu private int currentEnergyValue = 0; - - private String[] methodsArray = { - "scanRay", // 0 - "scanRadiusW", // 1 - "getResultsCountW", // 2 - "getResultW", // 3 - "getEnergyLevel", // 4 - - "getRadarX", "getRadarY", "getRadarZ", // 5, 6, 7 - }; - + + private String[] methodsArray = + { + "scanRay", // 0 + "scanRadiusW", // 1 + "getResultsCountW", // 2 + "getResultW", // 3 + "getEnergyLevel", // 4 + + "getRadarX", "getRadarY", "getRadarZ", // 5, 6, 7 + }; + private ArrayList<TileEntityReactor> results; - + private int scanRadius = 0; private int cooldownTime = 0; - - private boolean isEnergyEnoughForScanRadiusW(int radius) { + + private boolean isEnergyEnoughForScanRadiusW(int radius) + { int needEnergy = (radius * radius); - return ((getCurrentEnergyValue() - needEnergy) > 0); } - + @Override - public void updateEntity() { - if (!addedToEnergyNet && !this.tileEntityInvalid) { + public void updateEntity() + { + if (!addedToEnergyNet && !this.tileEntityInvalid) + { MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this)); addedToEnergyNet = true; } - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { + + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { return; } - try { - if (worldObj.getBlockMetadata(xCoord, yCoord, zCoord) == 2) { - if (cooldownTime++ > (20 * ((scanRadius / 1000) + 1))) { + + try + { + if (worldObj.getBlockMetadata(xCoord, yCoord, zCoord) == 2) + { + if (cooldownTime++ > (20 * ((scanRadius / 1000) + 1))) + { //System.out.println("Scanning..."); WarpDrive.instance.registry.removeDeadCores(); results = WarpDrive.instance.registry.searchWarpCoresInRadius(xCoord, yCoord, zCoord, scanRadius); worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1, 1 + 2); - cooldownTime = 0; } } - } catch (Exception e) { e.printStackTrace(); } + } + catch (Exception e) + { + e.printStackTrace(); + } } - + @Override - public void readFromNBT(NBTTagCompound tag) { + public void readFromNBT(NBTTagCompound tag) + { super.readFromNBT(tag); - this.currentEnergyValue = tag.getInteger("energy"); } @Override - public void writeToNBT(NBTTagCompound tag) { + public void writeToNBT(NBTTagCompound tag) + { super.writeToNBT(tag); - tag.setInteger("energy", this.getCurrentEnergyValue()); - } - + } + // IPeripheral methods implementation @Override - public String getType() { + public String getType() + { return "radar"; } @Override - public String[] getMethodNames() { + public String[] getMethodNames() + { return methodsArray; } @Override - public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception { - switch (method) { + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception + { + switch (method) + { case 0: // scanRay (toX, toY, toZ) return new Object[] { -1 }; - case 1: // scanRadiusW (radius) - if (arguments.length == 1) { + if (arguments.length == 1) + { int radius; - - try { + + try + { radius = ((Double)arguments[0]).intValue(); - } catch (Exception e) { radius = 0; } - - if (radius < 0 || radius > 10000) { + } + catch (Exception e) + { + radius = 0; + } + + if (radius < 0 || radius > 10000) + { scanRadius = 0; return new Object[] { 0 }; } - - if (radius != 0 && isEnergyEnoughForScanRadiusW(radius)) { + + if (radius != 0 && isEnergyEnoughForScanRadiusW(radius)) + { // Consume energy this.currentEnergyValue -= radius * radius; - // Begin searching scanRadius = radius; cooldownTime = 0; worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 2, 1 + 2); - } else { + } + else + { results = null; System.out.println("Radius: " + radius + " | Enough energy: " + isEnergyEnoughForScanRadiusW(radius)); } } - + return new Object[] { 0 }; - + case 2: // getResultsCountW - if (results != null) { + if (results != null) + { return new Integer[] { results.size() }; } - + break; - + case 3: // getResultW - if (arguments.length == 1 && (results != null)) { + if (arguments.length == 1 && (results != null)) + { int index; - - try { + + try + { index = ((Double)arguments[0]).intValue(); - } catch (Exception e) { index = -1; } - - if (index > -1 && index < results.size()) { - + } + catch (Exception e) + { + index = -1; + } + + if (index > -1 && index < results.size()) + { TileEntityReactor res = results.get(index); int yAddition = (res.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID) ? 255 : (res.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) ? 512 : 0; return new Object[] { ((String)res.coreFrequency), ((Integer)res.xCoord), ((Integer)res.yCoord + yAddition), ((Integer)res.zCoord) }; } } - + case 4: // getEnergyLevel return new Integer[] { this.getCurrentEnergyValue()}; - case 5: // getRadarX return new Integer[] { this.xCoord }; - case 6: // getRadarY return new Integer[] { this.yCoord }; - case 7: // getRadarZ return new Integer[] { this.zCoord }; - } - + return new Object[] { 0 }; } @Override - public boolean canAttachToSide(int side) { + public boolean canAttachToSide(int side) + { return true; } @Override - public void attach(IComputerAccess computer) { + public void attach(IComputerAccess computer) + { worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1, 1 + 2); } @Override - public void detach(IComputerAccess computer) { + public void detach(IComputerAccess computer) + { worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 1 + 2); } // IEnergySink methods implementation @Override - public int demandsEnergy() { + public double demandedEnergyUnits() + { return (MAX_ENERGY_VALUE - currentEnergyValue); } @Override - public int injectEnergy(Direction directionFrom, int amount) { - // Р�збыток энергии - int leftover = 0; + public double injectEnergyUnits(ForgeDirection directionFrom, double amount) + { + double leftover = 0; + currentEnergyValue += Math.round(amount); - currentEnergyValue += amount; - if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) { + if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) + { leftover = (getCurrentEnergyValue() - MAX_ENERGY_VALUE); currentEnergyValue = MAX_ENERGY_VALUE; } @@ -211,42 +241,44 @@ public class TileEntityRadar extends TileEntity implements IPeripheral, IEnergyS } @Override - public int getMaxSafeInput() { + public int getMaxSafeInput() + { return Integer.MAX_VALUE; } @Override - public boolean acceptsEnergyFrom(TileEntity emitter, Direction direction) { + public boolean acceptsEnergyFrom(TileEntity emitter, ForgeDirection direction) + { return true; } - @Override - public boolean isAddedToEnergyNet() { - return addedToEnergyNet; - } - /** * @return the currentEnergyValue */ - public int getCurrentEnergyValue() { + public int getCurrentEnergyValue() + { return currentEnergyValue; } - @Override - public void onChunkUnload() { - if (addedToEnergyNet) { + @Override + public void onChunkUnload() + { + if (addedToEnergyNet) + { MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); addedToEnergyNet = false; - } + } } - - @Override - public void invalidate() { - if (addedToEnergyNet) { + + @Override + public void invalidate() + { + if (addedToEnergyNet) + { MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); addedToEnergyNet = false; - } - + } + super.invalidate(); - } + } } diff --git a/src/cr0s/WarpDrive/TileEntityReactor.java b/src/cr0s/WarpDrive/TileEntityReactor.java index cf945ddc..c844ca15 100644 --- a/src/cr0s/WarpDrive/TileEntityReactor.java +++ b/src/cr0s/WarpDrive/TileEntityReactor.java @@ -1,12 +1,10 @@ package cr0s.WarpDrive; import cpw.mods.fml.common.FMLCommonHandler; -import cr0s.WarpDrive.WarpDrive; -import ic2.api.Direction; +import net.minecraftforge.common.ForgeDirection; import ic2.api.energy.event.EnergyTileLoadEvent; import ic2.api.energy.event.EnergyTileUnloadEvent; import ic2.api.energy.tile.IEnergySink; -import ic2.api.network.NetworkHelper; import java.util.List; @@ -30,8 +28,8 @@ import net.minecraftforge.common.MinecraftForge; /** * @author Cr0s */ -public class TileEntityReactor extends TileEntity implements IEnergySink { - +public class TileEntityReactor extends TileEntity implements IEnergySink +{ public boolean addedToEnergyNet = false; public Boolean ready; @@ -44,9 +42,9 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { public final int JUMP_UP = -1; public final int JUMP_DOWN = -2; - int dx, dz; - int direction; - int distance; + int dx, dz; + int direction; + int distance; public int maxX, maxY, maxZ; public int minX, minY, minZ; @@ -56,16 +54,16 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { public int shipUp, shipDown; public int shipHeight, shipWidth, shipLength; int shipSize = 0; - int shipVolume; + int shipVolume; int currentMode = 0; - - int currentEnergyValue = 0; + + int currentEnergyValue = 0; int maxEnergyValue = 100000000; - + private final int ENERGY_PER_BLOCK_MODE1 = 10; // eU private final int ENERGY_PER_DISTANCE_MODE1 = 100; // eU private final int ENERGY_PER_BLOCK_MODE2 = 1000; // eU - private final int ENERGY_PER_DISTANCE_MODE2 = 1000; // eU + private final int ENERGY_PER_DISTANCE_MODE2 = 1000; // eU private final int ENERGY_PER_ENTITY_TO_SPACE = 1000000; // eU private final byte MODE_BASIC_JUMP = 1; // 0-128 private final byte MODE_LONG_JUMP = 2; // 0-12800 @@ -75,51 +73,57 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { private final byte MODE_GATE_JUMP = 6; // Jump via jumpgate private final int MAX_JUMP_DISTANCE = 128; // Maximum jump length value private final int MAX_SHIP_VOLUME_ON_SURFACE = 15000; // Maximum ship mass to jump on earth (15k blocks) - private final int MIN_SHIP_VOLUME_FOR_HYPERSPACE = 500; // Minimum ship volume value for - + private final int MIN_SHIP_VOLUME_FOR_HYPERSPACE = 500; // Minimum ship volume value for + public final int MAX_SHIP_SIDE = 100; int cooldownTime = 0; private final int COOLDOWN_INTERVAL_SECONDS = 4; public int randomCooldownAddition = 0; - + private final int CORES_REGISTRY_UPDATE_INTERVAL_SECONDS = 10; private int registryUpdateTicks = 0; public String coreFrequency = "default"; - + public int isolationBlocksCount = 0; public int isolationUpdateTicks = 0; private final int ISOLATION_UPDATE_INTARVAL_SECONDS = 10; - - public String coreState = ""; + + public String coreState = ""; public TileEntityProtocol controller; - + private boolean soundPlayed = false; - + @Override - public void updateEntity() { - if (!FMLCommonHandler.instance().getEffectiveSide().isClient() && !addedToEnergyNet) { + public void updateEntity() + { + if (!FMLCommonHandler.instance().getEffectiveSide().isClient() && !addedToEnergyNet) + { MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this)); addedToEnergyNet = true; } // Update warp core in cores registry - if (++registryUpdateTicks > CORES_REGISTRY_UPDATE_INTERVAL_SECONDS * 20) { + if (++registryUpdateTicks > CORES_REGISTRY_UPDATE_INTERVAL_SECONDS * 20) + { registryUpdateTicks = 0; - WarpDrive.instance.registry.updateInRegistry(this); } if (FMLCommonHandler.instance().getEffectiveSide().isClient()) - return; - - if (++isolationUpdateTicks > ISOLATION_UPDATE_INTARVAL_SECONDS * 20) { + { + return; + } + + if (++isolationUpdateTicks > ISOLATION_UPDATE_INTARVAL_SECONDS * 20) + { isolationUpdateTicks = 0; updateIsolationState(); } - + TileEntity c = findControllerBlock(); - - if (c != null) { + + if (c != null) + { this.controller = (TileEntityProtocol)c; this.currentMode = controller.getMode(); shipFront = controller.getFront(); @@ -128,245 +132,297 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { shipBack = controller.getBack(); shipLeft = controller.getLeft(); shipDown = controller.getDown(); - - if (this.controller.isSummonAllFlag()) { + + if (this.controller.isSummonAllFlag()) + { summonPlayers(); controller.setSummonAllFlag(false); - } else if (!this.controller.getToSummon().isEmpty()) { + } + else if (!this.controller.getToSummon().isEmpty()) + { summonSinglePlayer(this.controller.getToSummon()); this.controller.setToSummon(""); } - } else { + } + else + { invalidAssembly = true; return; } - - switch (currentMode) { + + switch (currentMode) + { case MODE_TELEPORT: - if (isChestSummonMode()) { - if (ticks++ < 20) { + if (isChestSummonMode()) + { + if (ticks++ < 20) + { return; - } - - if (worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord)) { + } + + if (worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord)) + { summonPlayersByChestCode(); ticks = 0; } - } else { + } + else + { teleportPlayersToSpace(); } + break; + case MODE_BASIC_JUMP: case MODE_LONG_JUMP: - case MODE_BEACON_JUMP: + case MODE_BEACON_JUMP: case MODE_HYPERSPACE: case MODE_GATE_JUMP: - if (controller == null) { return; } + if (controller == null) + { + return; + } + coreState = "Energy level: " + currentEnergyValue + " Eu"; - - if (controller.isJumpFlag()) { + + if (controller.isJumpFlag()) + { // Set up activated animation if (worldObj.getBlockMetadata(xCoord, yCoord, zCoord) == 0) { // TODO: check for "warpcore turns into dirt" bug - worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1, 1 + 2); // Set block state to "active" + worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1, 1 + 2); // Set block state to "active" makePlayersOnShipDrunk(); } - - if (!soundPlayed) { + + if (!soundPlayed) + { worldObj.playSoundEffect(xCoord + 0.5f, yCoord + 0.5f, zCoord + 0.5f, "warpdrive:warp", 4F, 1F); this.soundPlayed = true; } + // Awaiting cooldown time if (/*currentMode != MODE_BASIC_JUMP && */cooldownTime++ < ((COOLDOWN_INTERVAL_SECONDS) * 20) + randomCooldownAddition) { return; } - + cooldownTime = 0; soundPlayed = false; - - if (!prepareToJump()) { - return; + + if (!prepareToJump()) + { + return; } - - if (WarpDrive.instance.registry.isWarpCoreIntersectsWithOthers(this)) { + + if (WarpDrive.instance.registry.isWarpCoreIntersectsWithOthers(this)) + { this.controller.setJumpFlag(false); messageToAllPlayersOnShip("Warp field intersects with other ship's field. Cannot jump."); - return; + return; } - - System.out.println("[W-C] Jumping!"); + System.out.println("[W-C] Jumping!"); doJump(); - controller.setJumpFlag(false); - } else + } + else { worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 1 + 2); // Deactivate block animation } + break; } } - - public void messageToAllPlayersOnShip(String msg) { + + public void messageToAllPlayersOnShip(String msg) + { AxisAlignedBB axisalignedbb = AxisAlignedBB.getBoundingBox(this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ); - - List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, axisalignedbb); - for (Object o : list) { - if (o == null || !(o instanceof EntityPlayer)) { + List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, axisalignedbb); + + for (Object o : list) + { + if (o == null || !(o instanceof EntityPlayer)) + { continue; } - + System.out.println(msg); ((EntityPlayer)o).addChatMessage("[WarpCore] " + msg); } - } - - public void updateIsolationState() { + } + + public void updateIsolationState() + { // Search block in cube around core with side 10 int xmax, ymax, zmax, x1, x2, z1, z2; int xmin, ymin, zmin; - final int ISOLATION_CUBE_SIDE = 6; - - x1 = xCoord + ((ISOLATION_CUBE_SIDE / 2) -1); - x2 = xCoord - ((ISOLATION_CUBE_SIDE / 2) -1); - - if (x1 < x2) { + x1 = xCoord + ((ISOLATION_CUBE_SIDE / 2) - 1); + x2 = xCoord - ((ISOLATION_CUBE_SIDE / 2) - 1); + + if (x1 < x2) + { xmin = x1; xmax = x2; - } else + } + else { xmin = x2; xmax = x1; } - z1 = zCoord + ((ISOLATION_CUBE_SIDE / 2) -1); - z2 = zCoord - ((ISOLATION_CUBE_SIDE / 2) -1); - - if (z1 < z2) { + z1 = zCoord + ((ISOLATION_CUBE_SIDE / 2) - 1); + z2 = zCoord - ((ISOLATION_CUBE_SIDE / 2) - 1); + + if (z1 < z2) + { zmin = z1; zmax = z2; - } else + } + else { zmin = z2; zmax = z1; } - ymax = yCoord + ((ISOLATION_CUBE_SIDE / 2) -1); - ymin = yCoord - ((ISOLATION_CUBE_SIDE / 2) -1); - + ymax = yCoord + ((ISOLATION_CUBE_SIDE / 2) - 1); + ymin = yCoord - ((ISOLATION_CUBE_SIDE / 2) - 1); this.isolationBlocksCount = 0; - + // Search for warp isolation blocks - for (int y = ymin; y <= ymax; y++) { - for (int x = xmin; x <= xmax; x++) { - for (int z = zmin; z <= zmax; z++) { - if (worldObj.getBlockId(x, y, z) == WarpDrive.instance.config.isolationID) { + for (int y = ymin; y <= ymax; y++) + { + for (int x = xmin; x <= xmax; x++) + { + for (int z = zmin; z <= zmax; z++) + { + if (worldObj.getBlockId(x, y, z) == WarpDrive.instance.config.isolationID) + { this.isolationBlocksCount++; } } } } } - - public void makePlayersOnShipDrunk() { - if (!prepareToJump()) { return; } - + + public void makePlayersOnShipDrunk() + { + if (!prepareToJump()) + { + return; + } + AxisAlignedBB axisalignedbb = AxisAlignedBB.getBoundingBox(this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ); - - List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, axisalignedbb); - for (Object o : list) { - if (o == null || !(o instanceof EntityPlayer)) { + List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, axisalignedbb); + + for (Object o : list) + { + if (o == null || !(o instanceof EntityPlayer)) + { continue; } - + // Set "drunk" effect ((EntityPlayer)o).addPotionEffect(new PotionEffect(Potion.confusion.id, 180, 0, true)); } } - - public void summonPlayers() { + + public void summonPlayers() + { calculateSpatialShipParameters(); AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ); - for (int i = 0; i < controller.players.size(); i++) { + for (int i = 0; i < controller.players.size(); i++) + { String nick = controller.players.get(i); EntityPlayerMP player = MinecraftServer.getServer().getConfigurationManager().getPlayerForUsername(nick); - if (player != null && !testBB(aabb, MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ))) { + if (player != null && !testBB(aabb, MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ))) + { summonPlayer(player, xCoord + dx, yCoord, zCoord + dz); } } } - - public void summonSinglePlayer(String nickname) { + + public void summonSinglePlayer(String nickname) + { calculateSpatialShipParameters(); AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ); - for (int i = 0; i < controller.players.size(); i++) { + for (int i = 0; i < controller.players.size(); i++) + { String nick = controller.players.get(i); EntityPlayerMP player = MinecraftServer.getServer().getConfigurationManager().getPlayerForUsername(nick); - if (player != null && nick.equals(nickname) && !testBB(aabb, MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ))) { + if (player != null && nick.equals(nickname) && !testBB(aabb, MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ))) + { summonPlayer(player, xCoord + dx, yCoord, zCoord + dz); return; } - } + } } - - public void summonPlayer(EntityPlayerMP player, int x, int y, int z) { - if (this.currentEnergyValue - this.ENERGY_PER_ENTITY_TO_SPACE >= 0) { - player.setPositionAndUpdate(x, y, z); - if (player.dimension != worldObj.provider.dimensionId) { - player.mcServer.getConfigurationManager().transferPlayerToDimension(player, this.worldObj.provider.dimensionId, new SpaceTeleporter(DimensionManager.getWorld(this.worldObj.provider.dimensionId), 0, MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ))); - } + public void summonPlayer(EntityPlayerMP player, int x, int y, int z) + { + if (this.currentEnergyValue - this.ENERGY_PER_ENTITY_TO_SPACE >= 0) + { + player.setPositionAndUpdate(x, y, z); - this.currentEnergyValue -= this.ENERGY_PER_ENTITY_TO_SPACE; - } + if (player.dimension != worldObj.provider.dimensionId) + { + player.mcServer.getConfigurationManager().transferPlayerToDimension(player, this.worldObj.provider.dimensionId, new SpaceTeleporter(DimensionManager.getWorld(this.worldObj.provider.dimensionId), 0, MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ))); + } + + this.currentEnergyValue -= this.ENERGY_PER_ENTITY_TO_SPACE; + } } - - public boolean prepareToJump() { + + public boolean prepareToJump() + { this.direction = controller.getDirection(); - this.shipFront = controller.getFront(); this.shipRight = controller.getRight(); this.shipUp = controller.getUp(); - this.shipBack = controller.getBack(); this.shipLeft = controller.getLeft(); this.shipDown = controller.getDown(); - this.distance = Math.min(this.MAX_JUMP_DISTANCE, controller.getDistance()); - return calculateSpatialShipParameters(); } - - - public boolean calculateSpatialShipParameters() { + + public boolean calculateSpatialShipParameters() + { int x1 = 0, x2 = 0, z1 = 0, z2 = 0; - if (Math.abs(dx) > 0) { - if (dx == 1) { + if (Math.abs(dx) > 0) + { + if (dx == 1) + { x1 = xCoord - shipBack; x2 = xCoord + shipFront; z1 = zCoord - shipLeft; z2 = zCoord + shipRight; - } else { + } + else + { x1 = xCoord - shipFront; x2 = xCoord + shipBack; z1 = zCoord - shipRight; z2 = zCoord + shipLeft; } - } else if (Math.abs(dz) > 0) { - if (dz == 1) { + } + else if (Math.abs(dz) > 0) + { + if (dz == 1) + { z1 = zCoord - shipBack; z2 = zCoord + shipFront; x1 = xCoord - shipRight; x2 = xCoord + shipLeft; - } else { + } + else + { z1 = zCoord - shipFront; z2 = zCoord + shipBack; x1 = xCoord - shipLeft; @@ -374,84 +430,95 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { } } - if (x1 < x2) { + if (x1 < x2) + { minX = x1; maxX = x2; - } else { + } + else + { minX = x2; maxX = x1; } - if (z1 < z2) { + if (z1 < z2) + { minZ = z1; maxZ = z2; - } else { + } + else + { minZ = z2; maxZ = z1; } minY = yCoord - shipDown; maxY = yCoord + shipUp; - this.shipSize = 0; - - switch (this.direction) { + + switch (this.direction) + { case 0: case 180: this.shipSize = this.shipBack + this.shipFront; break; + case 90: - case 270: + case 270: this.shipSize = this.shipLeft + shipRight; break; - + case -1: case -2: this.shipSize = this.shipDown + this.shipUp; - break; + break; } - + // Ship side is too big - if (shipLength > MAX_SHIP_SIDE || shipWidth > MAX_SHIP_SIDE || shipHeight > MAX_SHIP_SIDE) { - this.controller.setJumpFlag(false); - return false; - } - - this.shipVolume = getRealShipVolume(); - - if (shipVolume > MAX_SHIP_VOLUME_ON_SURFACE && worldObj.provider.dimensionId == 0) { + if (shipLength > MAX_SHIP_SIDE || shipWidth > MAX_SHIP_SIDE || shipHeight > MAX_SHIP_SIDE) + { this.controller.setJumpFlag(false); return false; - } - + } + + this.shipVolume = getRealShipVolume(); + + if (shipVolume > MAX_SHIP_VOLUME_ON_SURFACE && worldObj.provider.dimensionId == 0) + { + this.controller.setJumpFlag(false); + return false; + } + return true; } - private void doBeaconJump() { + private void doBeaconJump() + { if (currentEnergyValue - calculateRequiredEnergy(shipVolume, distance) < 0) { System.out.println("[WP-TE] Insufficient energy to jump"); this.controller.setJumpFlag(false); return; } - + // Search beacon coordinates String freq = controller.getBeaconFrequency(); int beaconX = 0, beaconZ = 0; boolean isBeaconFound = false; - EntityPlayerMP player; + for (int i = 0; i < MinecraftServer.getServer().getConfigurationManager().playerEntityList.size(); i++) { player = (EntityPlayerMP)MinecraftServer.getServer().getConfigurationManager().playerEntityList.get(i); - + // Skip players from other dimensions - if (player.dimension != worldObj.provider.dimensionId) { + if (player.dimension != worldObj.provider.dimensionId) + { continue; } - + TileEntity te = worldObj.getBlockTileEntity(MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY) - 1, MathHelper.floor_double(player.posZ)); - + if (te != null && (te instanceof TileEntityProtocol)) { if (((TileEntityProtocol)te).getBeaconFrequency().equals(freq)) @@ -463,23 +530,20 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { } } } - + // Now make jump to a beacon if (isBeaconFound) { // Consume all energy currentEnergyValue -= calculateRequiredEnergy(shipVolume, distance); - System.out.println("[TE-WC] Moving ship to a beacon (" + beaconX + "; " + yCoord + "; " + beaconZ + ")"); EntityJump jump = new EntityJump(worldObj, xCoord, yCoord, zCoord, 1, 0, dx, dz, this); - jump.maxX = maxX; jump.minX = minX; jump.maxZ = maxZ; jump.minZ = minZ; jump.maxY = maxY; jump.minY = minY; - jump.shipFront = shipFront; jump.shipBack = shipBack; jump.shipLeft = shipLeft; @@ -487,149 +551,164 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { jump.shipUp = shipUp; jump.shipDown = shipDown; jump.shipLength = this.shipSize; - jump.xCoord = xCoord; jump.yCoord = yCoord; jump.zCoord = zCoord; - jump.isCoordJump = true; // is jump to a beacon jump.destX = beaconX; jump.destY = yCoord; jump.destZ = beaconZ; - jump.on = true; - worldObj.spawnEntityInWorld(jump); - coreState = ""; - } else + coreState = ""; + } + else { System.out.println("[TE-WC] Beacon not found."); } - } + } - private boolean isShipInJumpgate(JumpGate jg) { + private boolean isShipInJumpgate(JumpGate jg) + { AxisAlignedBB aabb = jg.getGateAABB(); - System.out.println("Gate AABB: " + aabb); - int numBlocks = 0; - if (aabb.isVecInside(worldObj.getWorldVec3Pool().getVecFromPool(maxX - minX, maxY - minY, maxZ - minZ))) { + + if (aabb.isVecInside(worldObj.getWorldVec3Pool().getVecFromPool(maxX - minX, maxY - minY, maxZ - minZ))) + { return true; } - - for (int x = minX; x <= maxX; x++) { - for (int z = minZ; z <= maxZ; z++) { - for (int y = minY; y <= maxY; y++) { - if (!worldObj.isAirBlock(x, y, z)) { - if (aabb.minX <= x && aabb.maxX >= x && aabb.minY <= y && aabb.maxY >= y && aabb.minZ <= z && aabb.maxZ >= z) { + + for (int x = minX; x <= maxX; x++) + { + for (int z = minZ; z <= maxZ; z++) + { + for (int y = minY; y <= maxY; y++) + { + if (!worldObj.isAirBlock(x, y, z)) + { + if (aabb.minX <= x && aabb.maxX >= x && aabb.minY <= y && aabb.maxY >= y && aabb.minZ <= z && aabb.maxZ >= z) + { numBlocks++; } } } } - } - - if (numBlocks == 0) { - System.out.println("[GATE] Is 0 blocks inside gate."); + } + + if (numBlocks == 0) + { + System.out.println("[GATE] Is 0 blocks inside gate."); return false; - } - + } + System.out.println("[GATE] Ship volume: " + shipVolume + ", blocks in gate: " + numBlocks + ". Percentage: " + ((shipVolume / numBlocks) * 100)); - + // At least 80% of ship must be inside jumpgate - if (shipVolume / numBlocks > 0.8F) { + if (shipVolume / numBlocks > 0.8F) + { return true; } - + return false; } - - private boolean isFreePlaceForShip(int destX, int destY, int destZ) { + + private boolean isFreePlaceForShip(int destX, int destY, int destZ) + { int newX, newY, newZ; - - if (destY + shipUp > 255 || destY - shipDown < 5) { + + if (destY + shipUp > 255 || destY - shipDown < 5) + { return false; } - + int moveX = destX - xCoord; int moveY = destY - yCoord; int moveZ = destZ - zCoord; - - for (int x = minX; x <= maxX; x++) { - for (int z = minZ; z <= maxZ; z++) { - for (int y = minY; y <= maxY; y++) { - if (!worldObj.isAirBlock(x, y, z)) { + + for (int x = minX; x <= maxX; x++) + { + for (int z = minZ; z <= maxZ; z++) + { + for (int y = minY; y <= maxY; y++) + { + if (!worldObj.isAirBlock(x, y, z)) + { newX = moveX + x; newY = moveY + y; newZ = moveZ + z; - if (!worldObj.isAirBlock(newX, newY, newZ)) { + if (!worldObj.isAirBlock(newX, newY, newZ)) + { return false; } } } } - } - + } + return true; } - - private void doGateJump() { + + private void doGateJump() + { if (currentEnergyValue - calculateRequiredEnergy(shipVolume, distance) < 0) { System.out.println("[WP-TE] Insufficient energy to jump"); this.controller.setJumpFlag(false); return; } - + // Search beacon coordinates String gateName = controller.getTargetJumpgateName(); JumpGate jg = WarpDrive.instance.jumpGates.findGateByName(gateName); - int gateX, gateY, gateZ; int destX = 0, destY = 0, destZ = 0; boolean isGateFound = (jg != null); - + // Now make jump to a beacon if (isGateFound) { gateX = jg.xCoord; gateY = jg.yCoord; gateZ = jg.zCoord; - destX = gateX; destY = gateY; destZ = gateZ; JumpGate nearestGate = WarpDrive.instance.jumpGates.findNearestGate(xCoord, yCoord, zCoord); - - if (!isShipInJumpgate(nearestGate)) { + + if (!isShipInJumpgate(nearestGate)) + { messageToAllPlayersOnShip("[GATE] Ship is not inside the jumpgate. Jump rejected. Nearest jumpgate: " + nearestGate.toNiceString()); this.controller.setJumpFlag(false); return; } - - // If gate is blocked by obstacle - if (!isFreePlaceForShip(gateX, gateY, gateZ)) { + // If gate is blocked by obstacle + if (!isFreePlaceForShip(gateX, gateY, gateZ)) + { // Randomize destination coordinates and check for collision with obstacles around jumpgate // Try to find good place for ship int numTries = 10; // num tries to check for collision boolean placeFound = false; - for (; numTries > 0; numTries--) { - // randomize dest. coordinates around jumpgate - destX = gateX + ((worldObj.rand.nextBoolean())?-1:1) * (20 + worldObj.rand.nextInt(100)); - destZ = gateZ + ((worldObj.rand.nextBoolean())?-1:1) * (20 + worldObj.rand.nextInt(100)); - destY = gateY + ((worldObj.rand.nextBoolean())?-1:1) * (20 + worldObj.rand.nextInt(50)); + for (; numTries > 0; numTries--) + { + // randomize dest. coordinates around jumpgate + destX = gateX + ((worldObj.rand.nextBoolean()) ? -1 : 1) * (20 + worldObj.rand.nextInt(100)); + destZ = gateZ + ((worldObj.rand.nextBoolean()) ? -1 : 1) * (20 + worldObj.rand.nextInt(100)); + destY = gateY + ((worldObj.rand.nextBoolean()) ? -1 : 1) * (20 + worldObj.rand.nextInt(50)); // check for collision - if (isFreePlaceForShip(destX, destY, destZ)) { + if (isFreePlaceForShip(destX, destY, destZ)) + { placeFound = true; break; - } + } } - if (!placeFound) { + if (!placeFound) + { messageToAllPlayersOnShip("[GATE] Destination gate is blocked by obstacles. Cannot jump."); this.controller.setJumpFlag(false); return; @@ -637,20 +716,17 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { System.out.println("[GATE] Place found over " + (10 - numTries) + " tries."); } - + // Consume energy currentEnergyValue -= calculateRequiredEnergy(shipVolume, distance); - System.out.println("[TE-WC] Moving ship to a place around gate '" + jg.name + "' (" + destX + "; " + destY + "; " + destZ + ")"); EntityJump jump = new EntityJump(worldObj, xCoord, yCoord, zCoord, 1, 0, dx, dz, this); - jump.maxX = maxX; jump.minX = minX; jump.maxZ = maxZ; jump.minZ = minZ; jump.maxY = maxY; jump.minY = minY; - jump.shipFront = shipFront; jump.shipBack = shipBack; jump.shipLeft = shipLeft; @@ -658,91 +734,105 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { jump.shipUp = shipUp; jump.shipDown = shipDown; jump.shipLength = this.shipSize; - jump.xCoord = xCoord; jump.yCoord = yCoord; jump.zCoord = zCoord; - jump.isCoordJump = true; jump.destX = destX; jump.destY = destY; jump.destZ = destZ; - jump.on = true; - worldObj.spawnEntityInWorld(jump); - coreState = ""; - } else + coreState = ""; + } + else { messageToAllPlayersOnShip("[GATE] Destination jumpgate is not found. Check jumpgate name."); - this.controller.setJumpFlag(false); + this.controller.setJumpFlag(false); } - } - - - public void doJump() { - if (currentMode == this.MODE_GATE_JUMP) { + } + + public void doJump() + { + if (currentMode == this.MODE_GATE_JUMP) + { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + return; + } + System.out.println("[TE-WC] Performing gate jump..."); doGateJump(); - return; + return; } - + if (currentMode == this.MODE_BEACON_JUMP) { System.out.println("[TE-WC] Performing beacon jump..."); doBeaconJump(); return; - } - + } + // Check ship size for hyperspace jump - if (currentMode == this.MODE_HYPERSPACE) { - if (!isShipInJumpgate(WarpDrive.instance.jumpGates.findNearestGate(xCoord, yCoord, zCoord))) { - if (shipVolume < MIN_SHIP_VOLUME_FOR_HYPERSPACE) { + if (currentMode == this.MODE_HYPERSPACE) + { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + return; + } + + JumpGate t = WarpDrive.instance.jumpGates.findNearestGate(xCoord, yCoord, zCoord); + + if (t != null && !isShipInJumpgate(t)) + { + if (shipVolume < MIN_SHIP_VOLUME_FOR_HYPERSPACE) + { this.messageToAllPlayersOnShip("Ship is too small (" + shipVolume + "/" + MIN_SHIP_VOLUME_FOR_HYPERSPACE + "). Insufficient ship mass to open hyperspace portal."); this.controller.setJumpFlag(false); return; } } } - - if (currentMode == this.MODE_BASIC_JUMP || currentMode == this.MODE_LONG_JUMP || currentMode == MODE_HYPERSPACE) { + + if (currentMode == this.MODE_BASIC_JUMP || currentMode == this.MODE_LONG_JUMP || currentMode == MODE_HYPERSPACE) + { System.out.println("[WP-TE] Energy: " + currentEnergyValue + " eU"); System.out.println("[WP-TE] Need to jump: " + calculateRequiredEnergy(shipVolume, distance) + " eU"); - if (this.currentEnergyValue - calculateRequiredEnergy(shipVolume, distance) < 0) { + if (this.currentEnergyValue - calculateRequiredEnergy(shipVolume, distance) < 0) + { System.out.println("[WP-TE] Insufficient energy to jump"); this.controller.setJumpFlag(false); return; } this.currentEnergyValue -= calculateRequiredEnergy(shipVolume, distance); - System.out.println((new StringBuilder()).append("Jump params: X ").append(minX).append(" -> ").append(maxX).append(" blocks").toString()); System.out.println((new StringBuilder()).append("Jump params: Y ").append(minY).append(" -> ").append(maxY).append(" blocks").toString()); System.out.println((new StringBuilder()).append("Jump params: Z ").append(minZ).append(" -> ").append(maxZ).append(" blocks").toString()); //System.out.println("[WC-TE] Distance: " + distance + "; shipSize: " + shipSize); - if (this.currentMode == this.MODE_BASIC_JUMP) { - distance += shipSize; - } - - if (currentMode == this.MODE_LONG_JUMP && (direction != -1 && direction != -2)) { - if (worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) { + if (this.currentMode == this.MODE_BASIC_JUMP) + { + distance += shipSize; + } + + if (currentMode == this.MODE_LONG_JUMP && (direction != -1 && direction != -2)) + { + if (worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) + { distance *= 100; } } System.out.println((new StringBuilder()).append("[JUMP] Totally moving ").append((new StringBuilder()).append(shipVolume).append(" blocks to length ").append(distance).append(" blocks, direction: ").append(direction).toString()).toString()); - EntityJump jump = new EntityJump(worldObj, xCoord, yCoord, zCoord, distance, direction, dx, dz, this); - jump.maxX = maxX; jump.minX = minX; jump.maxZ = maxZ; jump.minZ = minZ; jump.maxY = maxY; jump.minY = minY; - jump.shipFront = shipFront; jump.shipBack = shipBack; jump.shipLeft = shipLeft; @@ -750,76 +840,76 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { jump.shipUp = shipUp; jump.shipDown = shipDown; jump.shipLength = this.shipSize; - jump.isCoordJump = false; - - if (currentMode == MODE_HYPERSPACE) { + + if (currentMode == MODE_HYPERSPACE) + { jump.toHyperSpace = (worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID); jump.fromHyperSpace = (worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID); - System.out.println("[JUMP] From HS: " + jump.fromHyperSpace + " | To HS: " + jump.fromHyperSpace); } - + jump.xCoord = xCoord; jump.yCoord = yCoord; jump.zCoord = zCoord; - jump.mode = currentMode; - jump.on = true; - worldObj.spawnEntityInWorld(jump); coreState = ""; } } - public void teleportPlayersToSpace() { - if (currentMode == MODE_TELEPORT && worldObj.provider.dimensionId != WarpDrive.instance.spaceDimID) { - if (worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord)) { + public void teleportPlayersToSpace() + { + if (currentMode == MODE_TELEPORT && worldObj.provider.dimensionId != WarpDrive.instance.spaceDimID) + { + if (worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord)) + { AxisAlignedBB axisalignedbb = AxisAlignedBB.getBoundingBox(xCoord - 5, yCoord - 5, zCoord - 5, xCoord + 5, yCoord + 5, zCoord + 5); List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, axisalignedbb); - for (Object o : list) { - if (currentEnergyValue - ENERGY_PER_ENTITY_TO_SPACE < 0) { + for (Object o : list) + { + if (currentEnergyValue - ENERGY_PER_ENTITY_TO_SPACE < 0) + { return; } currentEnergyValue -= ENERGY_PER_ENTITY_TO_SPACE; - 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); - final int WOOL_BLOCK_ID = 35; - int newY; - - for (newY = 254; newY > 0; newY--) { - if (DimensionManager.getWorld(WarpDrive.instance.spaceDimID).getBlockId(x, newY, z) == WOOL_BLOCK_ID) { + + for (newY = 254; newY > 0; newY--) + { + if (DimensionManager.getWorld(WarpDrive.instance.spaceDimID).getBlockId(x, newY, z) == WOOL_BLOCK_ID) + { break; } } - - if (newY <= 0) { newY = 254; } - - if (entity instanceof EntityPlayerMP) { + + if (newY <= 0) + { + newY = 254; + } + + if (entity instanceof EntityPlayerMP) + { ((EntityPlayerMP) entity).mcServer.getConfigurationManager().transferPlayerToDimension(((EntityPlayerMP) entity), WarpDrive.instance.spaceDimID, new SpaceTeleporter(DimensionManager.getWorld(WarpDrive.instance.spaceDimID), 0, x, 256, z)); - WorldServer space = DimensionManager.getWorld(WarpDrive.instance.spaceDimID); - if (space.isAirBlock(x, newY, z)) { - space.setBlock(x, newY, z, Block.stone.blockID, 0, 2); + if (space.isAirBlock(x, newY, z)) + { + space.setBlock(x, newY, z, Block.stone.blockID, 0, 2); space.setBlock(x + 1, newY, z, Block.stone.blockID, 0, 2); space.setBlock(x - 1, newY, z, Block.stone.blockID, 0, 2); - space.setBlock(x, newY, z + 1, Block.stone.blockID, 0, 2); space.setBlock(x, newY, z - 1, Block.stone.blockID, 0, 2); - space.setBlock(x + 1, newY, z + 1, Block.stone.blockID, 0, 2); space.setBlock(x - 1, newY, z - 1, Block.stone.blockID, 0, 2); - space.setBlock(x + 1, newY, z - 1, Block.stone.blockID, 0, 2); space.setBlock(x - 1, newY, z + 1, Block.stone.blockID, 0, 2); } @@ -828,102 +918,133 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { } } } - } + } } - - public void summonPlayersByChestCode() { - if (worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord) == null) { return; } + + public void summonPlayersByChestCode() + { + if (worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord) == null) + { + return; + } + TileEntityChest chest = (TileEntityChest)worldObj.getBlockTileEntity(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)) { + + if (checkPlayerInventory(chest, player)) + { System.out.println("[P] Summoning " + player.username); summonPlayer(player, xCoord, yCoord + 2, zCoord); } - } - } - - public boolean checkPlayerInventory(TileEntityChest chest, EntityPlayerMP player) { + } + } + + public 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++) { + + for (int index = 0; index < chest.getSizeInventory(); index++) + { ItemStack chestItem = chest.getStackInSlot(index); ItemStack playerItem = player.inventory.getStackInSlot(9 + index); - if (chestItem == null || playerItem == null) { continue; } + if (chestItem == null || playerItem == null) + { + continue; + } - if (chestItem.itemID != playerItem.itemID || chestItem.getItemDamage() != playerItem.getItemDamage() || chestItem.stackSize != playerItem.stackSize) { + if (chestItem.itemID != playerItem.itemID || chestItem.getItemDamage() != playerItem.getItemDamage() || chestItem.stackSize != playerItem.stackSize) + { return false; - } else { result = true; } - + } + else + { + result = true; + } + keyLength++; - } - - if (keyLength < MIN_KEY_LENGTH) { - System.out.println("[ChestCode] Key is too short: " + keyLength + " < " + MIN_KEY_LENGTH); - return false; } - + + if (keyLength < MIN_KEY_LENGTH) + { + System.out.println("[ChestCode] Key is too short: " + keyLength + " < " + MIN_KEY_LENGTH); + return false; + } + return result; } - - public Boolean isChestSummonMode() { + + public Boolean isChestSummonMode() + { TileEntity te = worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord); - - if (te != null) { + + if (te != null) + { return (te instanceof TileEntityChest); } - + return false; } - - public boolean testBB(AxisAlignedBB axisalignedbb, int x, int y, int z) { - return axisalignedbb.minX <= (double) x && axisalignedbb.maxX >= (double) x && axisalignedbb.minY <= (double) y && axisalignedbb.maxY >= (double) y && axisalignedbb.minZ <= (double) z && axisalignedbb.maxZ >= (double) z; - } - public String getCoreState() { + public boolean testBB(AxisAlignedBB axisalignedbb, int x, int y, int z) + { + return axisalignedbb.minX <= (double) x && axisalignedbb.maxX >= (double) x && axisalignedbb.minY <= (double) y && axisalignedbb.maxY >= (double) y && axisalignedbb.minZ <= (double) z && axisalignedbb.maxZ >= (double) z; + } + + public String getCoreState() + { return "[WarpCore] " + this.coreState; } - - public int calculateRequiredEnergy(int shipVolume, int jumpDistance) { + + public int calculateRequiredEnergy(int shipVolume, int jumpDistance) + { int energyValue = 0; - switch (currentMode) { + switch (currentMode) + { case MODE_BASIC_JUMP: energyValue = (ENERGY_PER_BLOCK_MODE1 * shipVolume) + (ENERGY_PER_DISTANCE_MODE1 * jumpDistance); break; + case MODE_LONG_JUMP: energyValue = (ENERGY_PER_BLOCK_MODE2 * shipVolume) + (ENERGY_PER_DISTANCE_MODE2 * jumpDistance); break; + case MODE_HYPERSPACE: energyValue = this.maxEnergyValue / 10; // 10% of maximum break; + case MODE_BEACON_JUMP: energyValue = this.maxEnergyValue / 2; // half of maximum break; + case MODE_GATE_JUMP: energyValue = 2 * shipVolume; } return energyValue; } - - public int getRealShipVolume() { + + public int getRealShipVolume() + { int shipVol = 0; - for (int x = minX; x <= maxX; x++) { - for (int z = minZ; z <= maxZ; z++) { - for (int y = minY; y <= maxY; y++) { + for (int x = minX; x <= maxX; x++) + { + for (int z = minZ; z <= maxZ; z++) + { + for (int y = minY; y <= maxY; y++) + { int blockID = worldObj.getBlockId(x, y, z); - if (blockID != 0) { + if (blockID != 0) + { shipVol++; } } @@ -933,32 +1054,40 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { return shipVol; } - public TileEntity findControllerBlock() { + public TileEntity findControllerBlock() + { TileEntity result; - result = worldObj.getBlockTileEntity(xCoord + 1, yCoord, zCoord); - if (result != null && result instanceof TileEntityProtocol) { + + if (result != null && result instanceof TileEntityProtocol) + { dx = 1; dz = 0; return result; } result = worldObj.getBlockTileEntity(xCoord - 1, yCoord, zCoord); - if (result != null && result instanceof TileEntityProtocol) { + + if (result != null && result instanceof TileEntityProtocol) + { dx = -1; dz = 0; return result; } result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord + 1); - if (result != null && result instanceof TileEntityProtocol) { - dx = 0; + + if (result != null && result instanceof TileEntityProtocol) + { + dx = 0; dz = 1; return result; } result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord - 1); - if (result != null && result instanceof TileEntityProtocol) { + + if (result != null && result instanceof TileEntityProtocol) + { dx = 0; dz = -1; return result; @@ -968,20 +1097,24 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { } @Override - public int demandsEnergy() { - if (this.controller != null && controller.getMode() == 0) { + public double demandedEnergyUnits() + { + if (this.controller != null && controller.getMode() == 0) + { return 0; } - + return (maxEnergyValue - currentEnergyValue); } @Override - public int injectEnergy(Direction directionFrom, int amount) { - int leftover = 0; + public double injectEnergyUnits(ForgeDirection directionFrom, double amount) + { + double leftover = 0; + currentEnergyValue += Math.round(amount); - currentEnergyValue += amount; - if (currentEnergyValue > maxEnergyValue) { + if (currentEnergyValue > maxEnergyValue) + { leftover = (currentEnergyValue - maxEnergyValue); currentEnergyValue = maxEnergyValue; } @@ -990,22 +1123,20 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { } @Override - public int getMaxSafeInput() { + public int getMaxSafeInput() + { return Integer.MAX_VALUE; } @Override - public boolean acceptsEnergyFrom(TileEntity emitter, Direction direction) { + public boolean acceptsEnergyFrom(TileEntity emitter, ForgeDirection direction) + { return true; } @Override - public boolean isAddedToEnergyNet() { - return addedToEnergyNet; - } - - @Override - public void readFromNBT(NBTTagCompound tag) { + public void readFromNBT(NBTTagCompound tag) + { super.readFromNBT(tag); currentEnergyValue = tag.getInteger("energy"); coreFrequency = tag.getString("corefrequency"); @@ -1014,39 +1145,42 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { } @Override - public void writeToNBT(NBTTagCompound tag) { + public void writeToNBT(NBTTagCompound tag) + { super.writeToNBT(tag); tag.setInteger("energy", currentEnergyValue); - tag.setString("corefrequency", coreFrequency); - tag.setInteger("isolation", this.isolationBlocksCount); } - - @Override - public void onChunkUnload() { - if (addedToEnergyNet) { + + @Override + public void onChunkUnload() + { + if (addedToEnergyNet) + { MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); addedToEnergyNet = false; - } - + } + WarpDrive.instance.registry.removeFromRegistry(this); } - + @Override - public void validate() { + public void validate() + { super.validate(); - WarpDrive.instance.registry.updateInRegistry(this); } - - @Override - public void invalidate() { - if (addedToEnergyNet) { + + @Override + public void invalidate() + { + if (addedToEnergyNet) + { MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); addedToEnergyNet = false; - } - + } + super.invalidate(); - } + } } diff --git a/src/cr0s/WarpDrive/Vector3.java b/src/cr0s/WarpDrive/Vector3.java index cc0a35cd..20ba8d48 100644 --- a/src/cr0s/WarpDrive/Vector3.java +++ b/src/cr0s/WarpDrive/Vector3.java @@ -15,764 +15,766 @@ import net.minecraftforge.common.ForgeDirection; /** * Vector3 Class is used for defining objects in a 3D space. - * + * * @author Calclavia */ public class Vector3 implements Cloneable { - - public double x; - public double y; - public double z; - - public Vector3() - { - this(0, 0, 0); - } - - public Vector3(double x, double y, double z) - { - this.x = x; - this.y = y; - this.z = z; - } - - public Vector3(Entity par1) - { - this.x = par1.posX; - this.y = par1.posY; - this.z = par1.posZ; - } - - public Vector3(TileEntity par1) - { - this.x = par1.xCoord; - this.y = par1.yCoord; - this.z = par1.zCoord; - } - - public Vector3(Vec3 par1) - { - this.x = par1.xCoord; - this.y = par1.yCoord; - this.z = par1.zCoord; - } - - public Vector3(MovingObjectPosition par1) - { - this.x = par1.blockX; - this.y = par1.blockY; - this.z = par1.blockZ; - } - - public Vector3(ChunkCoordinates par1) - { - this.x = par1.posX; - this.y = par1.posY; - this.z = par1.posZ; - } - - public Vector3(ForgeDirection direction) - { - this.x = direction.offsetX; - this.y = direction.offsetY; - this.z = direction.offsetZ; - } - - /** - * Loads a Vector3 from an NBT compound. - */ - public Vector3(NBTTagCompound nbt) - { - this.x = nbt.getDouble("x"); - this.y = nbt.getDouble("y"); - this.z = nbt.getDouble("z"); - } - - /** - * Returns the coordinates as integers, ideal for block placement. - */ - public int intX() - { - return (int) Math.floor(this.x); - } - - public int intY() - { - return (int) Math.floor(this.y); - } - - public int intZ() - { - return (int) Math.floor(this.z); - } - - /** - * Makes a new copy of this Vector. Prevents variable referencing problems. - */ - @Override - public Vector3 clone() - { - return new Vector3(this.x, this.y, this.z); - } - - /** - * Easy block access functions. - * - * @param world - * @return - */ - public int getBlockID(IBlockAccess world) - { - return world.getBlockId(this.intX(), this.intY(), this.intZ()); - } - - public int getBlockMetadata(IBlockAccess world) - { - return world.getBlockMetadata(this.intX(), this.intY(), this.intZ()); - } - - public TileEntity getTileEntity(IBlockAccess world) - { - return world.getBlockTileEntity(this.intX(), this.intY(), this.intZ()); - } - - public boolean setBlock(World world, int id, int metadata, int notify) - { - return world.setBlock(this.intX(), this.intY(), this.intZ(), id, metadata, notify); - } - - public boolean setBlock(World world, int id, int metadata) - { - return this.setBlock(world, id, metadata, 3); - } - - public boolean setBlock(World world, int id) - { - return this.setBlock(world, id, 0); - } - - - /** - * Converts this vector three into a Minecraft Vec3 object - */ - public Vec3 toVec3() - { - return Vec3.createVectorHelper(this.x, this.y, this.z); - } - - public double getMagnitude() - { - return Math.sqrt(this.getMagnitudeSquared()); - } - - public double getMagnitudeSquared() - { - return x * x + y * y + z * z; - } - - public Vector3 normalize() - { - double d = getMagnitude(); - - if (d != 0) - { - scale(1 / d); - } - return this; - } - - /** - * Gets the distance between two vectors - * - * @return The distance - */ - public static double distance(Vector3 par1, Vector3 par2) - { - double var2 = par1.x - par2.x; - double var4 = par1.y - par2.y; - double var6 = par1.z - par2.z; - return Math.sqrt(var2 * var2 + var4 * var4 + var6 * var6); - } - - public double distanceTo(Vector3 vector3) - { - double var2 = vector3.x - this.x; - double var4 = vector3.y - this.y; - double var6 = vector3.z - this.z; - return Math.sqrt(var2 * var2 + var4 * var4 + var6 * var6); - } - - /** - * Multiplies the vector by negative one. - */ - public Vector3 invert() - { - this.scale(-1); - return this; - } - - public Vector3 translate(Vector3 par1) - { - this.x += par1.x; - this.y += par1.y; - this.z += par1.z; - return this; - } - - public Vector3 translate(double par1) - { - this.x += par1; - this.y += par1; - this.z += par1; - return this; - } - - public static Vector3 translate(Vector3 translate, Vector3 par1) - { - translate.x += par1.x; - translate.y += par1.y; - translate.z += par1.z; - return translate; - } - - public static Vector3 translate(Vector3 translate, double par1) - { - translate.x += par1; - translate.y += par1; - translate.z += par1; - return translate; - } - - @Deprecated - public Vector3 add(Vector3 amount) - { - return translate(amount); - } - - @Deprecated - public Vector3 add(double amount) - { - return translate(amount); - } - - public Vector3 subtract(Vector3 amount) - { - return this.translate(amount.clone().invert()); - } - - public Vector3 subtract(double amount) - { - return this.translate(-amount); - } - - public Vector3 scale(double amount) - { - this.x *= amount; - this.y *= amount; - this.z *= amount; - return this; - } - - public Vector3 scale(Vector3 amount) - { - this.x *= amount.x; - this.y *= amount.y; - this.z *= amount.z; - return this; - } - - public static Vector3 scale(Vector3 vec, double amount) - { - return vec.scale(amount); - } - - public static Vector3 scale(Vector3 vec, Vector3 amount) - { - return vec.scale(amount); - } - - @Deprecated - public Vector3 multiply(double amount) - { - return this.scale(amount); - } - - @Deprecated - public Vector3 multiply(Vector3 amount) - { - return this.scale(amount); - } - - /** - * Static versions of a lot of functions - */ - @Deprecated - public static Vector3 subtract(Vector3 par1, Vector3 par2) - { - return new Vector3(par1.x - par2.x, par1.y - par2.y, par1.z - par2.z); - } - - @Deprecated - public static Vector3 add(Vector3 par1, Vector3 par2) - { - return new Vector3(par1.x + par2.x, par1.y + par2.y, par1.z + par2.z); - } - - @Deprecated - public static Vector3 add(Vector3 par1, double par2) - { - return new Vector3(par1.x + par2, par1.y + par2, par1.z + par2); - } - - @Deprecated - public static Vector3 multiply(Vector3 vec1, Vector3 vec2) - { - return new Vector3(vec1.x * vec2.x, vec1.y * vec2.y, vec1.z * vec2.z); - } - - @Deprecated - public static Vector3 multiply(Vector3 vec1, double vec2) - { - return new Vector3(vec1.x * vec2, vec1.y * vec2, vec1.z * vec2); - } - - public Vector3 round() - { - return new Vector3(Math.round(this.x), Math.round(this.y), Math.round(this.z)); - } - - public Vector3 ceil() - { - return new Vector3(Math.ceil(this.x), Math.ceil(this.y), Math.ceil(this.z)); - } - - public Vector3 floor() - { - return new Vector3(Math.floor(this.x), Math.floor(this.y), Math.floor(this.z)); - } - - public Vector3 toRound() - { - this.x = Math.round(this.x); - this.y = Math.round(this.y); - this.z = Math.round(this.z); - return this; - } - - public Vector3 toCeil() - { - this.x = Math.ceil(this.x); - this.y = Math.ceil(this.y); - this.z = Math.ceil(this.z); - return this; - } - - public Vector3 toFloor() - { - this.x = Math.floor(this.x); - this.y = Math.floor(this.y); - this.z = Math.floor(this.z); - return this; - } - - /** - * Gets all entities inside of this position in block space. - */ - public List<Entity> getEntitiesWithin(World worldObj, Class<? extends Entity> par1Class) - { - return worldObj.getEntitiesWithinAABB(par1Class, AxisAlignedBB.getBoundingBox(this.intX(), this.intY(), this.intZ(), this.intX() + 1, this.intY() + 1, this.intZ() + 1)); - } - - /** - * Gets a position relative to a position's side - * - * @param position - The position - * @param side - The side. 0-5 - * @return The position relative to the original position's side - */ - public Vector3 modifyPositionFromSide(ForgeDirection side, double amount) - { - switch (side.ordinal()) - { - case 0: - this.y -= amount; - break; - case 1: - this.y += amount; - break; - case 2: - this.z -= amount; - break; - case 3: - this.z += amount; - break; - case 4: - this.x -= amount; - break; - case 5: - this.x += amount; - break; - } - return this; - } - - public Vector3 modifyPositionFromSide(ForgeDirection side) - { - this.modifyPositionFromSide(side, 1); - return this; - } - - /** - * Cross product functions - * - * @return The cross product between this vector and another. - */ - public Vector3 crossProduct(Vector3 vec2) - { - return new Vector3(this.y * vec2.z - this.z * vec2.y, this.z * vec2.x - this.x * vec2.z, this.x * vec2.y - this.y * vec2.x); - } - - public Vector3 xCrossProduct() - { - return new Vector3(0.0D, this.z, -this.y); - } - - public Vector3 zCrossProduct() - { - return new Vector3(-this.y, this.x, 0.0D); - } - - public double dotProduct(Vector3 vec2) - { - return this.x * vec2.x + this.y * vec2.y + this.z * vec2.z; - } - - /** - * @return The perpendicular vector. - */ - public Vector3 getPerpendicular() - { - if (this.z == 0.0F) - { - return this.zCrossProduct(); - } - - return this.xCrossProduct(); - } - - /** - * @return True if this Vector3 is zero. - */ - public boolean isZero() - { - return (this.x == 0.0F) && (this.y == 0.0F) && (this.z == 0.0F); - } - - /** - * Rotate by a this vector around an axis. - * - * @return The new Vector3 rotation. - */ - public Vector3 rotate(float angle, Vector3 axis) - { - return translateMatrix(getRotationMatrix(angle, axis), this.clone()); - } - - public double[] getRotationMatrix(float angle) - { - double[] matrix = new double[16]; - Vector3 axis = this.clone().normalize(); - double x = axis.x; - double y = axis.y; - double z = axis.z; - angle *= 0.0174532925D; - float cos = (float) Math.cos(angle); - float ocos = 1.0F - cos; - float sin = (float) Math.sin(angle); - matrix[0] = (x * x * ocos + cos); - matrix[1] = (y * x * ocos + z * sin); - matrix[2] = (x * z * ocos - y * sin); - matrix[4] = (x * y * ocos - z * sin); - matrix[5] = (y * y * ocos + cos); - matrix[6] = (y * z * ocos + x * sin); - matrix[8] = (x * z * ocos + y * sin); - matrix[9] = (y * z * ocos - x * sin); - matrix[10] = (z * z * ocos + cos); - matrix[15] = 1.0F; - return matrix; - } - - public static Vector3 translateMatrix(double[] matrix, Vector3 translation) - { - double x = translation.x * matrix[0] + translation.y * matrix[1] + translation.z * matrix[2] + matrix[3]; - double y = translation.x * matrix[4] + translation.y * matrix[5] + translation.z * matrix[6] + matrix[7]; - double z = translation.x * matrix[8] + translation.y * matrix[9] + translation.z * matrix[10] + matrix[11]; - translation.x = x; - translation.y = y; - translation.z = z; - return translation; - } - - public static double[] getRotationMatrix(float angle, Vector3 axis) - { - return axis.getRotationMatrix(angle); - } - - /** - * Rotates this Vector by a yaw, pitch and roll value. - */ - public void rotate(double yaw, double pitch, double roll) - { - double yawRadians = Math.toRadians(yaw); - double pitchRadians = Math.toRadians(pitch); - double rollRadians = Math.toRadians(roll); - - double x = this.x; - double y = this.y; - double z = this.z; - - this.x = x * Math.cos(yawRadians) * Math.cos(pitchRadians) + z * (Math.cos(yawRadians) * Math.sin(pitchRadians) * Math.sin(rollRadians) - Math.sin(yawRadians) * Math.cos(rollRadians)) + y * (Math.cos(yawRadians) * Math.sin(pitchRadians) * Math.cos(rollRadians) + Math.sin(yawRadians) * Math.sin(rollRadians)); - this.z = x * Math.sin(yawRadians) * Math.cos(pitchRadians) + z * (Math.sin(yawRadians) * Math.sin(pitchRadians) * Math.sin(rollRadians) + Math.cos(yawRadians) * Math.cos(rollRadians)) + y * (Math.sin(yawRadians) * Math.sin(pitchRadians) * Math.cos(rollRadians) - Math.cos(yawRadians) * Math.sin(rollRadians)); - this.y = -x * Math.sin(pitchRadians) + z * Math.cos(pitchRadians) * Math.sin(rollRadians) + y * Math.cos(pitchRadians) * Math.cos(rollRadians); - } - - /** - * Rotates a point by a yaw and pitch around the anchor 0,0 by a specific angle. - */ - public void rotate(double yaw, double pitch) - { - this.rotate(yaw, pitch, 0); - } - - public void rotate(double yaw) - { - double yawRadians = Math.toRadians(yaw); - - double x = this.x; - double z = this.z; - - if (yaw != 0) - { - this.x = x * Math.cos(yawRadians) - z * Math.sin(yawRadians); - this.z = x * Math.sin(yawRadians) + z * Math.cos(yawRadians); - } - } - - /** - * Gets the delta look position based on the rotation yaw and pitch. Minecraft coordinates are - * messed up. Y and Z are flipped. Yaw is displaced by 90 degrees. Pitch is inversed. - * - * @param rotationYaw - * @param rotationPitch - */ - public static Vector3 getDeltaPositionFromRotation(float rotationYaw, float rotationPitch) - { - rotationYaw = rotationYaw + 90; - rotationPitch = -rotationPitch; - return new Vector3(Math.cos(Math.toRadians(rotationYaw)), Math.sin(Math.toRadians(rotationPitch)), Math.sin(Math.toRadians(rotationYaw))); - } - - /** - * Gets the angle between this vector and another vector. - * - * @return Angle in degrees - */ - public double getAngle(Vector3 vec2) - { - return anglePreNorm(this.clone().normalize(), vec2.clone().normalize()); - } - - public static double getAngle(Vector3 vec1, Vector3 vec2) - { - return vec1.getAngle(vec2); - } - - public double anglePreNorm(Vector3 vec2) - { - return Math.acos(this.dotProduct(vec2)); - } - - public static double anglePreNorm(Vector3 vec1, Vector3 vec2) - { - return Math.acos(vec1.clone().dotProduct(vec2)); - } - - /** - * Loads a Vector3 from an NBT compound. - */ - @Deprecated - public static Vector3 readFromNBT(NBTTagCompound nbt) - { - return new Vector3(nbt); - } - - /** - * Saves this Vector3 to disk - * - * @param prefix - The prefix of this save. Use some unique string. - * @param nbt - The NBT compound object to save the data in - */ - public NBTTagCompound writeToNBT(NBTTagCompound nbt) - { - nbt.setDouble("x", this.x); - nbt.setDouble("y", this.y); - nbt.setDouble("z", this.z); - return nbt; - } - - public static Vector3 UP() - { - return new Vector3(0, 1, 0); - } - - public static Vector3 DOWN() - { - return new Vector3(0, -1, 0); - } - - public static Vector3 NORTH() - { - return new Vector3(0, 0, -1); - } - - public static Vector3 SOUTH() - { - return new Vector3(0, 0, 1); - } - - public static Vector3 WEST() - { - return new Vector3(-1, 0, 0); - } - - public static Vector3 EAST() - { - return new Vector3(1, 0, 0); - } - - /** - * RayTrace Code, retrieved from MachineMuse. - * - * @author MachineMuse - */ - public MovingObjectPosition rayTrace(World world, float rotationYaw, float rotationPitch, boolean collisionFlag, double reachDistance) - { - // Somehow this destroys the playerPosition vector -.- - MovingObjectPosition pickedBlock = this.rayTraceBlocks(world, rotationYaw, rotationPitch, collisionFlag, reachDistance); - MovingObjectPosition pickedEntity = this.rayTraceEntities(world, rotationYaw, rotationPitch, collisionFlag, reachDistance); - - if (pickedBlock == null) - { - return pickedEntity; - } - else if (pickedEntity == null) - { - return pickedBlock; - } - else - { - double dBlock = this.distanceTo(new Vector3(pickedBlock.hitVec)); - double dEntity = this.distanceTo(new Vector3(pickedEntity.hitVec)); - - if (dEntity < dBlock) - { - return pickedEntity; - } - else - { - return pickedBlock; - } - } - } - - public MovingObjectPosition rayTraceBlocks(World world, float rotationYaw, float rotationPitch, boolean collisionFlag, double reachDistance) - { - Vector3 lookVector = getDeltaPositionFromRotation(rotationYaw, rotationPitch); - Vector3 reachPoint = translate(this, this.scale(lookVector, reachDistance)); - return world.rayTraceBlocks_do_do(this.toVec3(), reachPoint.toVec3(), collisionFlag, !collisionFlag); - } - - public MovingObjectPosition rayTraceEntities(World world, float rotationYaw, float rotationPitch, boolean collisionFlag, double reachDistance) - { - MovingObjectPosition pickedEntity = null; - Vec3 startingPosition = this.toVec3(); - Vec3 look = getDeltaPositionFromRotation(rotationYaw, rotationPitch).toVec3(); - Vec3 reachPoint = Vec3.createVectorHelper(startingPosition.xCoord + look.xCoord * reachDistance, startingPosition.yCoord + look.yCoord * reachDistance, startingPosition.zCoord + look.zCoord * reachDistance); - - double playerBorder = 1.1 * reachDistance; - AxisAlignedBB boxToScan = AxisAlignedBB.getAABBPool().getAABB(-playerBorder, -playerBorder, -playerBorder, playerBorder, playerBorder, playerBorder); - - @SuppressWarnings("unchecked") - List<Entity> entitiesHit = world.getEntitiesWithinAABBExcludingEntity(null, boxToScan); - double closestEntity = reachDistance; - - if (entitiesHit == null || entitiesHit.isEmpty()) - { - return null; - } - for (Entity entityHit : entitiesHit) - { - if (entityHit != null && entityHit.canBeCollidedWith() && entityHit.boundingBox != null) - { - float border = entityHit.getCollisionBorderSize(); - AxisAlignedBB aabb = entityHit.boundingBox.expand(border, border, border); - MovingObjectPosition hitMOP = aabb.calculateIntercept(startingPosition, reachPoint); - - if (hitMOP != null) - { - if (aabb.isVecInside(startingPosition)) - { - if (0.0D < closestEntity || closestEntity == 0.0D) - { - pickedEntity = new MovingObjectPosition(entityHit); - if (pickedEntity != null) - { - pickedEntity.hitVec = hitMOP.hitVec; - closestEntity = 0.0D; - } - } - } - else - { - double distance = startingPosition.distanceTo(hitMOP.hitVec); - - if (distance < closestEntity || closestEntity == 0.0D) - { - pickedEntity = new MovingObjectPosition(entityHit); - pickedEntity.hitVec = hitMOP.hitVec; - closestEntity = distance; - } - } - } - } - } - return pickedEntity; - } - - @Override - public int hashCode() - { - return ("X:" + this.x + "Y:" + this.y + "Z:" + this.z).hashCode(); - } - - @Override - public boolean equals(Object o) - { - if (o instanceof Vector3) - { - Vector3 vector3 = (Vector3) o; - return this.x == vector3.x && this.y == vector3.y && this.z == vector3.z; - } - - return false; - } - - @Override - public String toString() - { - return "Vector3 [" + this.x + "," + this.y + "," + this.z + "]"; - } - + public double x; + public double y; + public double z; + + public Vector3() + { + this(0, 0, 0); + } + + public Vector3(double x, double y, double z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public Vector3(Entity par1) + { + this.x = par1.posX; + this.y = par1.posY; + this.z = par1.posZ; + } + + public Vector3(TileEntity par1) + { + this.x = par1.xCoord; + this.y = par1.yCoord; + this.z = par1.zCoord; + } + + public Vector3(Vec3 par1) + { + this.x = par1.xCoord; + this.y = par1.yCoord; + this.z = par1.zCoord; + } + + public Vector3(MovingObjectPosition par1) + { + this.x = par1.blockX; + this.y = par1.blockY; + this.z = par1.blockZ; + } + + public Vector3(ChunkCoordinates par1) + { + this.x = par1.posX; + this.y = par1.posY; + this.z = par1.posZ; + } + + public Vector3(ForgeDirection direction) + { + this.x = direction.offsetX; + this.y = direction.offsetY; + this.z = direction.offsetZ; + } + + /** + * Loads a Vector3 from an NBT compound. + */ + public Vector3(NBTTagCompound nbt) + { + this.x = nbt.getDouble("x"); + this.y = nbt.getDouble("y"); + this.z = nbt.getDouble("z"); + } + + /** + * Returns the coordinates as integers, ideal for block placement. + */ + public int intX() + { + return (int) Math.floor(this.x); + } + + public int intY() + { + return (int) Math.floor(this.y); + } + + public int intZ() + { + return (int) Math.floor(this.z); + } + + /** + * Makes a new copy of this Vector. Prevents variable referencing problems. + */ + @Override + public Vector3 clone() + { + return new Vector3(this.x, this.y, this.z); + } + + /** + * Easy block access functions. + * + * @param world + * @return + */ + public int getBlockID(IBlockAccess world) + { + return world.getBlockId(this.intX(), this.intY(), this.intZ()); + } + + public int getBlockMetadata(IBlockAccess world) + { + return world.getBlockMetadata(this.intX(), this.intY(), this.intZ()); + } + + public TileEntity getTileEntity(IBlockAccess world) + { + return world.getBlockTileEntity(this.intX(), this.intY(), this.intZ()); + } + + public boolean setBlock(World world, int id, int metadata, int notify) + { + return world.setBlock(this.intX(), this.intY(), this.intZ(), id, metadata, notify); + } + + public boolean setBlock(World world, int id, int metadata) + { + return this.setBlock(world, id, metadata, 3); + } + + public boolean setBlock(World world, int id) + { + return this.setBlock(world, id, 0); + } + + /** + * Converts this vector three into a Minecraft Vec3 object + */ + public Vec3 toVec3() + { + return Vec3.createVectorHelper(this.x, this.y, this.z); + } + + public double getMagnitude() + { + return Math.sqrt(this.getMagnitudeSquared()); + } + + public double getMagnitudeSquared() + { + return x * x + y * y + z * z; + } + + public Vector3 normalize() + { + double d = getMagnitude(); + + if (d != 0) + { + scale(1 / d); + } + + return this; + } + + /** + * Gets the distance between two vectors + * + * @return The distance + */ + public static double distance(Vector3 par1, Vector3 par2) + { + double var2 = par1.x - par2.x; + double var4 = par1.y - par2.y; + double var6 = par1.z - par2.z; + return Math.sqrt(var2 * var2 + var4 * var4 + var6 * var6); + } + + public double distanceTo(Vector3 vector3) + { + double var2 = vector3.x - this.x; + double var4 = vector3.y - this.y; + double var6 = vector3.z - this.z; + return Math.sqrt(var2 * var2 + var4 * var4 + var6 * var6); + } + + /** + * Multiplies the vector by negative one. + */ + public Vector3 invert() + { + this.scale(-1); + return this; + } + + public Vector3 translate(Vector3 par1) + { + this.x += par1.x; + this.y += par1.y; + this.z += par1.z; + return this; + } + + public Vector3 translate(double par1) + { + this.x += par1; + this.y += par1; + this.z += par1; + return this; + } + + public static Vector3 translate(Vector3 translate, Vector3 par1) + { + translate.x += par1.x; + translate.y += par1.y; + translate.z += par1.z; + return translate; + } + + public static Vector3 translate(Vector3 translate, double par1) + { + translate.x += par1; + translate.y += par1; + translate.z += par1; + return translate; + } + + @Deprecated + public Vector3 add(Vector3 amount) + { + return translate(amount); + } + + @Deprecated + public Vector3 add(double amount) + { + return translate(amount); + } + + public Vector3 subtract(Vector3 amount) + { + return this.translate(amount.clone().invert()); + } + + public Vector3 subtract(double amount) + { + return this.translate(-amount); + } + + public Vector3 scale(double amount) + { + this.x *= amount; + this.y *= amount; + this.z *= amount; + return this; + } + + public Vector3 scale(Vector3 amount) + { + this.x *= amount.x; + this.y *= amount.y; + this.z *= amount.z; + return this; + } + + public static Vector3 scale(Vector3 vec, double amount) + { + return vec.scale(amount); + } + + public static Vector3 scale(Vector3 vec, Vector3 amount) + { + return vec.scale(amount); + } + + @Deprecated + public Vector3 multiply(double amount) + { + return this.scale(amount); + } + + @Deprecated + public Vector3 multiply(Vector3 amount) + { + return this.scale(amount); + } + + /** + * Static versions of a lot of functions + */ + @Deprecated + public static Vector3 subtract(Vector3 par1, Vector3 par2) + { + return new Vector3(par1.x - par2.x, par1.y - par2.y, par1.z - par2.z); + } + + @Deprecated + public static Vector3 add(Vector3 par1, Vector3 par2) + { + return new Vector3(par1.x + par2.x, par1.y + par2.y, par1.z + par2.z); + } + + @Deprecated + public static Vector3 add(Vector3 par1, double par2) + { + return new Vector3(par1.x + par2, par1.y + par2, par1.z + par2); + } + + @Deprecated + public static Vector3 multiply(Vector3 vec1, Vector3 vec2) + { + return new Vector3(vec1.x * vec2.x, vec1.y * vec2.y, vec1.z * vec2.z); + } + + @Deprecated + public static Vector3 multiply(Vector3 vec1, double vec2) + { + return new Vector3(vec1.x * vec2, vec1.y * vec2, vec1.z * vec2); + } + + public Vector3 round() + { + return new Vector3(Math.round(this.x), Math.round(this.y), Math.round(this.z)); + } + + public Vector3 ceil() + { + return new Vector3(Math.ceil(this.x), Math.ceil(this.y), Math.ceil(this.z)); + } + + public Vector3 floor() + { + return new Vector3(Math.floor(this.x), Math.floor(this.y), Math.floor(this.z)); + } + + public Vector3 toRound() + { + this.x = Math.round(this.x); + this.y = Math.round(this.y); + this.z = Math.round(this.z); + return this; + } + + public Vector3 toCeil() + { + this.x = Math.ceil(this.x); + this.y = Math.ceil(this.y); + this.z = Math.ceil(this.z); + return this; + } + + public Vector3 toFloor() + { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + this.z = Math.floor(this.z); + return this; + } + + /** + * Gets all entities inside of this position in block space. + */ + public List<Entity> getEntitiesWithin(World worldObj, Class <? extends Entity > par1Class) + { + return worldObj.getEntitiesWithinAABB(par1Class, AxisAlignedBB.getBoundingBox(this.intX(), this.intY(), this.intZ(), this.intX() + 1, this.intY() + 1, this.intZ() + 1)); + } + + /** + * Gets a position relative to a position's side + * + * @param position - The position + * @param side - The side. 0-5 + * @return The position relative to the original position's side + */ + public Vector3 modifyPositionFromSide(ForgeDirection side, double amount) + { + switch (side.ordinal()) + { + case 0: + this.y -= amount; + break; + + case 1: + this.y += amount; + break; + + case 2: + this.z -= amount; + break; + + case 3: + this.z += amount; + break; + + case 4: + this.x -= amount; + break; + + case 5: + this.x += amount; + break; + } + + return this; + } + + public Vector3 modifyPositionFromSide(ForgeDirection side) + { + this.modifyPositionFromSide(side, 1); + return this; + } + + /** + * Cross product functions + * + * @return The cross product between this vector and another. + */ + public Vector3 crossProduct(Vector3 vec2) + { + return new Vector3(this.y * vec2.z - this.z * vec2.y, this.z * vec2.x - this.x * vec2.z, this.x * vec2.y - this.y * vec2.x); + } + + public Vector3 xCrossProduct() + { + return new Vector3(0.0D, this.z, -this.y); + } + + public Vector3 zCrossProduct() + { + return new Vector3(-this.y, this.x, 0.0D); + } + + public double dotProduct(Vector3 vec2) + { + return this.x * vec2.x + this.y * vec2.y + this.z * vec2.z; + } + + /** + * @return The perpendicular vector. + */ + public Vector3 getPerpendicular() + { + if (this.z == 0.0F) + { + return this.zCrossProduct(); + } + + return this.xCrossProduct(); + } + + /** + * @return True if this Vector3 is zero. + */ + public boolean isZero() + { + return (this.x == 0.0F) && (this.y == 0.0F) && (this.z == 0.0F); + } + + /** + * Rotate by a this vector around an axis. + * + * @return The new Vector3 rotation. + */ + public Vector3 rotate(float angle, Vector3 axis) + { + return translateMatrix(getRotationMatrix(angle, axis), this.clone()); + } + + public double[] getRotationMatrix(float angle) + { + double[] matrix = new double[16]; + Vector3 axis = this.clone().normalize(); + double x = axis.x; + double y = axis.y; + double z = axis.z; + angle *= 0.0174532925D; + float cos = (float) Math.cos(angle); + float ocos = 1.0F - cos; + float sin = (float) Math.sin(angle); + matrix[0] = (x * x * ocos + cos); + matrix[1] = (y * x * ocos + z * sin); + matrix[2] = (x * z * ocos - y * sin); + matrix[4] = (x * y * ocos - z * sin); + matrix[5] = (y * y * ocos + cos); + matrix[6] = (y * z * ocos + x * sin); + matrix[8] = (x * z * ocos + y * sin); + matrix[9] = (y * z * ocos - x * sin); + matrix[10] = (z * z * ocos + cos); + matrix[15] = 1.0F; + return matrix; + } + + public static Vector3 translateMatrix(double[] matrix, Vector3 translation) + { + double x = translation.x * matrix[0] + translation.y * matrix[1] + translation.z * matrix[2] + matrix[3]; + double y = translation.x * matrix[4] + translation.y * matrix[5] + translation.z * matrix[6] + matrix[7]; + double z = translation.x * matrix[8] + translation.y * matrix[9] + translation.z * matrix[10] + matrix[11]; + translation.x = x; + translation.y = y; + translation.z = z; + return translation; + } + + public static double[] getRotationMatrix(float angle, Vector3 axis) + { + return axis.getRotationMatrix(angle); + } + + /** + * Rotates this Vector by a yaw, pitch and roll value. + */ + public void rotate(double yaw, double pitch, double roll) + { + double yawRadians = Math.toRadians(yaw); + double pitchRadians = Math.toRadians(pitch); + double rollRadians = Math.toRadians(roll); + double x = this.x; + double y = this.y; + double z = this.z; + this.x = x * Math.cos(yawRadians) * Math.cos(pitchRadians) + z * (Math.cos(yawRadians) * Math.sin(pitchRadians) * Math.sin(rollRadians) - Math.sin(yawRadians) * Math.cos(rollRadians)) + y * (Math.cos(yawRadians) * Math.sin(pitchRadians) * Math.cos(rollRadians) + Math.sin(yawRadians) * Math.sin(rollRadians)); + this.z = x * Math.sin(yawRadians) * Math.cos(pitchRadians) + z * (Math.sin(yawRadians) * Math.sin(pitchRadians) * Math.sin(rollRadians) + Math.cos(yawRadians) * Math.cos(rollRadians)) + y * (Math.sin(yawRadians) * Math.sin(pitchRadians) * Math.cos(rollRadians) - Math.cos(yawRadians) * Math.sin(rollRadians)); + this.y = -x * Math.sin(pitchRadians) + z * Math.cos(pitchRadians) * Math.sin(rollRadians) + y * Math.cos(pitchRadians) * Math.cos(rollRadians); + } + + /** + * Rotates a point by a yaw and pitch around the anchor 0,0 by a specific angle. + */ + public void rotate(double yaw, double pitch) + { + this.rotate(yaw, pitch, 0); + } + + public void rotate(double yaw) + { + double yawRadians = Math.toRadians(yaw); + double x = this.x; + double z = this.z; + + if (yaw != 0) + { + this.x = x * Math.cos(yawRadians) - z * Math.sin(yawRadians); + this.z = x * Math.sin(yawRadians) + z * Math.cos(yawRadians); + } + } + + /** + * Gets the delta look position based on the rotation yaw and pitch. Minecraft coordinates are + * messed up. Y and Z are flipped. Yaw is displaced by 90 degrees. Pitch is inversed. + * + * @param rotationYaw + * @param rotationPitch + */ + public static Vector3 getDeltaPositionFromRotation(float rotationYaw, float rotationPitch) + { + rotationYaw = rotationYaw + 90; + rotationPitch = -rotationPitch; + return new Vector3(Math.cos(Math.toRadians(rotationYaw)), Math.sin(Math.toRadians(rotationPitch)), Math.sin(Math.toRadians(rotationYaw))); + } + + /** + * Gets the angle between this vector and another vector. + * + * @return Angle in degrees + */ + public double getAngle(Vector3 vec2) + { + return anglePreNorm(this.clone().normalize(), vec2.clone().normalize()); + } + + public static double getAngle(Vector3 vec1, Vector3 vec2) + { + return vec1.getAngle(vec2); + } + + public double anglePreNorm(Vector3 vec2) + { + return Math.acos(this.dotProduct(vec2)); + } + + public static double anglePreNorm(Vector3 vec1, Vector3 vec2) + { + return Math.acos(vec1.clone().dotProduct(vec2)); + } + + /** + * Loads a Vector3 from an NBT compound. + */ + @Deprecated + public static Vector3 readFromNBT(NBTTagCompound nbt) + { + return new Vector3(nbt); + } + + /** + * Saves this Vector3 to disk + * + * @param prefix - The prefix of this save. Use some unique string. + * @param nbt - The NBT compound object to save the data in + */ + public NBTTagCompound writeToNBT(NBTTagCompound nbt) + { + nbt.setDouble("x", this.x); + nbt.setDouble("y", this.y); + nbt.setDouble("z", this.z); + return nbt; + } + + public static Vector3 UP() + { + return new Vector3(0, 1, 0); + } + + public static Vector3 DOWN() + { + return new Vector3(0, -1, 0); + } + + public static Vector3 NORTH() + { + return new Vector3(0, 0, -1); + } + + public static Vector3 SOUTH() + { + return new Vector3(0, 0, 1); + } + + public static Vector3 WEST() + { + return new Vector3(-1, 0, 0); + } + + public static Vector3 EAST() + { + return new Vector3(1, 0, 0); + } + + /** + * RayTrace Code, retrieved from MachineMuse. + * + * @author MachineMuse + */ + public MovingObjectPosition rayTrace(World world, float rotationYaw, float rotationPitch, boolean collisionFlag, double reachDistance) + { + // Somehow this destroys the playerPosition vector -.- + MovingObjectPosition pickedBlock = this.rayTraceBlocks(world, rotationYaw, rotationPitch, collisionFlag, reachDistance); + MovingObjectPosition pickedEntity = this.rayTraceEntities(world, rotationYaw, rotationPitch, collisionFlag, reachDistance); + + if (pickedBlock == null) + { + return pickedEntity; + } + else if (pickedEntity == null) + { + return pickedBlock; + } + else + { + double dBlock = this.distanceTo(new Vector3(pickedBlock.hitVec)); + double dEntity = this.distanceTo(new Vector3(pickedEntity.hitVec)); + + if (dEntity < dBlock) + { + return pickedEntity; + } + else + { + return pickedBlock; + } + } + } + + public MovingObjectPosition rayTraceBlocks(World world, float rotationYaw, float rotationPitch, boolean collisionFlag, double reachDistance) + { + Vector3 lookVector = getDeltaPositionFromRotation(rotationYaw, rotationPitch); + Vector3 reachPoint = translate(this, this.scale(lookVector, reachDistance)); + return world.rayTraceBlocks_do_do(this.toVec3(), reachPoint.toVec3(), collisionFlag, !collisionFlag); + } + + public MovingObjectPosition rayTraceEntities(World world, float rotationYaw, float rotationPitch, boolean collisionFlag, double reachDistance) + { + MovingObjectPosition pickedEntity = null; + Vec3 startingPosition = this.toVec3(); + Vec3 look = getDeltaPositionFromRotation(rotationYaw, rotationPitch).toVec3(); + Vec3 reachPoint = Vec3.createVectorHelper(startingPosition.xCoord + look.xCoord * reachDistance, startingPosition.yCoord + look.yCoord * reachDistance, startingPosition.zCoord + look.zCoord * reachDistance); + double playerBorder = 1.1 * reachDistance; + AxisAlignedBB boxToScan = AxisAlignedBB.getAABBPool().getAABB(-playerBorder, -playerBorder, -playerBorder, playerBorder, playerBorder, playerBorder); + @SuppressWarnings("unchecked") + List<Entity> entitiesHit = world.getEntitiesWithinAABBExcludingEntity(null, boxToScan); + double closestEntity = reachDistance; + + if (entitiesHit == null || entitiesHit.isEmpty()) + { + return null; + } + + for (Entity entityHit : entitiesHit) + { + if (entityHit != null && entityHit.canBeCollidedWith() && entityHit.boundingBox != null) + { + float border = entityHit.getCollisionBorderSize(); + AxisAlignedBB aabb = entityHit.boundingBox.expand(border, border, border); + MovingObjectPosition hitMOP = aabb.calculateIntercept(startingPosition, reachPoint); + + if (hitMOP != null) + { + if (aabb.isVecInside(startingPosition)) + { + if (0.0D < closestEntity || closestEntity == 0.0D) + { + pickedEntity = new MovingObjectPosition(entityHit); + + if (pickedEntity != null) + { + pickedEntity.hitVec = hitMOP.hitVec; + closestEntity = 0.0D; + } + } + } + else + { + double distance = startingPosition.distanceTo(hitMOP.hitVec); + + if (distance < closestEntity || closestEntity == 0.0D) + { + pickedEntity = new MovingObjectPosition(entityHit); + pickedEntity.hitVec = hitMOP.hitVec; + closestEntity = distance; + } + } + } + } + } + + return pickedEntity; + } + + @Override + public int hashCode() + { + return ("X:" + this.x + "Y:" + this.y + "Z:" + this.z).hashCode(); + } + + @Override + public boolean equals(Object o) + { + if (o instanceof Vector3) + { + Vector3 vector3 = (Vector3) o; + return this.x == vector3.x && this.y == vector3.y && this.z == vector3.z; + } + + return false; + } + + @Override + public String toString() + { + return "Vector3 [" + this.x + "," + this.y + "," + this.z + "]"; + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/WarpCoresRegistry.java b/src/cr0s/WarpDrive/WarpCoresRegistry.java index 39b892c4..d84e33c2 100644 --- a/src/cr0s/WarpDrive/WarpCoresRegistry.java +++ b/src/cr0s/WarpDrive/WarpCoresRegistry.java @@ -1,8 +1,5 @@ package cr0s.WarpDrive; -import cr0s.WarpDrive.WarpDrive; -import cr0s.WarpDrive.TileEntityReactor; - import java.util.ArrayList; import net.minecraft.entity.Entity; @@ -12,163 +9,187 @@ import net.minecraft.util.MathHelper; /** * @authorCr0s */ -public class WarpCoresRegistry { +public class WarpCoresRegistry +{ private ArrayList<TileEntityReactor> registry; - - public WarpCoresRegistry() { + + public WarpCoresRegistry() + { registry = new ArrayList<TileEntityReactor>(); } - - public int searchCoreInRegistry(TileEntityReactor core) { + + public int searchCoreInRegistry(TileEntityReactor core) + { int res = -1; - for (int i = 0; i < registry.size(); i++) { + for (int i = 0; i < registry.size(); i++) + { TileEntityReactor c = registry.get(i); - - if (c.xCoord == core.xCoord && c.yCoord == core.yCoord && c.zCoord == core.zCoord) { + + if (c.xCoord == core.xCoord && c.yCoord == core.yCoord && c.zCoord == core.zCoord) + { return i; } } - + return res; } - - public boolean isCoreInRegistry(TileEntityReactor core) { + + public boolean isCoreInRegistry(TileEntityReactor core) + { return (searchCoreInRegistry(core) != -1); } - - public void updateInRegistry(TileEntityReactor core) { + + public void updateInRegistry(TileEntityReactor core) + { int idx = searchCoreInRegistry(core); - + // update - if (idx != -1) { + if (idx != -1) + { registry.set(idx, core); - } else + } + else { registry.add(core); } } - - public void removeFromRegistry(TileEntityReactor core) { + + public void removeFromRegistry(TileEntityReactor core) + { int idx; - - if ((idx = searchCoreInRegistry(core)) != -1) { + + if ((idx = searchCoreInRegistry(core)) != -1) + { registry.remove(idx); } } - - public ArrayList<TileEntityReactor> searchWarpCoresInRadius(int x, int y, int z, int radius) { + + public ArrayList<TileEntityReactor> searchWarpCoresInRadius(int x, int y, int z, int radius) + { ArrayList<TileEntityReactor> res = new ArrayList<TileEntityReactor>(); - - for (TileEntityReactor c : registry) { + + for (TileEntityReactor c : registry) + { double d3 = c.xCoord - x; double d4 = c.yCoord - y; double d5 = c.zCoord - z; - double distance = MathHelper.sqrt_double(d3 * d3 + d4 * d4 + d5 * d5); - + if (distance <= radius && !(c.controller == null || c.controller.getMode() == 0) && !isCoreHidden(c)) { res.add(c); } } - + return res; } - - public void printRegistry() { + + public void printRegistry() + { System.out.println("WarpCores registry:"); removeDeadCores(); - - for (TileEntityReactor c : registry) { + + for (TileEntityReactor c : registry) + { System.out.println(c.coreFrequency + " (" + c.xCoord + "; " + c.yCoord + "; " + c.zCoord + ")"); } } - + final int LOWER_HIDE_POINT = 18; - private boolean isCoreHidden(TileEntityReactor core) { - if (core.isolationBlocksCount > 5) { + private boolean isCoreHidden(TileEntityReactor core) + { + if (core.isolationBlocksCount > 5) + { int randomNumber = core.worldObj.rand.nextInt(150); + if (randomNumber < LOWER_HIDE_POINT + core.isolationBlocksCount) { return true; } } - + return false; } - - public boolean isWarpCoreIntersectsWithOthers(TileEntityReactor core) { + + public boolean isWarpCoreIntersectsWithOthers(TileEntityReactor core) + { AxisAlignedBB aabb1, aabb2; - removeDeadCores(); - - for (TileEntityReactor c : registry) { + + for (TileEntityReactor c : registry) + { // Skip cores in other worlds - if (c.worldObj != core.worldObj) { - continue; - } - - // Skip self - if(c.xCoord == core.xCoord && c.yCoord == core.yCoord && c.zCoord == core.zCoord) { + if (c.worldObj != core.worldObj) + { continue; } - + + // Skip self + if (c.xCoord == core.xCoord && c.yCoord == core.yCoord && c.zCoord == core.zCoord) + { + continue; + } + // Skip offline warp cores - if (c.controller == null || c.controller.getMode() == 0 || !c.prepareToJump()) { + if (c.controller == null || c.controller.getMode() == 0 || !c.prepareToJump()) + { continue; } + // Search for nearest warp cores double d3 = c.xCoord - core.xCoord; double d4 = c.yCoord - core.yCoord; double d5 = c.zCoord - core.zCoord; - double distance = MathHelper.sqrt_double(d3 * d3 + d4 * d4 + d5 * d5); - + if (distance <= (2 * core.MAX_SHIP_SIDE) - 1) { // Check for warpfields intersections core.prepareToJump(); // calculate spatial parameters c.prepareToJump(); - // Compare warp-fields for intersection aabb1 = AxisAlignedBB.getBoundingBox(core.minX, core.minY, core.minZ, core.maxX, core.maxY, core.maxZ); aabb2 = AxisAlignedBB.getBoundingBox(c.minX, c.minY, c.minZ, c.maxX, c.maxY, c.maxZ); - - if (aabb1.intersectsWith(aabb2)) { + + if (aabb1.intersectsWith(aabb2)) + { return true; } - } + } } - + return false; } - - public void removeDeadCores() { - LocalProfiler.start("WCR.removeDeadCores()"); - ArrayList<TileEntityReactor> oldRegistry = (ArrayList<TileEntityReactor>) registry.clone(); - - for (TileEntityReactor c : registry) { - if (c != null && c.worldObj != null && (c.worldObj.getBlockId(c.xCoord, c.yCoord, c.zCoord) != WarpDrive.instance.config.coreID|| (c.worldObj.getBlockTileEntity(c.xCoord, c.yCoord, c.zCoord) != null && c.worldObj.getBlockTileEntity(c.xCoord, c.yCoord, c.zCoord).isInvalid()))) { + + public void removeDeadCores() + { + LocalProfiler.start("WCR.removeDeadCores()"); + ArrayList<TileEntityReactor> oldRegistry = (ArrayList<TileEntityReactor>) registry.clone(); + + for (TileEntityReactor c : registry) + { + if (c != null && c.worldObj != null && (c.worldObj.getBlockId(c.xCoord, c.yCoord, c.zCoord) != WarpDrive.instance.config.coreID || (c.worldObj.getBlockTileEntity(c.xCoord, c.yCoord, c.zCoord) != null && c.worldObj.getBlockTileEntity(c.xCoord, c.yCoord, c.zCoord).isInvalid()))) + { oldRegistry.remove(c); return; } } - + // Update old registry to new witout dead cores this.registry = (ArrayList<TileEntityReactor>) oldRegistry.clone(); LocalProfiler.stop(); } - + // TODO: fix it to normal work in client /*public boolean isEntityInsideAnyWarpField(Entity e) { AxisAlignedBB aabb1, aabb2; - + double x = e.posX; double y = e.posY; double z = e.posZ; - - for (TileEntityReactor c : registry) { + + for (TileEntityReactor c : registry) { // Skip offline or disassembled warp cores if (c.controller == null || !c.prepareToJump()) { System.out.println("Skipping " + c); @@ -176,24 +197,24 @@ public class WarpCoresRegistry { System.out.println("Controller is null!"); continue; } - + if (c.controller.getMode() == 0) { System.out.println("Mode is zero!"); continue; } - + if (!c.prepareToJump()) { System.out.println("prepareToJump() returns false!"); continue; } continue; } - + if (c.minX <= x && c.maxX >= x && c.minY <= y && c.maxY >= y && c.minZ <= z && c.maxZ >= z) { return true; } } - + return false; }*/ } diff --git a/src/cr0s/WarpDrive/WarpDrive.java b/src/cr0s/WarpDrive/WarpDrive.java index 2382c4f4..973cbbf9 100644 --- a/src/cr0s/WarpDrive/WarpDrive.java +++ b/src/cr0s/WarpDrive/WarpDrive.java @@ -20,7 +20,6 @@ import ic2.api.item.Items; import java.util.List; -import shipmod.ShipModConfig; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.client.Minecraft; @@ -37,32 +36,33 @@ import net.minecraftforge.common.ForgeChunkManager.Ticket; import net.minecraftforge.common.MinecraftForge; @Mod(modid = "WarpDrive", name = "WarpDrive", version = "1.0.5") -@NetworkMod(clientSideRequired = true, serverSideRequired = true, channels={"WarpDriveBeam", "WarpDriveFreq", "WarpDriveLaserT"}, packetHandler = PacketHandler.class) +@NetworkMod(clientSideRequired = true, serverSideRequired = true, channels = {"WarpDriveBeam", "WarpDriveFreq", "WarpDriveLaserT"}, packetHandler = PacketHandler.class) /** * @author Cr0s */ -public class WarpDrive implements LoadingCallback { +public class WarpDrive implements LoadingCallback +{ // World limits public final static int WORLD_LIMIT_BLOCKS = 100000; - + public static Block warpCore; public static Block protocolBlock; - public static Block radarBlock; + public static Block radarBlock; public static Block isolationBlock; public static Block airgenBlock; - public static Block laserBlock; - public static Block laserCamBlock; - public static Block cameraBlock; - public static Block monitorBlock; - public static Block boosterBlock; - public static Block miningLaserBlock; - public static Block liftBlock; - - public static Block airBlock; - public static Block gasBlock; + public static Block laserBlock; + public static Block laserCamBlock; + public static Block cameraBlock; + public static Block monitorBlock; + public static Block boosterBlock; + public static Block miningLaserBlock; + public static Block liftBlock; + + public static Block airBlock; + public static Block gasBlock; + + public static Block iridiumBlock; - public static Block iridiumBlock; - public static BiomeGenBase spaceBiome; public World space; private int spaceProviderID; @@ -73,240 +73,215 @@ public class WarpDrive implements LoadingCallback { public World hyperSpace; private int hyperSpaceProviderID; public int hyperSpaceDimID; - + @Instance("WarpDrive") public static WarpDrive instance; @SidedProxy(clientSide = "cr0s.WarpDrive.ClientProxy", serverSide = "cr0s.WarpDrive.CommonProxy") public static CommonProxy proxy; - + public WarpCoresRegistry registry; public JumpGatesRegistry jumpGates; - + public CamRegistry cams; public boolean isOverlayEnabled = false; public int overlayType = 0; - + public WarpDriveConfig config; - + @EventHandler //@PreInit - public void preInit(FMLPreInitializationEvent event) { - this.config = new WarpDriveConfig(new Configuration(event.getSuggestedConfigurationFile())); - this.config.loadAndSave(); - - if(FMLCommonHandler.instance().getSide().isClient()) + public void preInit(FMLPreInitializationEvent event) + { + this.config = new WarpDriveConfig(new Configuration(event.getSuggestedConfigurationFile())); + this.config.loadAndSave(); + + if (FMLCommonHandler.instance().getSide().isClient()) { System.out.println("[WarpDrive] Registering sounds event handler..."); - MinecraftForge.EVENT_BUS.register(new SoundHandler()); + MinecraftForge.EVENT_BUS.register(new SoundHandler()); } } @Init - public void load(FMLInitializationEvent event) { - // WARP CORE + public void load(FMLInitializationEvent event) + { + // WARP CORE this.warpCore = new BlockReactor(this.config.coreID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Warp Core"); LanguageRegistry.addName(warpCore, "Warp Core"); GameRegistry.registerBlock(warpCore, "warpCore"); GameRegistry.registerTileEntity(TileEntityReactor.class, "warpCore"); - // CORE CONTROLLER this.protocolBlock = new BlockProtocol(config.controllerID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Warp Controller"); LanguageRegistry.addName(protocolBlock, "Warp Controller"); GameRegistry.registerBlock(protocolBlock, "protocolBlock"); - GameRegistry.registerTileEntity(TileEntityProtocol.class, "protocolBlock"); - + GameRegistry.registerTileEntity(TileEntityProtocol.class, "protocolBlock"); // WARP RADAR this.radarBlock = new BlockRadar(config.radarID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("W-Radar"); + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("W-Radar"); LanguageRegistry.addName(radarBlock, "W-Radar"); GameRegistry.registerBlock(radarBlock, "radarBlock"); - GameRegistry.registerTileEntity(TileEntityRadar.class, "radarBlock"); - + GameRegistry.registerTileEntity(TileEntityRadar.class, "radarBlock"); // WARP ISOLATION this.isolationBlock = new BlockWarpIsolation(config.isolationID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Warp-Field Isolation Block"); + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Warp-Field Isolation Block"); LanguageRegistry.addName(isolationBlock, "Warp-Field Isolation Block"); - GameRegistry.registerBlock(isolationBlock, "isolationBlock"); - + GameRegistry.registerBlock(isolationBlock, "isolationBlock"); // AIR GENERATOR this.airgenBlock = new BlockAirGenerator(config.airgenID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Air Generator"); + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Air Generator"); LanguageRegistry.addName(airgenBlock, "Air Generator"); GameRegistry.registerBlock(airgenBlock, "airgenBlock"); - GameRegistry.registerTileEntity(TileEntityAirGenerator.class, "airgenBlock"); - + GameRegistry.registerTileEntity(TileEntityAirGenerator.class, "airgenBlock"); // AIR BLOCK - this.airBlock = (new BlockAir(config.airID)).setHardness(0.0F).setUnlocalizedName("Air block"); + this.airBlock = (new BlockAir(config.airID)).setHardness(0.0F).setUnlocalizedName("Air block"); LanguageRegistry.addName(airBlock, "Air block"); - GameRegistry.registerBlock(airBlock, "airBlock"); - + GameRegistry.registerBlock(airBlock, "airBlock"); // GAS BLOCK this.gasBlock = (new BlockGas(config.gasID)).setHardness(0.0F).setUnlocalizedName("Gas block"); LanguageRegistry.addName(gasBlock, "Gas block"); - GameRegistry.registerBlock(gasBlock, "gasBlock"); - + GameRegistry.registerBlock(gasBlock, "gasBlock"); // LASER EMITTER this.laserBlock = new BlockLaser(config.laserID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser Emitter"); + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser Emitter"); LanguageRegistry.addName(laserBlock, "Laser Emitter"); GameRegistry.registerBlock(laserBlock, "laserBlock"); - GameRegistry.registerTileEntity(TileEntityLaser.class, "laserBlock"); - + GameRegistry.registerTileEntity(TileEntityLaser.class, "laserBlock"); // LASER EMITTER WITH CAMERA this.laserCamBlock = new BlockLaserCam(config.laserCamID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser Emitter + Camera"); + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser Emitter + Camera"); LanguageRegistry.addName(laserCamBlock, "Laser Emitter + Camera"); - GameRegistry.registerBlock(laserCamBlock, "laserCamBlock"); - + GameRegistry.registerBlock(laserCamBlock, "laserCamBlock"); // CAMERA this.cameraBlock = new BlockCamera(config.camID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Camera block"); + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Camera block"); LanguageRegistry.addName(cameraBlock, "Camera"); - GameRegistry.registerBlock(cameraBlock, "cameraBlock"); - GameRegistry.registerTileEntity(TileEntityCamera.class, "cameraBlock"); - + GameRegistry.registerBlock(cameraBlock, "cameraBlock"); + GameRegistry.registerTileEntity(TileEntityCamera.class, "cameraBlock"); // MONITOR this.monitorBlock = new BlockMonitor(config.monitorID) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Monitor"); + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Monitor"); LanguageRegistry.addName(monitorBlock, "Monitor"); - GameRegistry.registerBlock(monitorBlock, "monitorBlock"); - GameRegistry.registerTileEntity(TileEntityMonitor.class, "monitorBlock"); - + GameRegistry.registerBlock(monitorBlock, "monitorBlock"); + GameRegistry.registerTileEntity(TileEntityMonitor.class, "monitorBlock"); // MINING LASER this.miningLaserBlock = new BlockMiningLaser(config.miningLaserID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Mining Laser"); + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Mining Laser"); LanguageRegistry.addName(miningLaserBlock, "Mining Laser"); GameRegistry.registerBlock(miningLaserBlock, "miningLaserBlock"); - GameRegistry.registerTileEntity(TileEntityMiningLaser.class, "miningLaserBlock"); - + GameRegistry.registerTileEntity(TileEntityMiningLaser.class, "miningLaserBlock"); // PARTICLE BOOSTER this.boosterBlock = new BlockParticleBooster(config.particleBoosterID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Particle Booster"); + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Particle Booster"); LanguageRegistry.addName(boosterBlock, "Particle Booster"); GameRegistry.registerBlock(boosterBlock, "boosterBlock"); - GameRegistry.registerTileEntity(TileEntityParticleBooster.class, "boosterBlock"); - + GameRegistry.registerTileEntity(TileEntityParticleBooster.class, "boosterBlock"); // RAY LIFT this.liftBlock = new BlockLift(config.liftID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser lift"); LanguageRegistry.addName(liftBlock, "Laser lift"); GameRegistry.registerBlock(liftBlock, "liftBlock"); - GameRegistry.registerTileEntity(TileEntityLift.class, "liftBlock"); - + GameRegistry.registerTileEntity(TileEntityLift.class, "liftBlock"); // IRIDIUM BLOCK this.iridiumBlock = new BlockIridium(config.iridiumID) .setHardness(0.8F).setResistance(150 * 4).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Block of Iridium"); + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Block of Iridium"); LanguageRegistry.addName(iridiumBlock, "Block of Iridium"); - GameRegistry.registerBlock(iridiumBlock, "iridiumBlock"); - + GameRegistry.registerBlock(iridiumBlock, "iridiumBlock"); proxy.registerEntities(); - ForgeChunkManager.setForcedChunkLoadingCallback(instance, instance); - spaceWorldGenerator = new SpaceWorldGenerator(); GameRegistry.registerWorldGenerator(spaceWorldGenerator); - hyperSpaceWorldGenerator = new HyperSpaceWorldGenerator(); - GameRegistry.registerWorldGenerator(hyperSpaceWorldGenerator); - + GameRegistry.registerWorldGenerator(hyperSpaceWorldGenerator); registerSpaceDimension(); registerHyperSpaceDimension(); MinecraftForge.EVENT_BUS.register(new SpaceEventHandler()); - - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { - MinecraftForge.EVENT_BUS.register(new CameraOverlay(Minecraft.getMinecraft())); + + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + MinecraftForge.EVENT_BUS.register(new CameraOverlay(Minecraft.getMinecraft())); } } @PostInit - public void postInit(FMLPostInitializationEvent event) { + public void postInit(FMLPostInitializationEvent event) + { space = DimensionManager.getWorld(spaceDimID); hyperSpace = DimensionManager.getWorld(hyperSpaceDimID); - GameRegistry.addRecipe(new ItemStack(warpCore), "ici", "cmc", "ici", - 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit")); - + 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit")); GameRegistry.addRecipe(new ItemStack(protocolBlock), "iic", "imi", "cii", - 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit")); - + 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit")); GameRegistry.addRecipe(new ItemStack(radarBlock), "ifi", "imi", "imi", - 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'f', Items.getItem("frequencyTransmitter")); - + 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'f', Items.getItem("frequencyTransmitter")); GameRegistry.addRecipe(new ItemStack(isolationBlock), "iii", "idi", "iii", - 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'd', Block.blockDiamond); - + 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'd', Block.blockDiamond); GameRegistry.addRecipe(new ItemStack(airgenBlock), "lcl", "lml", "lll", - 'l', Block.leaves, 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit")); - + 'l', Block.leaves, 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit")); GameRegistry.addRecipe(new ItemStack(laserBlock), "sss", "ama", "aaa", - 'm', Items.getItem("advancedMachine"), 'a', Items.getItem("advancedAlloy"), 's', Items.getItem("advancedCircuit")); - + 'm', Items.getItem("advancedMachine"), 'a', Items.getItem("advancedAlloy"), 's', Items.getItem("advancedCircuit")); GameRegistry.addRecipe(new ItemStack(miningLaserBlock), "aaa", "ama", "ccc", - 'c', Items.getItem("advancedCircuit"), 'a', Items.getItem("advancedAlloy"), 'm', Items.getItem("miner")); - + 'c', Items.getItem("advancedCircuit"), 'a', Items.getItem("advancedAlloy"), 'm', Items.getItem("miner")); GameRegistry.addRecipe(new ItemStack(boosterBlock), "afc", "ama", "cfa", - 'c', Items.getItem("advancedCircuit"), 'a', Items.getItem("advancedAlloy"), 'f', Items.getItem("glassFiberCableItem"), 'm', Items.getItem("mfeUnit")); - + 'c', Items.getItem("advancedCircuit"), 'a', Items.getItem("advancedAlloy"), 'f', Items.getItem("glassFiberCableItem"), 'm', Items.getItem("mfeUnit")); GameRegistry.addRecipe(new ItemStack(liftBlock), "aca", "ama", "a#a", - 'c', Items.getItem("advancedCircuit"), 'a', Items.getItem("advancedAlloy"), 'm', Items.getItem("magnetizer")); - - GameRegistry.addRecipe(new ItemStack(Item.enderPearl), "uuu", "uuu", "uuu", - 'u', Items.getItem("uraniumDrop")); - + 'c', Items.getItem("advancedCircuit"), 'a', Items.getItem("advancedAlloy"), 'm', Items.getItem("magnetizer")); + /* + GameRegistry.addRecipe(new ItemStack(Item.enderPearl), "uuu", "uuu", "uuu", + 'u', Items.getItem("uraniumDrop")); + */ GameRegistry.addRecipe(new ItemStack(iridiumBlock), "iii", "iii", "iii", - 'i', Items.getItem("iridiumPlate")); - GameRegistry.addShapelessRecipe(new ItemStack(Items.getItem("iridiumPlate").getItem(), 9), new ItemStack(iridiumBlock)); - + 'i', Items.getItem("iridiumPlate")); + GameRegistry.addShapelessRecipe(new ItemStack(Items.getItem("iridiumPlate").getItem(), 9), new ItemStack(iridiumBlock)); GameRegistry.addRecipe(new ItemStack(laserCamBlock), "imi", "cec", "#k#", - 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit"), 'e', laserBlock, 'k', cameraBlock); - + 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit"), 'e', laserBlock, 'k', cameraBlock); GameRegistry.addRecipe(new ItemStack(cameraBlock), "cgc", "gmg", "cgc", - 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit"), 'g', Block.glass); - + 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit"), 'g', Block.glass); GameRegistry.addRecipe(new ItemStack(monitorBlock), "gcg", "gmg", "ggg", - 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit"), 'g', Block.glass); - + 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit"), 'g', Block.glass); registry = new WarpCoresRegistry(); - - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { - jumpGates = new JumpGatesRegistry(); - } else { - cams = new CamRegistry(); + + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) + { + jumpGates = new JumpGatesRegistry(); + } + else + { + cams = new CamRegistry(); } } - private void registerSpaceDimension() { + private void registerSpaceDimension() + { spaceBiome = (new BiomeSpace(23)).setColor(0).setDisableRain().setBiomeName("Space"); this.spaceProviderID = 14; - DimensionManager.registerProviderType(this.spaceProviderID, SpaceProvider.class, true); this.spaceDimID = DimensionManager.getNextFreeDimId(); DimensionManager.registerDimension(this.spaceDimID, this.spaceProviderID); } - private void registerHyperSpaceDimension() { + private void registerHyperSpaceDimension() + { this.hyperSpaceProviderID = 15; - DimensionManager.registerProviderType(this.hyperSpaceProviderID, HyperSpaceProvider.class, true); this.hyperSpaceDimID = DimensionManager.getNextFreeDimId(); DimensionManager.registerDimension(this.hyperSpaceDimID, this.hyperSpaceProviderID); - } - + } + @ServerStarting public void serverLoad(FMLServerStartingEvent event) { @@ -314,10 +289,12 @@ public class WarpDrive implements LoadingCallback { event.registerServerCommand(new SpaceTpCommand()); event.registerServerCommand(new InvisibleCommand()); } - + @Override - public void ticketsLoaded(List<Ticket> tickets, World world) { - for(Ticket ticket : tickets) { + public void ticketsLoaded(List<Ticket> tickets, World world) + { + for (Ticket ticket : tickets) + { ForgeChunkManager.releaseTicket(ticket); } } diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index b79e1c95..f57a01e5 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -5,64 +5,59 @@ import java.util.Set; import net.minecraftforge.common.Configuration; -public class WarpDriveConfig { - private Configuration config; - - public Set<Integer> valuableOres; - public Set<Integer> minerValuables; - - public int coreID, controllerID, radarID, isolationID, airID, airgenID, gasID, laserID, miningLaserID, particleBoosterID, liftID, laserCamID, camID, monitorID, iridiumID; - /* - * public final static int WARP_CORE_BLOCKID = 500; +public class WarpDriveConfig +{ + private Configuration config; + + public Set<Integer> valuableOres; + public Set<Integer> minerValuables; + + public int coreID, controllerID, radarID, isolationID, airID, airgenID, gasID, laserID, miningLaserID, particleBoosterID, liftID, laserCamID, camID, monitorID, iridiumID; + /* + * public final static int WARP_CORE_BLOCKID = 500; public final static int PROTOCOL_BLOCK_BLOCKID = 501; public final static int RADAR_BLOCK_BLOCKID = 502; public final static int ISOLATION_BLOCKID = 503; public final static int AIR_BLOCKID = 504; public final static int AIRGEN_BLOCKID = 505; public final static int GAS_BLOCKID = 506; - + public final static int LASER_BLOCK_BLOCKID = 507; public final static int MINING_LASER_BLOCK_BLOCKID = 508; public final static int PARTICLE_BOOSTER_BLOCKID = 509; public final static int LIFT_BLOCKID = 510; - + public final static int LASER_BLOCKCAM_BLOCKID = 512; public final static int CAMERA_BLOCKID = 513; public final static int MONITOR_BLOCKID = 514; - + public final static int IRIDIUM_BLOCKID = 515; - */ - public WarpDriveConfig(Configuration config) { - this.config = config; - - this.valuableOres = new HashSet<Integer>(); - this.minerValuables = new HashSet<Integer>(); - } - - public void loadAndSave() { - this.config.load(); - - this.coreID = this.config.getBlock("core", 500).getInt(); - this.controllerID = this.config.getBlock("controller", 501).getInt(); - - this.radarID = this.config.getBlock("radar", 502).getInt(); - this.isolationID = this.config.getBlock("isolation", 503).getInt(); - - this.airID = this.config.getBlock("air", 504).getInt(); - this.airgenID = this.config.getBlock("airgen", 505).getInt(); - this.gasID = this.config.getBlock("gas", 506).getInt(); - - this.laserID = this.config.getBlock("laser", 507).getInt(); - this.miningLaserID = this.config.getBlock("mininglaser", 508).getInt(); - this.particleBoosterID = this.config.getBlock("particlebooster", 509).getInt(); - this.liftID = this.config.getBlock("lift", 510).getInt(); - - this.laserCamID = this.config.getBlock("lasercam", 512).getInt(); - this.camID = this.config.getBlock("camera", 513).getInt(); - this.monitorID = this.config.getBlock("monitor", 514).getInt(); - - this.iridiumID = this.config.getBlock("iridium", 515).getInt(); - - this.config.save(); - } + */ + public WarpDriveConfig(Configuration config) + { + this.config = config; + this.valuableOres = new HashSet<Integer>(); + this.minerValuables = new HashSet<Integer>(); + } + + public void loadAndSave() + { + this.config.load(); + this.coreID = this.config.getBlock("core", 500).getInt(); + this.controllerID = this.config.getBlock("controller", 501).getInt(); + this.radarID = this.config.getBlock("radar", 502).getInt(); + this.isolationID = this.config.getBlock("isolation", 503).getInt(); + this.airID = this.config.getBlock("air", 504).getInt(); + this.airgenID = this.config.getBlock("airgen", 505).getInt(); + this.gasID = this.config.getBlock("gas", 506).getInt(); + this.laserID = this.config.getBlock("laser", 507).getInt(); + this.miningLaserID = this.config.getBlock("mininglaser", 508).getInt(); + this.particleBoosterID = this.config.getBlock("particlebooster", 509).getInt(); + this.liftID = this.config.getBlock("lift", 510).getInt(); + this.laserCamID = this.config.getBlock("lasercam", 512).getInt(); + this.camID = this.config.getBlock("camera", 513).getInt(); + this.monitorID = this.config.getBlock("monitor", 514).getInt(); + this.iridiumID = this.config.getBlock("iridium", 515).getInt(); + this.config.save(); + } } diff --git a/src/cr0s/WarpDrive/WorldGenSmallShip.java b/src/cr0s/WarpDrive/WorldGenSmallShip.java index 6d5a1301..875f5374 100644 --- a/src/cr0s/WarpDrive/WorldGenSmallShip.java +++ b/src/cr0s/WarpDrive/WorldGenSmallShip.java @@ -1,7 +1,6 @@ package cr0s.WarpDrive; import cpw.mods.fml.common.Loader; -import cr0s.WarpDrive.WarpDrive; import ic2.api.item.Items; import java.util.Random; import net.minecraft.block.Block; @@ -15,666 +14,696 @@ import net.minecraft.world.gen.feature.WorldGenerator; public class WorldGenSmallShip extends WorldGenerator { - private boolean corrupted; - private boolean isICBMLoaded = false, isAELoaded = false, isAdvSolPanelLoaded = false; - - public WorldGenSmallShip (boolean corrupted) { - this.corrupted = corrupted; - - isICBMLoaded = Loader.isModLoaded("ICBM|Explosion"); - isAELoaded = Loader.isModLoaded("AppliedEnergistics"); - isAdvSolPanelLoaded = Loader.isModLoaded("AdvancedSolarPanel"); + private boolean corrupted; + private boolean isICBMLoaded = false, isAELoaded = false, isAdvSolPanelLoaded = false; + + public WorldGenSmallShip(boolean corrupted) + { + this.corrupted = corrupted; + isICBMLoaded = Loader.isModLoaded("ICBM|Explosion"); + isAELoaded = Loader.isModLoaded("AppliedEnergistics"); + isAdvSolPanelLoaded = Loader.isModLoaded("AdvancedSolarPanel"); + } + + @Override + public boolean generate(World world, Random rand, int i, int j, int k) + { + ItemStack cableType = Items.getItem("copperCableBlock").copy(); + + switch (rand.nextInt(4)) + { + case 0: + cableType = Items.getItem("glassFiberCableBlock").copy(); + break; + + case 1: + cableType = Items.getItem("glassFiberCableBlock").copy(); + break; + + case 2: + cableType = Items.getItem("insulatedGoldCableBlock").copy(); + break; + + case 3: + cableType = Items.getItem("doubleInsulatedIronCableBlock").copy(); + break; } - @Override - public boolean generate(World world, Random rand, int i, int j, int k) { - ItemStack cableType = Items.getItem("copperCableBlock").copy(); - switch (rand.nextInt(4)) { - case 0: - cableType = Items.getItem("glassFiberCableBlock").copy(); - break; - case 1: - cableType = Items.getItem("glassFiberCableBlock").copy(); - break; - case 2: - cableType = Items.getItem("insulatedGoldCableBlock").copy(); - break; - case 3: - cableType = Items.getItem("doubleInsulatedIronCableBlock").copy(); - break; - } - - int ADV_SOLAR_BLOCKID = 194; - int solarType = rand.nextInt(2); - if (!isAdvSolPanelLoaded) { - ADV_SOLAR_BLOCKID = Items.getItem("solarPanel").itemID; - solarType = Items.getItem("solarPanel").getItemDamage(); - } - - world.setBlock(i + 0, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 0, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 1, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 1, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 1, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 1, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 1, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 1, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 3, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 3, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 3, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 4, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 2, j + 4, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 2, j + 4, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 2, j + 5, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 2, j + 5, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 2, j + 5, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 3, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 3, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 3, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 4, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 4, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 5, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 5, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 2, k + 5, Block.glowStone.blockID); - world.setBlock(i + 4, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 2, k + 9, Block.glowStone.blockID); - world.setBlock(i + 4, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 4, k + 4, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 4, j + 4, k + 10, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 4, j + 5, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 5, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 5, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 5, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 2, k + 4, Block.glowStone.blockID); - world.setBlock(i + 5, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 2, k + 7, Block.cloth.blockID, 14, 0); - world.setBlock(i + 5, j + 2, k + 8, Block.cloth.blockID, 8, 0); - world.setBlock(i + 5, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 2, k + 10, Block.glowStone.blockID); - world.setBlock(i + 5, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 3, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 3, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 4, k + 3, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 5, j + 4, k + 11, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 5, j + 5, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 5, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 5, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 5, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 2, k + 6, Block.cloth.blockID, 14, 0); - world.setBlock(i + 6, j + 2, k + 7, Block.cloth.blockID, 8, 0); - world.setBlock(i + 6, j + 2, k + 8, Block.cloth.blockID, 14, 0); - world.setBlock(i + 6, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - - world.setBlock(i + 6, j + 3, k + 3, Block.chest.blockID, 3, 0); - fillChestWithBonuses(world, rand, i + 6, j + 3, k + 3); - - world.setBlock(i + 6, j + 3, k + 11, Block.chest.blockID, 2, 0); - fillChestWithBonuses(world, rand, i + 6, j + 3, k + 11); - - world.setBlock(i + 6, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 4, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - - world.setBlock(i + 6, j + 4, k + 3, Block.chest.blockID, 3, 0); - fillChestWithBonuses(world, rand, i + 6, j + 4, k + 3); - - world.setBlock(i + 6, j + 4, k + 11, Block.chest.blockID, 2, 0); - fillChestWithBonuses(world, rand, i + 6, j + 4, k + 11); - - world.setBlock(i + 6, j + 4, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 5, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 5, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 2, k + 7, Block.cloth.blockID, 8, 0); - world.setBlock(i + 7, j + 2, k + 8, Block.cloth.blockID, 8, 0); - world.setBlock(i + 7, j + 2, k + 9, Block.cloth.blockID, 14, 0); - world.setBlock(i + 7, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 7, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 7, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 7, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 7, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 7, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); - world.setBlock(i + 7, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 7, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 2, k + 6, Block.cloth.blockID, 14, 0); - world.setBlock(i + 8, j + 2, k + 7, Block.cloth.blockID, 14, 0); - world.setBlock(i + 8, j + 2, k + 8, Block.cloth.blockID, 14, 0); - world.setBlock(i + 8, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 8, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 8, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 8, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 8, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 8, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); - world.setBlock(i + 8, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 2, k + 5, Block.cloth.blockID, 14, 0); - world.setBlock(i + 9, j + 2, k + 6, Block.cloth.blockID, 8, 0); - world.setBlock(i + 9, j + 2, k + 7, Block.cloth.blockID, 14, 0); - world.setBlock(i + 9, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 2, k + 10, Block.cloth.blockID, 14, 0); - world.setBlock(i + 9, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 9, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 9, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 9, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 9, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 9, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); - // Placing air generator - world.setBlock(i + 9, j + 5, k + 7, WarpDrive.instance.config.airgenID, 0, 0); - - world.setBlock(i + 9, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 8, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 8, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 2, k + 5, Block.cloth.blockID, 8, 0); - world.setBlock(i + 10, j + 2, k + 6, Block.cloth.blockID, 8, 0); - world.setBlock(i + 10, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 2, k + 9, Block.cloth.blockID, 8, 0); - world.setBlock(i + 10, j + 2, k + 10, Block.cloth.blockID, 14, 0); - world.setBlock(i + 10, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 3, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 10, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 10, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 10, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 10, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 10, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 10, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); - - // Placing air generator - world.setBlock(i + 10, j + 5, k + 7, WarpDrive.instance.config.airgenID, 0, 0); - - world.setBlock(i + 10, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 8, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 8, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 3, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); - - // Place warp-controller - if (rand.nextBoolean()) { - world.setBlock(i + 11, j + 3, k + 7, WarpDrive.instance.config.controllerID); - } - - world.setBlock(i + 11, j + 3, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 4, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); - - // Place computer - if (rand.nextBoolean()) { - world.setBlock(i + 11, j + 4, k + 7, 1225, 16384, 0); - } - - - world.setBlock(i + 11, j + 4, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 5, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 11, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); - world.setBlock(i + 11, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 8, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 8, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 9, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 9, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 3, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); - - // Place warp-core - if (rand.nextBoolean()) { - world.setBlock(i + 12, j + 3, k + 7, WarpDrive.instance.config.coreID); - } - - world.setBlock(i + 12, j + 3, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 4, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 4, k + 7, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 12, j + 4, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 5, k + 7, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 12, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 12, j + 6, k + 7, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 12, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 3, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 11, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 4, Block.glowStone.blockID); - world.setBlock(i + 13, j + 5, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 10, Block.glowStone.blockID); - world.setBlock(i + 13, j + 5, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 4, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 4, k + 5, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 4, k + 6, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 4, k + 8, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 4, k + 9, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 4, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 5, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 5, k + 5, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 5, k + 6, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 5, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 5, k + 8, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 5, k + 9, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 5, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 5, k + 7, Block.blockRedstone.blockID); - world.setBlock(i + 15, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 16, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 16, j + 5, k + 7, Block.blockRedstone.blockID); - world.setBlock(i + 16, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 17, j + 5, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - - world.setBlock(i + 12, j + 2, k + 9, Block.trapdoor.blockID, 10, 0); - - spawnNPC(world, i + 9, j + 3, k + 5); - - return true; - } - - public void spawnNPC(World world, int i, int j, int k) { + int ADV_SOLAR_BLOCKID = 194; + int solarType = rand.nextInt(2); + + if (!isAdvSolPanelLoaded) + { + ADV_SOLAR_BLOCKID = Items.getItem("solarPanel").itemID; + solarType = Items.getItem("solarPanel").getItemDamage(); + } + + world.setBlock(i + 0, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 0, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 1, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 1, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 1, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 1, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 1, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 1, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 3, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 3, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 3, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 4, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 2, j + 4, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 2, j + 4, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 2, j + 5, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 2, j + 5, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 2, j + 5, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 3, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 3, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 3, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 4, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 4, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 5, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 5, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 2, k + 5, Block.glowStone.blockID); + world.setBlock(i + 4, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 2, k + 9, Block.glowStone.blockID); + world.setBlock(i + 4, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 4, k + 4, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 4, j + 4, k + 10, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 4, j + 5, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 5, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 5, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 5, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 2, k + 4, Block.glowStone.blockID); + world.setBlock(i + 5, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 2, k + 7, Block.cloth.blockID, 14, 0); + world.setBlock(i + 5, j + 2, k + 8, Block.cloth.blockID, 8, 0); + world.setBlock(i + 5, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 2, k + 10, Block.glowStone.blockID); + world.setBlock(i + 5, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 3, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 3, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 4, k + 3, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 5, j + 4, k + 11, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 5, j + 5, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 5, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 5, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 5, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 2, k + 6, Block.cloth.blockID, 14, 0); + world.setBlock(i + 6, j + 2, k + 7, Block.cloth.blockID, 8, 0); + world.setBlock(i + 6, j + 2, k + 8, Block.cloth.blockID, 14, 0); + world.setBlock(i + 6, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 3, k + 3, Block.chest.blockID, 3, 0); + fillChestWithBonuses(world, rand, i + 6, j + 3, k + 3); + world.setBlock(i + 6, j + 3, k + 11, Block.chest.blockID, 2, 0); + fillChestWithBonuses(world, rand, i + 6, j + 3, k + 11); + world.setBlock(i + 6, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 4, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 4, k + 3, Block.chest.blockID, 3, 0); + fillChestWithBonuses(world, rand, i + 6, j + 4, k + 3); + world.setBlock(i + 6, j + 4, k + 11, Block.chest.blockID, 2, 0); + fillChestWithBonuses(world, rand, i + 6, j + 4, k + 11); + world.setBlock(i + 6, j + 4, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 5, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 5, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 2, k + 7, Block.cloth.blockID, 8, 0); + world.setBlock(i + 7, j + 2, k + 8, Block.cloth.blockID, 8, 0); + world.setBlock(i + 7, j + 2, k + 9, Block.cloth.blockID, 14, 0); + world.setBlock(i + 7, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 7, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 7, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 7, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 7, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 7, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); + world.setBlock(i + 7, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 7, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 2, k + 6, Block.cloth.blockID, 14, 0); + world.setBlock(i + 8, j + 2, k + 7, Block.cloth.blockID, 14, 0); + world.setBlock(i + 8, j + 2, k + 8, Block.cloth.blockID, 14, 0); + world.setBlock(i + 8, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 8, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 8, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 8, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 8, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 8, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); + world.setBlock(i + 8, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 2, k + 5, Block.cloth.blockID, 14, 0); + world.setBlock(i + 9, j + 2, k + 6, Block.cloth.blockID, 8, 0); + world.setBlock(i + 9, j + 2, k + 7, Block.cloth.blockID, 14, 0); + world.setBlock(i + 9, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 2, k + 10, Block.cloth.blockID, 14, 0); + world.setBlock(i + 9, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 9, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 9, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 9, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 9, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 9, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); + // Placing air generator + world.setBlock(i + 9, j + 5, k + 7, WarpDrive.instance.config.airgenID, 0, 0); + world.setBlock(i + 9, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 8, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 8, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 2, k + 5, Block.cloth.blockID, 8, 0); + world.setBlock(i + 10, j + 2, k + 6, Block.cloth.blockID, 8, 0); + world.setBlock(i + 10, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 2, k + 9, Block.cloth.blockID, 8, 0); + world.setBlock(i + 10, j + 2, k + 10, Block.cloth.blockID, 14, 0); + world.setBlock(i + 10, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 3, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 10, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 10, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 10, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 10, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 10, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 10, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); + // Placing air generator + world.setBlock(i + 10, j + 5, k + 7, WarpDrive.instance.config.airgenID, 0, 0); + world.setBlock(i + 10, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 8, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 8, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 3, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); + + // Place warp-controller + if (rand.nextBoolean()) + { + world.setBlock(i + 11, j + 3, k + 7, WarpDrive.instance.config.controllerID); + } + + world.setBlock(i + 11, j + 3, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 4, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); + + // Place computer + if (rand.nextBoolean()) + { + world.setBlock(i + 11, j + 4, k + 7, 1225, 16384, 0); + } + + world.setBlock(i + 11, j + 4, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 5, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 11, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); + world.setBlock(i + 11, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 8, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 8, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 9, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 9, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 3, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); + + // Place warp-core + if (rand.nextBoolean()) + { + world.setBlock(i + 12, j + 3, k + 7, WarpDrive.instance.config.coreID); + } + + world.setBlock(i + 12, j + 3, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 4, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 4, k + 7, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 12, j + 4, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 5, k + 7, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 12, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 12, j + 6, k + 7, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 12, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 3, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 11, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 4, Block.glowStone.blockID); + world.setBlock(i + 13, j + 5, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 10, Block.glowStone.blockID); + world.setBlock(i + 13, j + 5, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 4, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 4, k + 5, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 4, k + 6, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 4, k + 8, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 4, k + 9, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 4, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 5, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 5, k + 5, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 5, k + 6, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 5, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 5, k + 8, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 5, k + 9, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 5, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 5, k + 7, Block.blockRedstone.blockID); + world.setBlock(i + 15, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 16, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 16, j + 5, k + 7, Block.blockRedstone.blockID); + world.setBlock(i + 16, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 17, j + 5, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 9, Block.trapdoor.blockID, 10, 0); + spawnNPC(world, i + 9, j + 3, k + 5); + return true; + } + + public void spawnNPC(World world, int i, int j, int k) + { int numMobs = 2 + world.rand.nextInt(10); - - if (world.rand.nextBoolean()) { // Villagers - for (int idx = 0; idx < numMobs; idx++) { + + if (world.rand.nextBoolean()) // Villagers + { + for (int idx = 0; idx < numMobs; idx++) + { EntityVillager entityvillager = new EntityVillager(world, 0); entityvillager.setLocationAndAngles((double)i + 0.5D, (double)j, (double)k + 0.5D, 0.0F, 0.0F); world.spawnEntityInWorld(entityvillager); } - } else // Zombies + } + else // Zombies { - for (int idx = 0; idx < numMobs; idx++) { + for (int idx = 0; idx < numMobs; idx++) + { EntityZombie entityzombie = new EntityZombie(world); entityzombie.setLocationAndAngles((double)i + 0.5D, (double)j, (double)k + 0.5D, 0.0F, 0.0F); world.spawnEntityInWorld(entityzombie); - } + } } } - - public void fillChestWithBonuses(World worldObj, Random rand, int x, int y, int z) { - TileEntity te = worldObj.getBlockTileEntity(x, y, z); - if (te != null) { - TileEntityChest chest = (TileEntityChest)te; - int numBonuses = rand.nextInt(28); + public void fillChestWithBonuses(World worldObj, Random rand, int x, int y, int z) + { + TileEntity te = worldObj.getBlockTileEntity(x, y, z); - for (int i = 0; i < chest.getSizeInventory(); i++) - { - if (rand.nextInt(15) == 0) { - numBonuses--; + if (te != null) + { + TileEntityChest chest = (TileEntityChest)te; + int numBonuses = rand.nextInt(28); - chest.setInventorySlotContents(i, getRandomBonus(rand)); - } - } - } - } - - private ItemStack getRandomBonus(Random rand) { - ItemStack res = null; - boolean isDone = false; - while (!isDone) { - switch (rand.nextInt(14)) { - case 0: - res = Items.getItem("massFabricator").copy(); - res.stackSize = 1 + rand.nextInt(2); - isDone = true; - break; - case 1: - res = Items.getItem("nuke").copy(); - res.stackSize = 1 + rand.nextInt(64); - isDone = true; - break; - case 2: // Quantum armor bonuses - case 3: - case 4: - case 5: - isDone = true; - break;// skipped - case 6: - res = Items.getItem("glassFiberCableItem").copy(); - res.stackSize = 2 + rand.nextInt(63); - isDone = true; - break; - case 7: - res = Items.getItem("matter").copy(); - res.stackSize = 2 + rand.nextInt(63); - isDone = true; - break; - case 8: - isDone = true; - break;// skipped - // AE Quarz - case 9: - if (isAELoaded) { - res = new ItemStack(4362, 2 + rand.nextInt(63), 6).copy(); - isDone = true; - } - break; - // AE improved processor - case 10: - if (isAELoaded) { - res = new ItemStack(4362, 2 + rand.nextInt(15), 19).copy(); - isDone = true; - } - break; - // Rocket launcher platform Tier3 - case 11: - if (isICBMLoaded) { - res = new ItemStack(3884, 2 + rand.nextInt(1), 2).copy(); - isDone = true; - } - break; - // Missles from conventional to hypersonic - case 12: - if (isICBMLoaded) { - res = new ItemStack(4159, 2 + rand.nextInt(1), rand.nextInt(21)).copy(); - isDone = true; - } - break; - // Advanced solar panels - case 13: - if (isAdvSolPanelLoaded) { - res = new ItemStack(194, 2 + rand.nextInt(1), rand.nextInt(3)).copy(); - isDone = true; - } - break; - } - } - return res; - } + for (int i = 0; i < chest.getSizeInventory(); i++) + { + if (rand.nextInt(15) == 0) + { + numBonuses--; + chest.setInventorySlotContents(i, getRandomBonus(rand)); + } + } + } + } + + private ItemStack getRandomBonus(Random rand) + { + ItemStack res = null; + boolean isDone = false; + + while (!isDone) + { + switch (rand.nextInt(14)) + { + case 0: + res = Items.getItem("massFabricator").copy(); + res.stackSize = 1 + rand.nextInt(2); + isDone = true; + break; + + case 1: + res = Items.getItem("nuke").copy(); + res.stackSize = 1 + rand.nextInt(64); + isDone = true; + break; + + case 2: // Quantum armor bonuses + case 3: + case 4: + case 5: + isDone = true; + break;// skipped + + case 6: + res = Items.getItem("glassFiberCableItem").copy(); + res.stackSize = 2 + rand.nextInt(63); + isDone = true; + break; + + case 7: + res = Items.getItem("matter").copy(); + res.stackSize = 2 + rand.nextInt(63); + isDone = true; + break; + + case 8: + isDone = true; + break;// skipped + + // AE Quarz + case 9: + if (isAELoaded) + { + res = new ItemStack(4362, 2 + rand.nextInt(63), 6).copy(); + isDone = true; + } + + break; + + // AE improved processor + case 10: + if (isAELoaded) + { + res = new ItemStack(4362, 2 + rand.nextInt(15), 19).copy(); + isDone = true; + } + + break; + + // Rocket launcher platform Tier3 + case 11: + if (isICBMLoaded) + { + res = new ItemStack(3884, 2 + rand.nextInt(1), 2).copy(); + isDone = true; + } + + break; + + // Missles from conventional to hypersonic + case 12: + if (isICBMLoaded) + { + res = new ItemStack(4159, 2 + rand.nextInt(1), rand.nextInt(21)).copy(); + isDone = true; + } + + break; + + // Advanced solar panels + case 13: + if (isAdvSolPanelLoaded) + { + res = new ItemStack(194, 2 + rand.nextInt(1), rand.nextInt(3)).copy(); + isDone = true; + } + + break; + } + } + + return res; + } } diff --git a/src/cr0s/WarpDrive/WorldGenStation.java b/src/cr0s/WarpDrive/WorldGenStation.java index a507d129..e91b1bf6 100644 --- a/src/cr0s/WarpDrive/WorldGenStation.java +++ b/src/cr0s/WarpDrive/WorldGenStation.java @@ -12,11 +12,12 @@ import net.minecraft.world.World; * * @author user */ -public class WorldGenStation { +public class WorldGenStation +{ public WorldGenStation() { } - - public boolean generate(World world, Random rand, int i, int j, int k) { + public boolean generate(World world, Random rand, int i, int j, int k) + { world.setBlock(i + 1, j + 0, k + 3, Block.stone.blockID); world.setBlock(i + 1, j + 0, k + 12, Block.stone.blockID); world.setBlock(i + 1, j + 1, k + 3, Block.stone.blockID); @@ -614,7 +615,6 @@ public class WorldGenStation { world.setBlock(i + 12, j + 6, k + 12, Block.stone.blockID); world.setBlock(i + 12, j + 7, k + 3, Block.stone.blockID); world.setBlock(i + 12, j + 7, k + 12, Block.stone.blockID); - - return true; - } + return true; + } } diff --git a/src/cr0s/WarpDrive/WorldGenStructure.java b/src/cr0s/WarpDrive/WorldGenStructure.java index c436f533..7ba29f1b 100644 --- a/src/cr0s/WarpDrive/WorldGenStructure.java +++ b/src/cr0s/WarpDrive/WorldGenStructure.java @@ -3,24 +3,29 @@ package cr0s.WarpDrive; import ic2.api.item.Items; import java.util.Random; -public class WorldGenStructure { - public static int getStoneBlock(boolean corrupted, Random rand) { - int res = Items.getItem("reinforcedStone").itemID; - - if (corrupted && (rand.nextInt(15) == 1)) { - res = 0; - } - - return res; - } - - public static int getGlassBlock(boolean corrupted, Random rand) { - int res = Items.getItem("reinforcedGlass").itemID; - - if (corrupted && (rand.nextInt(30) == 1)) { - res = 0; - } - - return res; - } +public class WorldGenStructure +{ + public static int getStoneBlock(boolean corrupted, Random rand) + { + int res = Items.getItem("reinforcedStone").itemID; + + if (corrupted && (rand.nextInt(15) == 1)) + { + res = 0; + } + + return res; + } + + public static int getGlassBlock(boolean corrupted, Random rand) + { + int res = Items.getItem("reinforcedGlass").itemID; + + if (corrupted && (rand.nextInt(30) == 1)) + { + res = 0; + } + + return res; + } } diff --git a/src/cr0s/WarpDrive/client/ClientProxy.java b/src/cr0s/WarpDrive/client/ClientProxy.java index 1dc1826d..52e12840 100644 --- a/src/cr0s/WarpDrive/client/ClientProxy.java +++ b/src/cr0s/WarpDrive/client/ClientProxy.java @@ -6,16 +6,17 @@ import cr0s.WarpDrive.CommonProxy; import cr0s.WarpDrive.FXBeam; import cr0s.WarpDrive.Vector3; -public class ClientProxy extends CommonProxy { +public class ClientProxy extends CommonProxy +{ + @Override + public void registerRenderers() + { + } @Override - public void registerRenderers() { + public void renderBeam(World world, Vector3 position, Vector3 target, float red, float green, float blue, int age, int energy) + { + System.out.println("Rendering beam..."); + FMLClientHandler.instance().getClient().effectRenderer.addEffect(new FXBeam(world, position, target, red, green, blue, age, energy)); } - - @Override - public void renderBeam(World world, Vector3 position, Vector3 target, float red, float green, float blue, int age, int energy) - { - System.out.println("Rendering beam..."); - FMLClientHandler.instance().getClient().effectRenderer.addEffect(new FXBeam(world, position, target, red, green, blue, age, energy)); - } } \ No newline at end of file diff --git a/src/cr0s/WarpDriveCore/WCClassTransformer.java b/src/cr0s/WarpDriveCore/WCClassTransformer.java index a131b1ec..8032b7e4 100644 --- a/src/cr0s/WarpDriveCore/WCClassTransformer.java +++ b/src/cr0s/WarpDriveCore/WCClassTransformer.java @@ -1,6 +1,5 @@ package cr0s.WarpDriveCore; - import java.io.File; import java.io.InputStream; import java.util.HashMap; @@ -17,14 +16,15 @@ import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.VarInsnNode; -public class WCClassTransformer implements net.minecraft.launchwrapper.IClassTransformer { +public class WCClassTransformer implements net.minecraft.launchwrapper.IClassTransformer +{ + private HashMap<String, String> nodemap = new HashMap<String, String>(); - private HashMap<String,String> nodemap = new HashMap<String, String>(); - - private final String GRAVITY_MANAGER_CLASS = "cr0s/WarpDrive/GravityManager"; - - public WCClassTransformer() { - // Obfuscated Notch methods + private final String GRAVITY_MANAGER_CLASS = "cr0s/WarpDrive/GravityManager"; + + public WCClassTransformer() + { + // Obfuscated Notch methods nodemap.put("worldClass", "abv"); nodemap.put("playerMP", "ju"); nodemap.put("netLoginHandler", "jx"); @@ -66,49 +66,61 @@ public class WCClassTransformer implements net.minecraft.launchwrapper.IClassTra nodemap.put("clickMiddleMouseButtonDesc", "()V"); nodemap.put("itemRendererClass", "bfg"); nodemap.put("renderOverlaysMethod", "b"); - nodemap.put("renderOverlaysDesc", "(F)V"); - } - - @Override - public byte[] transform(String name, String transformedName, byte[] bytes) { - - if (nodemap == null) { - System.out.println("========= NODEMAP IS NULL!!! ========"); - return bytes; - } - - if (name.replace('.', '/').equals(nodemap.get("entityLivingClass"))) { - bytes = transformEntityLiving(bytes); - } else - if(name.replace('.', '/').equals(nodemap.get("entityItemClass"))) { - bytes = transformEntityItem(bytes); - } - - return bytes; - } + nodemap.put("renderOverlaysDesc", "(F)V"); + } - private byte[] transformEntityItem( byte[] bytes) { + @Override + public byte[] transform(String name, String transformedName, byte[] bytes) + { + if (nodemap == null) + { + System.out.println("========= NODEMAP IS NULL!!! ========"); + return bytes; + } + + if (name.replace('.', '/').equals(nodemap.get("entityLivingClass"))) + { + bytes = transformEntityLiving(bytes); + } + else if (name.replace('.', '/').equals(nodemap.get("entityItemClass"))) + { + bytes = transformEntityItem(bytes); + } + + return bytes; + } + + private byte[] transformEntityItem(byte[] bytes) + { ClassNode node = new ClassNode(); ClassReader reader = new ClassReader(bytes); reader.accept(node, 0); int operationCount = 2; int injectionCount = 0; Iterator methods = node.methods.iterator(); + do { - if(!methods.hasNext()) + if (!methods.hasNext()) + { break; + } + MethodNode methodnode = (MethodNode)methods.next(); - if(methodnode.name.equals(nodemap.get("onUpdateMethod")) && methodnode.desc.equals(nodemap.get("onUpdateDesc"))) + + if (methodnode.name.equals(nodemap.get("onUpdateMethod")) && methodnode.desc.equals(nodemap.get("onUpdateDesc"))) { int count = 0; - while(count < methodnode.instructions.size()) + + while (count < methodnode.instructions.size()) { AbstractInsnNode list = methodnode.instructions.get(count); - if(list instanceof LdcInsnNode) + + if (list instanceof LdcInsnNode) { LdcInsnNode nodeAt = (LdcInsnNode)list; - if(nodeAt.cst.equals(Double.valueOf(0.039999999105930328D))) + + if (nodeAt.cst.equals(Double.valueOf(0.039999999105930328D))) { VarInsnNode beforeNode = new VarInsnNode(25, 0); MethodInsnNode overwriteNode = new MethodInsnNode(184, GRAVITY_MANAGER_CLASS, "getItemGravity", (new StringBuilder()).append("(L").append((String)nodemap.get("entityItemClass")).append(";)D").toString()); @@ -116,7 +128,8 @@ public class WCClassTransformer implements net.minecraft.launchwrapper.IClassTra methodnode.instructions.set(nodeAt, overwriteNode); injectionCount++; } - if(nodeAt.cst.equals(Double.valueOf(0.98000001907348633D))) + + if (nodeAt.cst.equals(Double.valueOf(0.98000001907348633D))) { VarInsnNode beforeNode = new VarInsnNode(25, 0); MethodInsnNode overwriteNode = new MethodInsnNode(184, GRAVITY_MANAGER_CLASS, "getItemGravity2", (new StringBuilder()).append("(L").append((String)nodemap.get("entityItemClass")).append(";)D").toString()); @@ -125,39 +138,51 @@ public class WCClassTransformer implements net.minecraft.launchwrapper.IClassTra injectionCount++; } } + count++; } } - } while(true); + } + while (true); + ClassWriter writer = new ClassWriter(1); node.accept(writer); bytes = writer.toByteArray(); System.out.println((new StringBuilder()).append("[WDCore] WarpDrive successfully injected bytecode into: ").append(node.name).append(" (").append(injectionCount).append(" / ").append(operationCount).append(")").toString()); return bytes; - } + } - private byte[] transformEntityLiving(byte[] bytes) { + private byte[] transformEntityLiving(byte[] bytes) + { ClassNode node = new ClassNode(); ClassReader reader = new ClassReader(bytes); reader.accept(node, 0); int operationCount = 1; int injectionCount = 0; Iterator methods = node.methods.iterator(); + do { - if(!methods.hasNext()) + if (!methods.hasNext()) + { break; + } + MethodNode methodnode = (MethodNode)methods.next(); - if(methodnode.name.equals(nodemap.get("moveEntityMethod")) && methodnode.desc.equals(nodemap.get("moveEntityDesc"))) + + if (methodnode.name.equals(nodemap.get("moveEntityMethod")) && methodnode.desc.equals(nodemap.get("moveEntityDesc"))) { int count = 0; - while(count < methodnode.instructions.size()) + + while (count < methodnode.instructions.size()) { AbstractInsnNode list = methodnode.instructions.get(count); - if(list instanceof LdcInsnNode) + + if (list instanceof LdcInsnNode) { LdcInsnNode nodeAt = (LdcInsnNode)list; - if(nodeAt.cst.equals(Double.valueOf(0.080000000000000002D))) + + if (nodeAt.cst.equals(Double.valueOf(0.080000000000000002D))) { VarInsnNode beforeNode = new VarInsnNode(25, 0); MethodInsnNode overwriteNode = new MethodInsnNode(184, GRAVITY_MANAGER_CLASS, "getGravityForEntity", (new StringBuilder()).append("(L").append((String)nodemap.get("entityLivingClass")).append(";)D").toString()); @@ -166,14 +191,17 @@ public class WCClassTransformer implements net.minecraft.launchwrapper.IClassTra injectionCount++; } } + count++; } } - } while(true); + } + while (true); + ClassWriter writer = new ClassWriter(1); node.accept(writer); bytes = writer.toByteArray(); System.out.println((new StringBuilder()).append("[WDCore] WarpDrive successfully injected bytecode into: ").append(node.name).append(" (").append(injectionCount).append(" / ").append(operationCount).append(")").toString()); return bytes; - } + } } diff --git a/src/cr0s/WarpDriveCore/WCDummyContainer.java b/src/cr0s/WarpDriveCore/WCDummyContainer.java index ccff7bd3..deb2b4a8 100644 --- a/src/cr0s/WarpDriveCore/WCDummyContainer.java +++ b/src/cr0s/WarpDriveCore/WCDummyContainer.java @@ -13,50 +13,48 @@ import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; -public class WCDummyContainer extends DummyModContainer { +public class WCDummyContainer extends DummyModContainer +{ + public WCDummyContainer() + { + super(new ModMetadata()); + ModMetadata meta = getMetadata(); + meta.modId = "WarpDriveCore"; + meta.name = "WarpDriveCore"; + meta.version = "1.0.0.0"; + meta.credits = "Cr0s"; + meta.authorList = Arrays.asList("cr0s"); + meta.description = ""; + meta.url = ""; + meta.updateUrl = ""; + meta.screenshots = new String[0]; + meta.logoFile = ""; + } - public WCDummyContainer() { + @Override + public boolean registerBus(EventBus bus, LoadController controller) + { + bus.register(this); + return true; + } - super(new ModMetadata()); - ModMetadata meta = getMetadata(); - meta.modId = "WarpDriveCore"; - meta.name = "WarpDriveCore"; - meta.version = "1.0.0.0"; - meta.credits = "Cr0s"; - meta.authorList = Arrays.asList("cr0s"); - meta.description = ""; - meta.url = ""; - meta.updateUrl = ""; - meta.screenshots = new String[0]; - meta.logoFile = ""; + @Subscribe + public void modConstruction(FMLConstructionEvent evt) + { + } - } + @Subscribe + public void init(FMLInitializationEvent evt) + { + } - @Override - public boolean registerBus(EventBus bus, LoadController controller) { - bus.register(this); - return true; - } - - - @Subscribe - public void modConstruction(FMLConstructionEvent evt){ - - } - - @Subscribe - public void init(FMLInitializationEvent evt) { - - } - - @Subscribe - public void preInit(FMLPreInitializationEvent evt) { - - } - - @Subscribe - public void postInit(FMLPostInitializationEvent evt) { - - } + @Subscribe + public void preInit(FMLPreInitializationEvent evt) + { + } + @Subscribe + public void postInit(FMLPostInitializationEvent evt) + { + } } diff --git a/src/cr0s/WarpDriveCore/WCFMLLoadingPlugin.java b/src/cr0s/WarpDriveCore/WCFMLLoadingPlugin.java index e3923995..4b5ef165 100644 --- a/src/cr0s/WarpDriveCore/WCFMLLoadingPlugin.java +++ b/src/cr0s/WarpDriveCore/WCFMLLoadingPlugin.java @@ -10,39 +10,43 @@ import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; @MCVersion(value = "1.6.2") public class WCFMLLoadingPlugin implements IFMLLoadingPlugin, IFMLCallHook { + public static File location; - public static File location; - - @Override - public String[] getLibraryRequestClass() { - return null; - } + @Override + public String[] getLibraryRequestClass() + { + return null; + } - @Override - public String[] getASMTransformerClass() { - return new String[]{ WCClassTransformer.class.getName() }; - } + @Override + public String[] getASMTransformerClass() + { + return new String[] { WCClassTransformer.class.getName() }; + } - @Override - public String getModContainerClass() { - return WCDummyContainer.class.getName(); - } + @Override + public String getModContainerClass() + { + return WCDummyContainer.class.getName(); + } - @Override - public String getSetupClass() { - return getClass().getName(); - } + @Override + public String getSetupClass() + { + return getClass().getName(); + } - @Override - public void injectData(Map<String, Object> data) { - location = (File) data.get("coremodLocation"); - System.out.println("*** Transformer jar location location.getName: " + location.getName()); - } - - @Override - public Void call() throws Exception { - System.out.println("[WCD] call()"); - return null; - } + @Override + public void injectData(Map<String, Object> data) + { + location = (File) data.get("coremodLocation"); + System.out.println("*** Transformer jar location location.getName: " + location.getName()); + } + @Override + public Void call() throws Exception + { + System.out.println("[WCD] call()"); + return null; + } } \ No newline at end of file diff --git a/src/cr0s/serverMods/AntiFallDamage.java b/src/cr0s/serverMods/AntiFallDamage.java index 807d88f7..f6909695 100644 --- a/src/cr0s/serverMods/AntiFallDamage.java +++ b/src/cr0s/serverMods/AntiFallDamage.java @@ -10,25 +10,30 @@ import net.minecraftforge.event.entity.living.LivingFallEvent; * Гашение урона при падении с джетпаком или квантовыми бутсами * @author Cr0s */ -public class AntiFallDamage { +public class AntiFallDamage +{ private final int JETPACK_ID = 30210; private final int ELECTRIC_JETPACK_ID = 30209; private final int QUANTUM_BOOTS_ID = 30171; - + @ForgeSubscribe - public void livingFall(LivingFallEvent event) { + public void livingFall(LivingFallEvent event) + { EntityLivingBase entity = event.entityLiving; float distance = event.distance; - if (entity instanceof EntityPlayer) { + if (entity instanceof EntityPlayer) + { EntityPlayer player = (EntityPlayer) entity; - int check = MathHelper.ceiling_float_int(distance - 3.0F); - if (check > 0) { // Падение может нанести урон + + if (check > 0) // Падение может нанести урон + { // Проверяем наличие защиты if ((player.getCurrentArmor(0) != null && player.getCurrentArmor(0).itemID == QUANTUM_BOOTS_ID) || (player.getCurrentArmor(2) != null && player.getCurrentArmor(2).itemID == JETPACK_ID) || - (player.getCurrentArmor(2) != null && player.getCurrentArmor(2).itemID == ELECTRIC_JETPACK_ID)) { + (player.getCurrentArmor(2) != null && player.getCurrentArmor(2).itemID == ELECTRIC_JETPACK_ID)) + { event.setCanceled(true); // Блокируем падение, если защита есть } } diff --git a/src/cr0s/serverMods/CommonProxy.java b/src/cr0s/serverMods/CommonProxy.java index 9391b03f..36d96e05 100644 --- a/src/cr0s/serverMods/CommonProxy.java +++ b/src/cr0s/serverMods/CommonProxy.java @@ -1,8 +1,9 @@ package cr0s.serverMods; -public class CommonProxy { +public class CommonProxy +{ // some code goes here - public void setupLoginHook() { - + public void setupLoginHook() + { } } \ No newline at end of file diff --git a/src/cr0s/serverMods/LoginHookClass.java b/src/cr0s/serverMods/LoginHookClass.java index d983054e..431fb252 100644 --- a/src/cr0s/serverMods/LoginHookClass.java +++ b/src/cr0s/serverMods/LoginHookClass.java @@ -10,140 +10,126 @@ import net.minecraft.network.NetLoginHandler; import net.minecraft.network.packet.NetHandler; import net.minecraft.network.packet.Packet1Login; import net.minecraft.server.MinecraftServer; +import com.google.common.base.Strings; -/** - * Авторизация РЅРёРє.пароль - * @author Cr0s - */ -public class LoginHookClass implements IConnectionHandler { +public class LoginHookClass implements IConnectionHandler +{ + private String checkLogin(String s) throws FileNotFoundException, IOException + { + if (s.indexOf(".") == -1 || s.split("\\.").length != 2) + return "Никнейм и пароль должны быть разделены точками."; - private String kickReason = ""; - private File uFile; + if (!s.matches("^[a-zA-Z0-9_.]+$")) + return "Имя пользователя или пароль содержат недопустимые символы."; - public LoginHookClass() { - uFile = MinecraftServer.getServer().getFile("users.txt"); - } + String s4 = s.split("\\.")[0].trim(); + String s5 = s.split("\\.")[1].trim(); - private void checkLogin(NetLoginHandler netHandler) throws FileNotFoundException, IOException { - String s = netHandler.clientUsername; - System.out.println("[SERVER MODS] Logging in user: " + s); - - BufferedReader bufferedreader = new BufferedReader(new FileReader(uFile)); + if (s4.length() < 2 && !s4.equals("Q")) + return "Имя пользователя слишком короткое."; - if (s.indexOf(".") == -1 || s.split("\\.").length != 2) { - kickReason = "Никнейм Рё пароль должны быть разделены точками."; - bufferedreader.close(); - return; - } + if (s5.length() < 3) + return "Пароль слишком короткий."; - if (!s.matches("^[a-zA-Z0-9_.]+$")) { - kickReason = "Р�РјСЏ пользователя или пароль содержат недопустимые символы."; - bufferedreader.close(); - return; - } + if (s4.length() > 15) + return "\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u0434\u043B\u0438\u043D\u043D\u044B\u0439 \u043B\u043E\u0433\u0438\u043D! (>15)"; - String s4 = s.split("\\.")[0].trim(); - String s5 = s.split("\\.")[1].trim(); + BufferedReader bufferedreader = new BufferedReader(new FileReader(MinecraftServer.getServer().getFile("users.txt"))); - if (s4.length() < 2 && !s4.equals("Q")) { - kickReason = "Р�РјСЏ пользователя слишком короткое."; - bufferedreader.close(); - return; - } + String s1; - if (s5.length() < 3) { - kickReason = "Пароль слишком короткий."; - bufferedreader.close(); - return; - } + while ((s1 = bufferedreader.readLine()) != null) + { + String s2; + String s3; - if (s4.length() > 15) { - kickReason = "\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u0434\u043B\u0438\u043D\u043D\u044B\u0439 \u043B\u043E\u0433\u0438\u043D! (>15)"; - bufferedreader.close(); - return; - } + try + { + s2 = s1.split("\\.")[0]; + s3 = s1.split("\\.")[1]; + } + catch (Exception exception) + { + bufferedreader.close(); + return "login.password error, database is corrupted."; + } - String s1; + if (s2.toLowerCase().equals(s4.toLowerCase())) + { + if (!s3.equals(s5)) + { + System.out.println((new StringBuilder()).append(s).append(" failed to login (pwd: ").append(s3).append(")").toString()); + bufferedreader.close(); + return "Неправильный пароль!"; + } + else + { + bufferedreader.close(); + return ""; + } + } + } - while ((s1 = bufferedreader.readLine()) != null) { - String s2; - String s3; + bufferedreader.close(); + PrintWriter printwriter = new PrintWriter(new FileWriter(MinecraftServer.getServer().getFile("users.txt"), true)); + printwriter.println(s); + printwriter.close(); + return ""; + } - try { - s2 = s1.split("\\.")[0]; - s3 = s1.split("\\.")[1]; - } catch (Exception exception) { - kickReason = "login.password error, database is corrupted."; - bufferedreader.close(); - return; - } + @Override + public void playerLoggedIn(Player player, NetHandler netHandler, INetworkManager manager) + { + //throw new UnsupportedOperationException("Not supported yet."); + } - if (s2.toLowerCase().equals(s4.toLowerCase())) { - if (!s3.equals(s5)) { - kickReason = "Неправильный пароль!"; - System.out.println((new StringBuilder()).append(netHandler.clientUsername).append(" failed to login (pwd: ").append(s3).append(")").toString()); - bufferedreader.close(); - return; - } else { - bufferedreader.close(); - return; - } - } - } + @Override + public String connectionReceived(NetLoginHandler netHandler, INetworkManager manager) + { + String kickReason = ""; + String s = netHandler.clientUsername; - bufferedreader.close(); - - // Создаём новый аккаунт - PrintWriter printwriter = new PrintWriter(new FileWriter(uFile, true)); - printwriter.println(s); - printwriter.close(); - - kickReason = ""; - } + try + { + kickReason = checkLogin(s); + System.out.println("[SERVER MODS] Logging in user: " + s + " Result: " + kickReason); + } + catch (FileNotFoundException ex) + { + Logger.getLogger(LoginHookClass.class.getName()).log(Level.SEVERE, null, ex); + } + catch (IOException ex) + { + Logger.getLogger(LoginHookClass.class.getName()).log(Level.SEVERE, null, ex); + } - @Override - public void playerLoggedIn(Player player, NetHandler netHandler, INetworkManager manager) { - //throw new UnsupportedOperationException("Not supported yet."); - } + if (Strings.isNullOrEmpty(kickReason)) + netHandler.clientUsername = s.split("\\.")[0]; - @Override - public String connectionReceived(NetLoginHandler netHandler, INetworkManager manager) { - kickReason = ""; - - try { - checkLogin(netHandler); - } catch (FileNotFoundException ex) { - Logger.getLogger(LoginHookClass.class.getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { - Logger.getLogger(LoginHookClass.class.getName()).log(Level.SEVERE, null, ex); - } - - // РќРµ кикать - if (kickReason.isEmpty()) { - // Удалить пароль РёР· имени пользователя - netHandler.clientUsername = netHandler.clientUsername.split("\\.")[0]; - } - - return kickReason; - } + return kickReason; + } - @Override - public void connectionOpened(NetHandler netClientHandler, String server, int port, INetworkManager manager) { - //throw new UnsupportedOperationException("Not supported yet."); - } + @Override + public void connectionOpened(NetHandler netClientHandler, String server, int port, INetworkManager manager) + { + //throw new UnsupportedOperationException("Not supported yet."); + } - @Override - public void connectionOpened(NetHandler netClientHandler, MinecraftServer server, INetworkManager manager) { - //throw new UnsupportedOperationException("Not supported yet."); - } + @Override + public void connectionOpened(NetHandler netClientHandler, MinecraftServer server, INetworkManager manager) + { + //throw new UnsupportedOperationException("Not supported yet."); + } - @Override - public void connectionClosed(INetworkManager manager) { - //throw new UnsupportedOperationException("Not supported yet."); - } + @Override + public void connectionClosed(INetworkManager manager) + { + //throw new UnsupportedOperationException("Not supported yet."); + } - @Override - public void clientLoggedIn(NetHandler clientHandler, INetworkManager manager, Packet1Login login) { - throw new UnsupportedOperationException("Not supported yet."); - } + @Override + public void clientLoggedIn(NetHandler clientHandler, INetworkManager manager, Packet1Login login) + { + //throw new UnsupportedOperationException("Not supported yet."); + } } \ No newline at end of file diff --git a/src/cr0s/serverMods/ServerMods.java b/src/cr0s/serverMods/ServerMods.java index 248f5c63..0b043886 100644 --- a/src/cr0s/serverMods/ServerMods.java +++ b/src/cr0s/serverMods/ServerMods.java @@ -12,34 +12,36 @@ import cpw.mods.fml.common.network.NetworkMod; import net.minecraftforge.common.MinecraftForge; import cr0s.WarpDrive.SpaceEventHandler; -@Mod(modid="ServerMods", name="ServerMods", version="0.0.1") +@Mod(modid = "ServerMods", name = "ServerMods", version = "0.0.1") @NetworkMod(clientSideRequired = false, serverSideRequired = true, connectionHandler = LoginHookClass.class) /** * @author Cr0s */ -public class ServerMods { +public class ServerMods +{ + // The instance of your mod that Forge uses. + @Instance("ServerMods") + public static ServerMods instance; - // The instance of your mod that Forge uses. - @Instance("ServerMods") - public static ServerMods instance; - - @PreInit - public void preInit(FMLPreInitializationEvent event) { - // Stub Method - } - - @Init - public void load(FMLInitializationEvent event) { - // Включить авторизацию (включается автоматически) - //proxy.setupLoginHook(); - - // Снять урон от падения с джетпаком и крузис-тапками - MinecraftForge.EVENT_BUS.register(new AntiFallDamage()); - } - - @PostInit - public void postInit(FMLPostInitializationEvent event) { - // Stub Method - } + @PreInit + public void preInit(FMLPreInitializationEvent event) + { + // Stub Method + } + + @Init + public void load(FMLInitializationEvent event) + { + // Включить авторизацию (включается автоматически) + //proxy.setupLoginHook(); + // Снять урон от падения с джетпаком и крузис-тапками + MinecraftForge.EVENT_BUS.register(new AntiFallDamage()); + } + + @PostInit + public void postInit(FMLPostInitializationEvent event) + { + // Stub Method + } } \ No newline at end of file diff --git a/src/shipmod/BlockID.java b/src/shipmod/BlockID.java deleted file mode 100644 index ed270113..00000000 --- a/src/shipmod/BlockID.java +++ /dev/null @@ -1,195 +0,0 @@ -// $Id$ -/* - * WorldEdit - * Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -package shipmod; - -/** - * List of block IDs. - * - * @author sk89q - */ -public final class BlockID { - public static final int AIR = 0; - public static final int STONE = 1; - public static final int GRASS = 2; - public static final int DIRT = 3; - public static final int COBBLESTONE = 4; - public static final int WOOD = 5; - public static final int SAPLING = 6; - public static final int BEDROCK = 7; - public static final int WATER = 8; - public static final int STATIONARY_WATER = 9; - public static final int LAVA = 10; - public static final int STATIONARY_LAVA = 11; - public static final int SAND = 12; - public static final int GRAVEL = 13; - public static final int GOLD_ORE = 14; - public static final int IRON_ORE = 15; - public static final int COAL_ORE = 16; - public static final int LOG = 17; - public static final int LEAVES = 18; - public static final int SPONGE = 19; - public static final int GLASS = 20; - public static final int LAPIS_LAZULI_ORE = 21; - public static final int LAPIS_LAZULI_BLOCK = 22; - public static final int DISPENSER = 23; - public static final int SANDSTONE = 24; - public static final int NOTE_BLOCK = 25; - public static final int BED = 26; - public static final int POWERED_RAIL = 27; - public static final int DETECTOR_RAIL = 28; - public static final int PISTON_STICKY_BASE = 29; - public static final int WEB = 30; - public static final int LONG_GRASS = 31; - public static final int DEAD_BUSH = 32; - public static final int PISTON_BASE = 33; - public static final int PISTON_EXTENSION = 34; - public static final int CLOTH = 35; - public static final int PISTON_MOVING_PIECE = 36; - public static final int YELLOW_FLOWER = 37; - public static final int RED_FLOWER = 38; - public static final int BROWN_MUSHROOM = 39; - public static final int RED_MUSHROOM = 40; - public static final int GOLD_BLOCK = 41; - public static final int IRON_BLOCK = 42; - public static final int DOUBLE_STEP = 43; - public static final int STEP = 44; - public static final int BRICK = 45; - public static final int TNT = 46; - public static final int BOOKCASE = 47; - public static final int MOSSY_COBBLESTONE = 48; - public static final int OBSIDIAN = 49; - public static final int TORCH = 50; - public static final int FIRE = 51; - public static final int MOB_SPAWNER = 52; - public static final int WOODEN_STAIRS = 53; - public static final int OAK_WOOD_STAIRS = 53; - public static final int CHEST = 54; - public static final int REDSTONE_WIRE = 55; - public static final int DIAMOND_ORE = 56; - public static final int DIAMOND_BLOCK = 57; - public static final int WORKBENCH = 58; - public static final int CROPS = 59; - public static final int SOIL = 60; - public static final int FURNACE = 61; - public static final int BURNING_FURNACE = 62; - public static final int SIGN_POST = 63; - public static final int WOODEN_DOOR = 64; - public static final int LADDER = 65; - public static final int MINECART_TRACKS = 66; - public static final int COBBLESTONE_STAIRS = 67; - public static final int WALL_SIGN = 68; - public static final int LEVER = 69; - public static final int STONE_PRESSURE_PLATE = 70; - public static final int IRON_DOOR = 71; - public static final int WOODEN_PRESSURE_PLATE = 72; - public static final int REDSTONE_ORE = 73; - public static final int GLOWING_REDSTONE_ORE = 74; - public static final int REDSTONE_TORCH_OFF = 75; - public static final int REDSTONE_TORCH_ON = 76; - public static final int STONE_BUTTON = 77; - public static final int SNOW = 78; - public static final int ICE = 79; - public static final int SNOW_BLOCK = 80; - public static final int CACTUS = 81; - public static final int CLAY = 82; - public static final int REED = 83; - public static final int JUKEBOX = 84; - public static final int FENCE = 85; - public static final int PUMPKIN = 86; - public static final int NETHERSTONE = 87; - public static final int NETHERRACK = 87; - public static final int SLOW_SAND = 88; - public static final int LIGHTSTONE = 89; - public static final int PORTAL = 90; - public static final int JACKOLANTERN = 91; - public static final int CAKE_BLOCK = 92; - public static final int REDSTONE_REPEATER_OFF = 93; - public static final int REDSTONE_REPEATER_ON = 94; - public static final int LOCKED_CHEST = 95; - public static final int TRAP_DOOR = 96; - public static final int SILVERFISH_BLOCK = 97; - public static final int STONE_BRICK = 98; - public static final int BROWN_MUSHROOM_CAP = 99; - public static final int RED_MUSHROOM_CAP = 100; - public static final int IRON_BARS = 101; - public static final int GLASS_PANE = 102; - public static final int MELON_BLOCK = 103; - public static final int PUMPKIN_STEM = 104; - public static final int MELON_STEM = 105; - public static final int VINE = 106; - public static final int FENCE_GATE = 107; - public static final int BRICK_STAIRS = 108; - public static final int STONE_BRICK_STAIRS = 109; - public static final int MYCELIUM = 110; - public static final int LILY_PAD = 111; - public static final int NETHER_BRICK = 112; - public static final int NETHER_BRICK_FENCE = 113; - public static final int NETHER_BRICK_STAIRS = 114; - public static final int NETHER_WART = 115; - public static final int ENCHANTMENT_TABLE = 116; - public static final int BREWING_STAND = 117; - public static final int CAULDRON = 118; - public static final int END_PORTAL = 119; - public static final int END_PORTAL_FRAME = 120; - public static final int END_STONE = 121; - public static final int DRAGON_EGG = 122; - public static final int REDSTONE_LAMP_OFF = 123; - public static final int REDSTONE_LAMP_ON = 124; - public static final int DOUBLE_WOODEN_STEP = 125; - public static final int WOODEN_STEP = 126; - public static final int COCOA_PLANT = 127; - public static final int SANDSTONE_STAIRS = 128; - public static final int EMERALD_ORE = 129; - public static final int ENDER_CHEST = 130; - public static final int TRIPWIRE_HOOK = 131; - public static final int TRIPWIRE = 132; - public static final int EMERALD_BLOCK = 133; - public static final int SPRUCE_WOOD_STAIRS = 134; - public static final int BIRCH_WOOD_STAIRS = 135; - public static final int JUNGLE_WOOD_STAIRS = 136; - public static final int COMMAND_BLOCK = 137; - public static final int BEACON = 138; - public static final int COBBLESTONE_WALL = 139; - public static final int FLOWER_POT = 140; - public static final int CARROTS = 141; - public static final int POTATOES = 142; - public static final int WOODEN_BUTTON = 143; - public static final int HEAD = 144; - public static final int ANVIL = 145; - public static final int TRAPPED_CHEST = 146; - public static final int PRESSURE_PLATE_LIGHT = 147; - public static final int PRESSURE_PLATE_HEAVY = 148; - public static final int COMPARATOR_OFF = 149; - public static final int COMPARATOR_ON = 150; - public static final int DAYLIGHT_SENSOR = 151; - public static final int REDSTONE_BLOCK = 152; - public static final int QUARTZ_ORE = 153; - public static final int HOPPER = 154; - public static final int QUARTZ_BLOCK = 155; - public static final int QUARTZ_STAIRS = 156; - public static final int ACTIVATOR_RAIL = 157; - public static final int DROPPER = 158; - public static final int STAINED_CLAY = 159; - public static final int HAY_BLOCK = 170; - public static final int CARPET = 171; - public static final int HARDENED_CLAY = 172; - public static final int COAL_BLOCK = 173; - -} diff --git a/src/shipmod/BlockMetaRotation.java b/src/shipmod/BlockMetaRotation.java deleted file mode 100644 index 2c07eed3..00000000 --- a/src/shipmod/BlockMetaRotation.java +++ /dev/null @@ -1,41 +0,0 @@ -package shipmod; - -public class BlockMetaRotation -{ - public final int blockID; - public final int[] metaRotation; - private int bitMask; - - protected BlockMetaRotation(int blockid, int[] metarotation, int bitmask) - { - if (metarotation.length != 4) - { - throw new IllegalArgumentException("MetaRotation int array must have length 4"); - } - else - { - this.blockID = blockid; - this.metaRotation = metarotation; - this.bitMask = bitmask; - } - } - - public int getRotatedMeta(int currentmeta, int rotate) - { - for (int i = 0; i < this.metaRotation.length; ++i) - { - if (this.metaRotation[i] == (currentmeta & this.bitMask)) - { - int mr = currentmeta & ~this.bitMask | this.metaRotation[wrapRotationIndex(i + rotate)] & this.bitMask; - return mr; - } - } - - return currentmeta; - } - - public static int wrapRotationIndex(int i) - { - return i & 3; - } -} diff --git a/src/shipmod/ClientProxy.java b/src/shipmod/ClientProxy.java deleted file mode 100644 index 16249717..00000000 --- a/src/shipmod/ClientProxy.java +++ /dev/null @@ -1,37 +0,0 @@ -package shipmod; - -import cpw.mods.fml.client.registry.ClientRegistry; -import cpw.mods.fml.client.registry.KeyBindingRegistry; -import cpw.mods.fml.client.registry.RenderingRegistry; -import cpw.mods.fml.common.registry.LanguageRegistry; -import net.minecraft.client.settings.KeyBinding; -import shipmod.control.ShipKeyHandler; -import shipmod.entity.EntityShip; -import shipmod.render.RenderShip; - -public class ClientProxy extends CommonProxy -{ - private ShipKeyHandler shipKeyHandler; - - public void registerTickHandlers() - { - super.registerTickHandlers(); - this.shipKeyHandler = new ShipKeyHandler(new KeyBinding("key.shipmod.up", 45), new KeyBinding("key.shipmod.down", 44), new KeyBinding("key.shipmod.brake", 46), new KeyBinding("key.shipmod.align", 13)); - KeyBindingRegistry.registerKeyBinding(this.shipKeyHandler); - } - - public void registerLocalization() - { - LanguageRegistry lang = LanguageRegistry.instance(); - lang.addStringLocalization(ShipMod.blockMarkShip.getUnlocalizedName().concat(".name"), "en_US", "Shuttle Controller"); - lang.addStringLocalization(this.shipKeyHandler.kbUp.keyDescription, "en_US", "Ascent Ship"); - lang.addStringLocalization(this.shipKeyHandler.kbDown.keyDescription, "en_US", "Descent Ship"); - lang.addStringLocalization(this.shipKeyHandler.kbBrake.keyDescription, "en_US", "Brake Ship"); - lang.addStringLocalization(this.shipKeyHandler.kbAlign.keyDescription, "en_US", "Align Ship"); - } - - public void registerRenderers() - { - RenderingRegistry.registerEntityRenderingHandler(EntityShip.class, new RenderShip()); - } -} diff --git a/src/shipmod/CommonProxy.java b/src/shipmod/CommonProxy.java deleted file mode 100644 index 71f5c39d..00000000 --- a/src/shipmod/CommonProxy.java +++ /dev/null @@ -1,10 +0,0 @@ -package shipmod; - -public class CommonProxy -{ - public void registerTickHandlers() {} - - public void registerLocalization() {} - - public void registerRenderers() {} -} diff --git a/src/shipmod/ConnectionHandler.java b/src/shipmod/ConnectionHandler.java deleted file mode 100644 index c0424ad4..00000000 --- a/src/shipmod/ConnectionHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package shipmod; - -import cpw.mods.fml.common.network.IConnectionHandler; -import cpw.mods.fml.common.network.Player; -import net.minecraft.network.INetworkManager; -import net.minecraft.network.NetLoginHandler; -import net.minecraft.network.packet.NetHandler; -import net.minecraft.network.packet.Packet1Login; -import net.minecraft.server.MinecraftServer; - -public class ConnectionHandler implements IConnectionHandler -{ - public void playerLoggedIn(Player player, NetHandler netHandler, INetworkManager manager) {} - - public String connectionReceived(NetLoginHandler netHandler, INetworkManager manager) - { - return null; - } - - public void connectionOpened(NetHandler netClientHandler, String server, int port, INetworkManager manager) {} - - public void connectionOpened(NetHandler netClientHandler, MinecraftServer server, INetworkManager manager) {} - - public void connectionClosed(INetworkManager manager) {} - - public void clientLoggedIn(NetHandler clientHandler, INetworkManager manager, Packet1Login login) {} -} diff --git a/src/shipmod/ForgeHookContainer.java b/src/shipmod/ForgeHookContainer.java deleted file mode 100644 index 4cc9c9ac..00000000 --- a/src/shipmod/ForgeHookContainer.java +++ /dev/null @@ -1,31 +0,0 @@ -package shipmod; - -import com.google.common.io.ByteArrayDataOutput; -import com.google.common.io.ByteStreams; - -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.network.PacketDispatcher; -import net.minecraft.network.packet.Packet250CustomPayload; -import net.minecraftforge.event.ForgeSubscribe; -import net.minecraftforge.event.entity.EntityJoinWorldEvent; -import shipmod.entity.EntityShip; - -public class ForgeHookContainer -{ - @ForgeSubscribe - public void onEntitySpawn(EntityJoinWorldEvent event) - { - if (FMLCommonHandler.instance().getEffectiveSide().isClient() && event.entity instanceof EntityShip) - { - if (!((EntityShip)event.entity).getCapabilities().hasSigns()) - { - return; - } - - ByteArrayDataOutput out = ByteStreams.newDataOutput(4); - out.writeInt(event.entity.entityId); - Packet250CustomPayload packet = new Packet250CustomPayload("reqShipSigns", out.toByteArray()); - PacketDispatcher.sendPacketToServer(packet); - } - } -} diff --git a/src/shipmod/MetaRotations$1.java b/src/shipmod/MetaRotations$1.java deleted file mode 100644 index 0e0cde0c..00000000 --- a/src/shipmod/MetaRotations$1.java +++ /dev/null @@ -1,19 +0,0 @@ -package shipmod; - -import java.io.File; -import java.io.FilenameFilter; - -class MetaRotations$1 implements FilenameFilter -{ - final MetaRotations this$0; - - MetaRotations$1(MetaRotations var1) - { - this.this$0 = var1; - } - - public boolean accept(File f, String name) - { - return name.endsWith(".mrot"); - } -} diff --git a/src/shipmod/MetaRotations.java b/src/shipmod/MetaRotations.java deleted file mode 100644 index e7896d53..00000000 --- a/src/shipmod/MetaRotations.java +++ /dev/null @@ -1,723 +0,0 @@ -package shipmod; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import net.minecraft.block.Block; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.MathHelper; -import net.minecraft.world.IBlockAccess; -import net.minecraft.world.World; -import shipmod.MetaRotations$1; -import shipmod.BlockID; -import ic2.api.network.NetworkHelper; - -public class MetaRotations -{ - private File metaRotationsDirectory; - public Map<Integer, BlockMetaRotation> metaRotationMap = new HashMap(); - - public int getRotatedMeta(int block, int meta, int rotate) - { - if (rotate == 0) - { - return meta; - } - else - { - BlockMetaRotation rotation = (BlockMetaRotation)this.metaRotationMap.get(Integer.valueOf(block)); - return rotation == null ? meta : rotation.getRotatedMeta(meta, rotate); - } - } - - public int getRotatedMeta(Block block, int meta, int rotate) - { - return this.getRotatedMeta(block.blockID, meta, rotate); - } - - public void addMetaRotation(int blockid, int bitmask, int ... metarotation) - { - ShipMod.modLogger.finer("Adding meta rotations (id=" + blockid + ", name=" + Block.blocksList[blockid].getUnlocalizedName() + ", mask=" + bitmask + ", rot=" + Arrays.toString(metarotation) + ")"); - this.metaRotationMap.put(Integer.valueOf(blockid), new BlockMetaRotation(blockid, metarotation, bitmask)); - } - - public void addMetaRotation(Block block, int bitmask, int ... metarotation) - { - this.addMetaRotation(block.blockID, bitmask, metarotation); - } - - public void parseMetaRotations(BufferedReader reader) throws IOException - { - int lineno = 0; - String line; - - while ((line = reader.readLine()) != null) - { - ++lineno; - - if (!line.startsWith("#") && line.length() != 0) - { - int mask = -1; - int[] rot = new int[4]; - String[] as = line.split(";"); - - if (as.length < 3) - { - ShipMod.modLogger.warning("Curruption in metarotation file at line " + lineno + "(Not enough parameters)"); - } - else - { - String[] block = as[0].split(","); - int[] ids = new int[block.length]; - - for (int arr$ = 0; arr$ < block.length; ++arr$) - { - try - { - ids[arr$] = Integer.parseInt(block[arr$].trim()); - } - catch (NumberFormatException var17) - { - String i$ = block[arr$].trim(); - Block[] blockid = Block.blocksList; - int len$1 = blockid.length; - - for (int i$1 = 0; i$1 < len$1; ++i$1) - { - Block b = blockid[i$1]; - - if (b != null && b.getUnlocalizedName().toLowerCase().equals("tile.".concat(i$.toLowerCase()))) - { - ids[arr$] = b.blockID; - } - } - } - } - - int len$; - - try - { - mask = Integer.decode(as[1].trim()).intValue(); - String[] var19 = as[2].split(","); - - for (len$ = 0; len$ < rot.length; ++len$) - { - rot[len$] = Integer.parseInt(var19[len$].trim()); - } - } - catch (NumberFormatException var16) - { - ShipMod.modLogger.warning("Curruption in metarotation file at line " + lineno + " (" + var16.getLocalizedMessage() + ")"); - } - - int[] var18 = ids; - len$ = ids.length; - - for (int var20 = 0; var20 < len$; ++var20) - { - int var21 = var18[var20]; - this.addMetaRotation(var21, mask, rot); - } - } - } - } - } - - public void setConfigDirectory(File configdirectory) - { - this.metaRotationsDirectory = new File(configdirectory, "ShipMod"); - - if (!this.metaRotationsDirectory.isDirectory()) - { - this.metaRotationsDirectory.mkdirs(); - } - } - - public void readMetaRotationFiles() - { - if (this.metaRotationsDirectory == null) - { - throw new NullPointerException("Config folder has not been initialized"); - } - else - { - this.metaRotationMap.clear(); - File defaultfile = new File(this.metaRotationsDirectory, "default.mrot"); - ShipMod.modLogger.finer("Creating default.mrot"); - BufferedWriter writer = null; - - try - { - defaultfile.createNewFile(); - writer = new BufferedWriter(new FileWriter(defaultfile)); - writer.write("#----------------#\n"); - writer.write("# VANILLA BLOCKS #\n"); - writer.write("#----------------#\n"); - writer.write("# Default vanilla block meta rotations\n"); - writer.write("# This file will be overwritten every start, changes will not be implemented!\n"); - writer.write("# blocknames/blockIDs; bitmask; 4 metadata values in the clockwise rotation order\n"); - writer.write("\n"); - writer.write("# Pumpkin & Lantern\n"); - writer.write("86, 87; 0x3; 0, 1, 2, 3;\n"); - writer.write("\n"); - writer.write("# Stairs\n"); - writer.write("53, 67, 108, 109, 114, 128, 134, 135, 136, 156; 0x3; 2, 1, 3, 0;\n"); - writer.write("\n"); - writer.write("# Torches, levers and buttons\n"); - writer.write("50, 69, 75, 76, 77, 143; 0x7; 4, 1, 3, 2;\n"); - writer.write("\n"); - writer.write("# Sign\n"); - writer.write("68; 0x7; 3, 4, 2, 5;\n"); - writer.write("\n"); - writer.write("# Log\n"); - writer.write("17; 0xC; 4, 8, 4, 8;\n"); - writer.write("\n"); - writer.write("# Quarts pillar\n"); - writer.write("155; 0x7; 3, 4, 3, 4;\n"); - writer.write("\n"); - writer.write("# Ladder\n"); - writer.write("65; 0x7; 3, 4, 2, 5;\n"); - writer.write("\n# Fence gate\n"); - writer.write("107; 0x3; 0, 1, 2, 3;\n"); - writer.write("\n# Furnace, dispenser, chest\n"); - writer.write("61, 62, 23, 54; 0x7; 2, 5, 3, 4;\n"); - writer.write("\n# Redstone repeater\n"); - writer.write("93, 94; 0x3; 0, 1, 2, 3;\n"); - writer.write("\n# Doors\n"); - writer.write("64, 71; 0x3; 0, 1, 2, 3;\n"); - writer.write("\n# Bed\n"); - writer.write("26; 0x3; 0, 1, 2, 3;\n"); - writer.write("\n# AS stuff\n"); - writer.write("3769, 3779, 3772; 0x3; 2, 1, 3, 0;\n"); - } - catch (IOException var33) - { - var33.printStackTrace(); - } - finally - { - if (writer != null) - { - try - { - writer.close(); - } - catch (IOException var30) - { - var30.printStackTrace(); - } - } - } - - File archshipsmodfile = new File(this.metaRotationsDirectory, "ShipMod.mrot"); - ShipMod.modLogger.finer("Creating ShipMod.mrot"); - writer = null; - - try - { - archshipsmodfile.createNewFile(); - writer = new BufferedWriter(new FileWriter(archshipsmodfile)); - writer.write("# Block meta rotations\n"); - writer.write("\n"); - writer.write("markShip; 0x3; 0, 1, 2, 3;\n"); - } - catch (IOException var32) - { - var32.printStackTrace(); - } - finally - { - if (writer != null) - { - try - { - writer.close(); - } - catch (IOException var31) - { - var31.printStackTrace(); - } - } - } - - File[] files = this.metaRotationsDirectory.listFiles(new MetaRotations$1(this)); - File[] arr$ = files; - int len$ = files.length; - - for (int i$ = 0; i$ < len$; ++i$) - { - File f = arr$[i$]; - - try - { - this.readMetaRotationFile(f); - } - catch (IOException var34) - { - var34.printStackTrace(); - } - } - } - } - - public void readMetaRotationFile(File file) throws IOException - { - ShipMod.modLogger.info("Reading metarotation file " + file.getAbsolutePath()); - BufferedReader reader = new BufferedReader(new FileReader(file)); - this.parseMetaRotations(reader); - reader.close(); - } - - public static int rotate90(int type, int data) { - switch (type) { - case BlockID.MINECART_TRACKS: - switch (data) { - case 6: return 7; - case 7: return 8; - case 8: return 9; - case 9: return 6; - } - /* FALL-THROUGH */ - - case BlockID.POWERED_RAIL: - case BlockID.DETECTOR_RAIL: - case BlockID.ACTIVATOR_RAIL: - switch (data & 0x7) { - case 0: return 1 | (data & ~0x7); - case 1: return 0 | (data & ~0x7); - case 2: return 5 | (data & ~0x7); - case 3: return 4 | (data & ~0x7); - case 4: return 2 | (data & ~0x7); - case 5: return 3 | (data & ~0x7); - } - break; - - case BlockID.WOODEN_STAIRS: - case BlockID.COBBLESTONE_STAIRS: - case BlockID.BRICK_STAIRS: - case BlockID.STONE_BRICK_STAIRS: - case BlockID.NETHER_BRICK_STAIRS: - case BlockID.SANDSTONE_STAIRS: - case BlockID.SPRUCE_WOOD_STAIRS: - case BlockID.BIRCH_WOOD_STAIRS: - case BlockID.JUNGLE_WOOD_STAIRS: - case BlockID.QUARTZ_STAIRS: - switch (data) { - case 0: return 2; - case 1: return 3; - case 2: return 1; - case 3: return 0; - case 4: return 6; - case 5: return 7; - case 6: return 5; - case 7: return 4; - } - break; - - case BlockID.COCOA_PLANT: - case BlockID.TRIPWIRE_HOOK: - int extra = data & ~0x3; - int withoutFlags = data & 0x3; - switch (withoutFlags) { - case 0: return 1 | extra; - case 1: return 2 | extra; - case 2: return 3 | extra; - case 3: return 0 | extra; - } - break; - - case BlockID.SIGN_POST: - return (data + 4) % 16; - - case BlockID.LADDER: - case BlockID.WALL_SIGN: - case BlockID.FURNACE: - case BlockID.BURNING_FURNACE: - case BlockID.ENDER_CHEST: - case BlockID.TRAPPED_CHEST: - case BlockID.HOPPER: - switch (data) { - case 2: return 5; - case 3: return 4; - case 4: return 2; - case 5: return 3; - } - break; - - case BlockID.DROPPER: - int dispPower = data & 0x8; - switch (data & ~0x8) { - case 2: return 5 | dispPower; - case 3: return 4 | dispPower; - case 4: return 2 | dispPower; - case 5: return 3 | dispPower; - } - break; - - case BlockID.LOG: - if (data >= 4 && data <= 11) data ^= 0xc; - break; - - case BlockID.COMPARATOR_OFF: - case BlockID.COMPARATOR_ON: - int dir = data & 0x03; - int delay = data - dir; - switch (dir) { - case 0: return 1 | delay; - case 1: return 2 | delay; - case 2: return 3 | delay; - case 3: return 0 | delay; - } - break; - - case BlockID.TRAP_DOOR: - int withoutOrientation = data & ~0x3; - int orientation = data & 0x3; - switch (orientation) { - case 0: return 3 | withoutOrientation; - case 1: return 2 | withoutOrientation; - case 2: return 0 | withoutOrientation; - case 3: return 1 | withoutOrientation; - } - break; - - case BlockID.PISTON_BASE: - case BlockID.PISTON_STICKY_BASE: - case BlockID.PISTON_EXTENSION: - System.out.println("Flipping piston..."); - final int rest = data & ~0x7; - switch (data & 0x7) { - case 2: return 5 | rest; - case 3: return 4 | rest; - case 4: return 2 | rest; - case 5: return 3 | rest; - } - break; - - case BlockID.BROWN_MUSHROOM_CAP: - case BlockID.RED_MUSHROOM_CAP: - if (data >= 10) return data; - return (data * 3) % 10; - - case BlockID.VINE: - return ((data << 1) | (data >> 3)) & 0xf; - - case BlockID.FENCE_GATE: - return ((data + 1) & 0x3) | (data & ~0x3); - - case BlockID.ANVIL: - return data ^ 0x1; - - case BlockID.HAY_BLOCK: - if (data == 4) return 8; - else if (data == 8) return 4; - else return 0; // sanitize extraneous data values since hay blocks are weird - - } - - return data; - } - - public static boolean examForIC2Machine(TileEntity te) { - if (te == null) { - return false; - } - - //System.out.println("Testing for IC2 machine " + te.getClass().getSimpleName()); - Class c = te.getClass().getSuperclass(); - //System.out.println("Superclass name: " + c.getName()); - return (c == null) ? false : (c.getName().contains("ic2.core.block.generator.tileentity") || c.getName().contains("ic2.core.block.wiring.TileEntity") || c.getName().contains("ic2.core.block.machine.tileentity")); - } - - public static short rotateIC2MachineFacing90Reverse(short facing) { - switch(facing) // 3 5 2 4 - { - case 3: - facing = 5; - break; - - case 5: - facing = 2; - break; - - case 2: - facing = 4; - break; - - case 4: - facing = 3; - break; - } - return facing; - } - - public static boolean examForAEMachine(TileEntity te) { - if (te == null) { - return false; - } - - //System.out.println("Testing for AE machine " + te.getClass().getSimpleName()); - Class c = te.getClass().getSuperclass(); - //System.out.println("Superclass name: " + c.getName()); - return (c == null) ? false : (c.getName().contains("appeng.me.basetiles") || c.getName().contains("appeng.me.tile") || c.getName().contains("appeng.common.base.AppEngTile")); - } - - public static int rotateAEMachineFacing90Reverse(int facing) { - switch(facing) // 0 4 2 1 - { - case 0: - facing = 4; - break; - - case 4: - facing = 2; - break; - - case 2: - facing = 1; - break; - - case 1: - facing = 0; - break; - } - - return facing; - } - - public static int rotateAECableFacing90Reverse(int facing) { - switch(facing) // 3 5 2 4 - { - case 3: - facing = 5; - break; - - case 5: - facing = 2; - break; - - case 2: - facing = 4; - break; - - case 4: - facing = 3; - break; - } - - return facing; - } - - public static int getCCSubtypeFromMetadata(int metadata) { - return metadata >= 2 && metadata <= 5? 0 : (metadata >= 2 && (metadata < 6 || metadata > 9) ? (metadata == 10 ? 2 :(metadata == 11 ? 3 : 4)) : 1); - } - - public static int getCCDirectionFromMetadata(int metadata) { - return metadata >= 2 && metadata <= 5 ? metadata : (metadata <= 9 ? (metadata < 2 ? metadata : metadata - 4) : 2); - } - - public static int rotateCCBlock90Reverse(int dir) { - switch(dir) - { - case 4: - return 3; - case 3: - return 5; - case 5: - return 2; - case 2: - return 4; - } - - return dir; - } - - public static int rotateComputer90Reverse(int meta) { - int typeMeta = meta & 0x8; - - switch(meta - typeMeta) - { - case 4: - return typeMeta + 3; - case 3: - return typeMeta + 5; - case 5: - return typeMeta + 2; - case 2: - return typeMeta + 4; - } - - return meta; - } - - - /** - * Rotate a block's data value -90 degrees (north<-east<-south<-west<-north); - * - * @param type - * @param data - * @return - */ - public static int rotate90Reverse(int type, int data) { - switch (type) { - case BlockID.MINECART_TRACKS: - switch (data) { - case 7: return 6; - case 8: return 7; - case 9: return 8; - case 6: return 9; - } - /* FALL-THROUGH */ - - case BlockID.POWERED_RAIL: - case BlockID.DETECTOR_RAIL: - case BlockID.ACTIVATOR_RAIL: - int power = data & ~0x7; - switch (data & 0x7) { - case 1: return 0 | power; - case 0: return 1 | power; - case 5: return 2 | power; - case 4: return 3 | power; - case 2: return 4 | power; - case 3: return 5 | power; - } - break; - - case BlockID.WOODEN_STAIRS: - case BlockID.COBBLESTONE_STAIRS: - case BlockID.BRICK_STAIRS: - case BlockID.STONE_BRICK_STAIRS: - case BlockID.NETHER_BRICK_STAIRS: - case BlockID.SANDSTONE_STAIRS: - case BlockID.SPRUCE_WOOD_STAIRS: - case BlockID.BIRCH_WOOD_STAIRS: - case BlockID.JUNGLE_WOOD_STAIRS: - case BlockID.QUARTZ_STAIRS: - switch (data) { - case 2: return 0; - case 3: return 1; - case 1: return 2; - case 0: return 3; - case 6: return 4; - case 7: return 5; - case 5: return 6; - case 4: return 7; - } - break; - - case BlockID.WOODEN_DOOR: - case BlockID.IRON_DOOR: - case BlockID.COCOA_PLANT: - case BlockID.TRIPWIRE_HOOK: - int extra = data & ~0x3; - int withoutFlags = data & 0x3; - switch (withoutFlags) { - case 1: return 0 | extra; - case 2: return 1 | extra; - case 3: return 2 | extra; - case 0: return 3 | extra; - } - break; - - case BlockID.SIGN_POST: - return (data + 12) % 16; - - case BlockID.LADDER: - case BlockID.WALL_SIGN: - case BlockID.FURNACE: - case BlockID.BURNING_FURNACE: - case BlockID.ENDER_CHEST: - case BlockID.TRAPPED_CHEST: - case BlockID.HOPPER: - switch (data) { - case 5: return 2; - case 4: return 3; - case 2: return 4; - case 3: return 5; - } - break; - - case BlockID.DROPPER: - int dispPower = data & 0x8; - switch (data & ~0x8) { - case 5: return 2 | dispPower; - case 4: return 3 | dispPower; - case 2: return 4 | dispPower; - case 3: return 5 | dispPower; - } - break; - - case BlockID.LOG: - if (data >= 4 && data <= 11) data ^= 0xc; - break; - - case BlockID.COMPARATOR_OFF: - case BlockID.COMPARATOR_ON: - int dir = data & 0x03; - int delay = data - dir; - switch (dir) { - case 1: return 0 | delay; - case 2: return 1 | delay; - case 3: return 2 | delay; - case 0: return 3 | delay; - } - break; - - case BlockID.TRAP_DOOR: - int withoutOrientation = data & ~0x3; - int orientation = data & 0x3; - switch (orientation) { - case 3: return 0 | withoutOrientation; - case 2: return 1 | withoutOrientation; - case 0: return 2 | withoutOrientation; - case 1: return 3 | withoutOrientation; - } - - case BlockID.PISTON_BASE: - case BlockID.PISTON_STICKY_BASE: - case BlockID.PISTON_EXTENSION: - System.out.println("Flipping piston..."); - final int rest = data & ~0x7; - switch (data & 0x7) { - case 5: return 2 | rest; - case 4: return 3 | rest; - case 2: return 4 | rest; - case 3: return 5 | rest; - } - break; - - case BlockID.BROWN_MUSHROOM_CAP: - case BlockID.RED_MUSHROOM_CAP: - if (data >= 10) return data; - return (data * 7) % 10; - - case BlockID.VINE: - return ((data >> 1) | (data << 3)) & 0xf; - - case BlockID.FENCE_GATE: - return ((data + 3) & 0x3) | (data & ~0x3); - - case BlockID.ANVIL: - return data ^ 0x1; - - case BlockID.HAY_BLOCK: - if (data == 4) return 8; - else if (data == 8) return 4; - else return 0; - - } - - return data; - } -} diff --git a/src/shipmod/PacketHandler.java b/src/shipmod/PacketHandler.java deleted file mode 100644 index a5b45199..00000000 --- a/src/shipmod/PacketHandler.java +++ /dev/null @@ -1,134 +0,0 @@ -package shipmod; - -import com.google.common.io.ByteArrayDataInput; -import com.google.common.io.ByteArrayDataOutput; -import com.google.common.io.ByteStreams; -import cpw.mods.fml.common.network.IPacketHandler; -import cpw.mods.fml.common.network.PacketDispatcher; -import cpw.mods.fml.common.network.Player; -import java.util.ArrayList; -import java.util.Iterator; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.network.INetworkManager; -import net.minecraft.network.packet.Packet250CustomPayload; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.tileentity.TileEntitySign; -import shipmod.entity.EntityShip; - -public class PacketHandler implements IPacketHandler -{ - public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) - { - ShipMod.modLogger.finest("Received packet " + packet.channel + " with player " + player.toString()); - EntityPlayer entityplayer = (EntityPlayer)player; - ByteArrayDataInput in; - int id; - Entity entity; - - if (packet.channel.equals("shipControl")) - { - in = ByteStreams.newDataInput(packet.data); - id = in.readInt(); - entity = entityplayer.worldObj.getEntityByID(id); - - if (entity instanceof EntityShip) - { - byte signs = in.readByte(); - EntityShip i = (EntityShip)entity; - i.getController().updateControl(i, entityplayer, signs); - } - } - else if (packet.channel.equals("shipInteract")) - { - in = ByteStreams.newDataInput(packet.data); - id = in.readInt(); - entity = entityplayer.worldObj.getEntityByID(id); - - if (entity instanceof EntityShip) - { - entity.func_130002_c(entityplayer); - } - } - else if (packet.channel.equals("reqShipSigns")) - { - in = ByteStreams.newDataInput(packet.data); - id = in.readInt(); - entity = entityplayer.worldObj.getEntityByID(id); - - if (entity instanceof EntityShip) - { - if (!((EntityShip)entity).getCapabilities().hasSigns()) - { - return; - } - - ArrayList var14 = new ArrayList(); - Iterator var15 = ((EntityShip)entity).getShipChunk().chunkTileEntityMap.values().iterator(); - - while (var15.hasNext()) - { - TileEntity s = (TileEntity)var15.next(); - - if (s instanceof TileEntitySign) - { - var14.add((TileEntitySign)s); - } - } - - if (var14.size() > 0) - { - ByteArrayDataOutput var17 = ByteStreams.newDataOutput(6 + var14.size() * 70); - var17.writeInt(id); - var17.writeShort(var14.size()); - Iterator var20 = var14.iterator(); - - while (var20.hasNext()) - { - TileEntitySign te = (TileEntitySign)var20.next(); - var17.writeShort(te.xCoord & 15 | (te.yCoord & 15) << 4 | (te.zCoord & 15) << 8); - var17.writeUTF(te.signText[0]); - var17.writeUTF(te.signText[1]); - var17.writeUTF(te.signText[2]); - var17.writeUTF(te.signText[3]); - } - - try - { - Packet250CustomPayload var21 = new Packet250CustomPayload("shipSigns", var17.toByteArray()); - PacketDispatcher.sendPacketToPlayer(var21, player); - } - catch (IllegalArgumentException var12) - { - ShipMod.modLogger.warning("Ship has too many signs to send"); - } - } - } - } - else if (packet.channel.equals("shipSigns")) - { - in = ByteStreams.newDataInput(packet.data); - id = in.readInt(); - entity = entityplayer.worldObj.getEntityByID(id); - - if (entity instanceof EntityShip) - { - short var13 = in.readShort(); - - for (int var16 = 0; var16 < var13; ++var16) - { - short var18 = in.readShort(); - TileEntity var19 = ((EntityShip)entity).getShipChunk().getBlockTileEntity(var18 & 15, var18 >>> 4 & 15, var18 >>> 8 & 15); - - if (var19 instanceof TileEntitySign) - { - ((TileEntitySign)var19).signText[0] = in.readUTF(); - ((TileEntitySign)var19).signText[1] = in.readUTF(); - ((TileEntitySign)var19).signText[2] = in.readUTF(); - ((TileEntitySign)var19).signText[3] = in.readUTF(); - } - } - } - } - } -} diff --git a/src/shipmod/ShipMod.java b/src/shipmod/ShipMod.java deleted file mode 100644 index 3446ff20..00000000 --- a/src/shipmod/ShipMod.java +++ /dev/null @@ -1,119 +0,0 @@ -package shipmod; - -import cpw.mods.fml.common.Mod; -import cpw.mods.fml.common.SidedProxy; -import cpw.mods.fml.common.Mod.EventHandler; -import cpw.mods.fml.common.Mod.Instance; -import cpw.mods.fml.common.event.FMLInitializationEvent; -import cpw.mods.fml.common.event.FMLPostInitializationEvent; -import cpw.mods.fml.common.event.FMLPreInitializationEvent; -import cpw.mods.fml.common.event.FMLServerStartingEvent; -import cpw.mods.fml.common.network.NetworkMod; -import cpw.mods.fml.common.registry.EntityRegistry; -import cpw.mods.fml.common.registry.GameRegistry; -import ic2.api.item.Items; - -import java.util.Collections; -import java.util.logging.Logger; - -import net.minecraft.block.Block; -import net.minecraft.block.material.MapColor; -import net.minecraft.block.material.Material; -import net.minecraft.command.CommandBase; -import net.minecraft.creativetab.CreativeTabs; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraftforge.common.Configuration; -import net.minecraftforge.common.MinecraftForge; -import shipmod.blockitem.BlockMarkShip; -import shipmod.blockitem.ItemCreateShip; -import shipmod.command.CommandHelp; -import shipmod.command.CommandAlignShip; -import shipmod.command.CommandDismountShip; -import shipmod.command.CommandKillShip; -import shipmod.command.CommandReloadMetaRotations; -import shipmod.command.CommandShipInfo; -import shipmod.command.CommandTpShip; -import shipmod.entity.EntityShip; - -@Mod( - modid = "ShipMod", - name = "ShipMod", - version = "1.6.2 v0.0.1" -) -@NetworkMod( - clientSideRequired = true, - serverSideRequired = true, - packetHandler = PacketHandler.class, - connectionHandler = ConnectionHandler.class, - channels = {"shipControl", "shipInteract", "reqShipSigns", "shipSigns"} -) -public class ShipMod -{ - @Instance("ShipMod") - public static ShipMod instance; - @SidedProxy( - clientSide = "shipmod.ClientProxy", - serverSide = "shipmod.CommonProxy" - ) - public static CommonProxy proxy; - public static Logger modLogger; - public static ItemCreateShip itemCreateVehicle; - public static BlockMarkShip blockMarkShip; - public static Material materialFloater; - public ShipModConfig modConfig; - public MetaRotations metaRotations = new MetaRotations(); - private ForgeHookContainer hookContainer = new ForgeHookContainer(); - - @EventHandler - public void preInitMod(FMLPreInitializationEvent event) - { - modLogger = event.getModLog(); - this.modConfig = new ShipModConfig(new Configuration(event.getSuggestedConfigurationFile())); - this.modConfig.loadAndSave(); - this.metaRotations.setConfigDirectory(event.getModConfigurationDirectory()); - } - - @EventHandler - public void initMod(FMLInitializationEvent event) - { - blockMarkShip = (BlockMarkShip)(new BlockMarkShip(this.modConfig.blockMarkShipID)).setUnlocalizedName("markShip").func_111022_d("markShip").setCreativeTab(CreativeTabs.tabTransport); - blockMarkShip.setStepSound(Block.soundMetalFootstep).setHardness(2.0F).setResistance(15.0F); - GameRegistry.registerBlock(blockMarkShip, "markShip"); - - GameRegistry.addRecipe(new ItemStack(blockMarkShip), "ici", "cec", "ici", - 'i', Items.getItem("iridiumPlate"), 'e', Item.enderPearl, 'c', Items.getItem("advancedCircuit")); - - EntityRegistry.registerModEntity(EntityShip.class, "shipmod", 1, this, 64, this.modConfig.shipEntitySyncRate, true); - - proxy.registerTickHandlers(); - proxy.registerLocalization(); - proxy.registerRenderers(); - MinecraftForge.EVENT_BUS.register(this.hookContainer); - } - - @EventHandler - public void postInitMod(FMLPostInitializationEvent event) - { - this.metaRotations.readMetaRotationFiles(); - } - - @EventHandler - public void serverStarting(FMLServerStartingEvent event) - { - this.registerASCommand(event, new CommandHelp()); - this.registerASCommand(event, new CommandReloadMetaRotations()); - this.registerASCommand(event, new CommandDismountShip()); - this.registerASCommand(event, new CommandShipInfo()); - this.registerASCommand(event, new CommandKillShip()); - this.registerASCommand(event, new CommandAlignShip()); - this.registerASCommand(event, new CommandTpShip()); - Collections.sort(CommandHelp.asCommands); - } - - private void registerASCommand(FMLServerStartingEvent event, CommandBase commandbase) - { - event.registerServerCommand(commandbase); - CommandHelp.asCommands.add(commandbase); - } -} diff --git a/src/shipmod/ShipModConfig.java b/src/shipmod/ShipModConfig.java deleted file mode 100644 index c7531b67..00000000 --- a/src/shipmod/ShipModConfig.java +++ /dev/null @@ -1,81 +0,0 @@ -package shipmod; - -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import net.minecraft.block.Block; -import net.minecraftforge.common.Configuration; - -public class ShipModConfig -{ - private static int[] defaultForbiddenBlocks = new int[] {Block.dirt.blockID, Block.grass.blockID, Block.sand.blockID, Block.gravel.blockID, Block.blockClay.blockID, Block.ice.blockID, Block.waterMoving.blockID, Block.waterStill.blockID, Block.lavaMoving.blockID, Block.lavaStill.blockID, Block.snow.blockID, Block.waterlily.blockID, Block.netherrack.blockID, Block.slowSand.blockID, Block.tallGrass.blockID}; - private static int[] defaultOverwritableBlocks = new int[] {Block.tallGrass.blockID, Block.waterlily.blockID}; - public static final int CONTROL_TYPE_VANILLA = 0; - public static final int CONTROL_TYPE_ARCHIMEDES = 1; - private Configuration config; - private Map<String, Object> materialStringMap; - public boolean enableAirShips = true; - public int shipEntitySyncRate; - public int maxShipChunkBlocks; - public float flyBalloonRatio = 0f; - public boolean connectDiagonalBlocks1; - public Set<Integer> forbiddenBlocks; - public Set<Integer> overwritableBlocks; - public int shipControlType; - public boolean remountOnDecompilationFail; - public float turnSpeed; - public float speedLimit; - public boolean enableRightClickDismount; - public int itemCreateVehicleID; - public int blockMarkShipID; - public int blockFloaterID; - public int blockBalloonID; - public int blockGaugeID; - - public ShipModConfig(Configuration configuration) - { - this.config = configuration; - this.forbiddenBlocks = new HashSet(); - this.overwritableBlocks = new HashSet(); - } - - public void loadAndSave() - { - this.config.load(); - this.shipEntitySyncRate = this.config.get("settings", "sync_rate", 20, "The amount of ticks between a server-client synchronization. Higher numbers reduce network traffic. Lower numbers increase multiplayer experience. 20 ticks = 1 second").getInt(); - this.shipControlType = this.config.get("control", "control_type", 1, "Set to 0 to use vanilla boat controls, set to 1 to use the new controls.").getInt(); - this.remountOnDecompilationFail = this.config.get("control", "remount_on_decomp_fail", false, "Set to \'true\' to automatically remount a ship if decompilation failed.").getBoolean(false); - this.turnSpeed = (float)this.config.get("control", "turn_speed", 1.0D, "A multiplier of the ship\'s turn speed.").getDouble(1.0D); - this.speedLimit = (float)this.config.get("control", "speed_limit", 30.0D, "The maximum velocity a ship can have, in meter per second. This does not affect acceleration.").getDouble(30.0D); - this.speedLimit /= 20.0F; - this.enableRightClickDismount = this.config.get("control", "enable_right_click_dismount", false, "Enable if right clicking on the ship should also dismount you.").getBoolean(false); - this.maxShipChunkBlocks = this.config.get("mobile_chunk", "max_chunk_blocks", 2048, "The maximum amount of blocks that a mobile ship chunk may contain, limited to a maximum of 3200 blocks").getInt(); - this.maxShipChunkBlocks = Math.min(this.maxShipChunkBlocks, 3400); - this.connectDiagonalBlocks1 = this.config.get("mobile_chunk", "connect_diagonal_blocks_1", false, "Blocks connected diagonally on one axis will also be added to the ship when this value is set to \'true\'.").getBoolean(false); - int[] forbiddenblocks = this.config.get("mobile_chunk", "forbidden_blocks", defaultForbiddenBlocks, "A list of blocks that will not be added to a ship.").getIntList(); - int[] overwritableblocks = this.config.get("mobile_chunk", "overwritable_blocks", defaultOverwritableBlocks, "A list of blocks that may be overwritten when decompiling a ship.").getIntList(); - int[] arr$ = forbiddenblocks; - int len$ = forbiddenblocks.length; - int i$; - int i; - - for (i$ = 0; i$ < len$; ++i$) - { - i = arr$[i$]; - this.forbiddenBlocks.add(Integer.valueOf(i)); - } - - arr$ = overwritableblocks; - len$ = overwritableblocks.length; - - for (i$ = 0; i$ < len$; ++i$) - { - i = arr$[i$]; - this.overwritableBlocks.add(Integer.valueOf(i)); - } - - this.blockMarkShipID = this.config.getBlock("mark_ship", 3611).getInt(); - this.blockGaugeID = this.config.getBlock("gauge", 3614).getInt(); - this.config.save(); - } -} diff --git a/src/shipmod/blockitem/BlockMarkShip.java b/src/shipmod/blockitem/BlockMarkShip.java deleted file mode 100644 index 86f439a9..00000000 --- a/src/shipmod/blockitem/BlockMarkShip.java +++ /dev/null @@ -1,184 +0,0 @@ -package shipmod.blockitem; - -import java.util.List; - -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; -import net.minecraft.block.BlockDirectional; -import net.minecraft.block.material.Material; -import net.minecraft.client.renderer.texture.IconRegister; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.tileentity.TileEntityChest; -import net.minecraft.util.AxisAlignedBB; -import net.minecraft.util.Icon; -import net.minecraft.world.World; -import shipmod.ShipMod; -import shipmod.chunk.ChunkBuilder; -import shipmod.entity.EntityShip; - -public class BlockMarkShip extends BlockDirectional -{ - private Icon frontIcon; - final int FUEL_CAN_ID = 30232; - final int EMPTY_FUEL_CAN_ID = 30231; - - final int SECONDS_OF_FLYING_PER_CAN = 300; // without ship blocks - final int TICKS_OF_TIME_PER_BLOCK_DECREASE = 10; // half a second per block - - public BlockMarkShip(int id) - { - super(id, Material.iron); - } - - @SideOnly(Side.CLIENT) - - /** - * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata - */ - public Icon getIcon(int side, int meta) - { - meta &= 3; - return side == 2 ? (meta == 0 ? this.frontIcon : this.blockIcon) : (side == 3 ? (meta == 2 ? this.frontIcon : this.blockIcon) : (side == 4 ? (meta == 3 ? this.frontIcon : this.blockIcon) : (side == 5 ? (meta == 1 ? this.frontIcon : this.blockIcon) : this.blockIcon))); - } - - /** - * When this method is called, your block should register all the icons it needs with the given IconRegister. This - * is the only chance you get to register icons. - */ - public void registerIcons(IconRegister reg) - { - super.registerIcons(reg); - this.frontIcon = reg.registerIcon("shipmod:shuttleControllerFront"); - this.blockIcon = reg.registerIcon("shipmod:shuttleControllerSide"); - } - - /** - * Called when the block is placed in the world. - */ - public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase entityliving, ItemStack itemstack) - { - int dir = Math.round(entityliving.rotationYaw / 90.0F) & 3; - world.setBlockMetadataWithNotify(x, y, z, dir, 3); - } - - private TileEntityChest searchChest(World worldObj, int xCoord, int yCoord, int zCoord) { - TileEntity result = null; - result = worldObj.getBlockTileEntity(xCoord + 1, yCoord, zCoord); - if (result != null && result instanceof TileEntityChest) { - return (TileEntityChest) result; - } - - result = worldObj.getBlockTileEntity(xCoord - 1, yCoord, zCoord); - if (result != null && result instanceof TileEntityChest) { - return (TileEntityChest) result; - } - - result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord + 1); - if (result != null && result instanceof TileEntityChest) { - return (TileEntityChest) result; - } - - result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord - 1); - if (result != null && result instanceof TileEntityChest) { - return (TileEntityChest) result; - } - - result = worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord); - if (result != null && result instanceof TileEntityChest) { - return (TileEntityChest) result; - } - - return null; - } - - private int consumeFuel(World worldObj, int xCoord, int yCoord, int zCoord) { - int res = 0; - - TileEntityChest chest = searchChest(worldObj, xCoord, yCoord, zCoord); - if (chest != null) { - for (int i = 0; i < chest.getSizeInventory(); i++) { - ItemStack stack = chest.getStackInSlot(i); - - if (stack != null && stack.itemID == FUEL_CAN_ID) { - res += (20 * SECONDS_OF_FLYING_PER_CAN) * stack.stackSize; - chest.setInventorySlotContents(i, new ItemStack(EMPTY_FUEL_CAN_ID, 1, 0)); - } - } - } - - return res; - } - - /** - * Called upon block activation (right click on the block.) - */ - public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityplayer, int par6, float par7, float par8, float par9) - { - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) - { - return true; - } - else - { - world.isRemote = true; // lock world from changes - ChunkBuilder builder = new ChunkBuilder(world, x, y, z); - builder.doFilling(); - - if (builder.getResult() == 0) - { - if (builder.getBlockCount() < 10) { - ((EntityPlayerMP)entityplayer).addChatMessage("[ShipMod] Ship is too small!"); - world.isRemote = false; - return false; - } - - int fuelLevel = consumeFuel(world, x, y, z); - fuelLevel -= (builder.getBlockCount() * TICKS_OF_TIME_PER_BLOCK_DECREASE); - - // By half of second per ship block - if (fuelLevel <= 0) { - ((EntityPlayerMP)entityplayer).addChatMessage("[ShipMod] Not enough fuel!"); - world.isRemote = false; - return false; - } else { - int flysec = fuelLevel / 20; - ((EntityPlayerMP)entityplayer).addChatMessage("[ShipMod] Loaded fuel for " + ((flysec <= 120) ? flysec + " seconds" : (flysec / 60) + " minutes") + " of flying"); - } - - EntityShip entity = builder.getEntity(world); - world.isRemote = false; - if (entity != null) - { - entity.health = builder.getBlockCount(); - entity.fuelLevel = fuelLevel; - world.spawnEntityInWorld(entity); - entityplayer.mountEntity(entity); - return true; - } - } - - if (builder.getResult() == 1) - { - ((EntityPlayerMP)entityplayer).addChatMessage("[ShipMod] Cannot create vehicle with more than " + ShipMod.instance.modConfig.maxShipChunkBlocks + " blocks"); - } - else if (builder.getResult() == 2) - { - ((EntityPlayerMP)entityplayer).addChatMessage("[ShipMod] Cannot create vehicle with no vehicle marker"); - } - else if (builder.getResult() == 3) - { - ((EntityPlayerMP)entityplayer).addChatMessage("[ShipMod] An error occured while compiling ship. Please report the appeared exception in the console."); - } else if (builder.getResult() == 4) { - ((EntityPlayerMP)entityplayer).addChatMessage("[ShipMod] ACTIVE WARP-CORE DETECTED. CANNOT CREATE VEHICLE."); - } - - world.isRemote = false; - return false; - } - } -} diff --git a/src/shipmod/blockitem/ItemCreateShip.java b/src/shipmod/blockitem/ItemCreateShip.java deleted file mode 100644 index f615c962..00000000 --- a/src/shipmod/blockitem/ItemCreateShip.java +++ /dev/null @@ -1,69 +0,0 @@ -package shipmod.blockitem; - -import cpw.mods.fml.common.FMLCommonHandler; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.world.World; -import shipmod.chunk.ChunkBuilder; -import shipmod.entity.EntityShip; - -public class ItemCreateShip extends Item -{ - public ItemCreateShip(int id) - { - super(id); - } - - /** - * Callback for item usage. If the item does something special on right clicking, he will have one of those. Return - * True if something happen and false if it don't. This is for ITEMS, not BLOCKS - */ - public boolean onItemUse(ItemStack itemstack, EntityPlayer entityplayer, World world, int x, int y, int z, int par7, float par8, float par9, float par10) - { - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) - { - return true; - } - else - { - ChunkBuilder filler = new ChunkBuilder(world, x, y, z); - filler.doFilling(); - - if (filler.getResult() == 0) - { - EntityShip entity = filler.getEntity(world); - world.spawnEntityInWorld(entity); - return true; - } - else - { - if (filler.getResult() == 1) - { - ((EntityPlayerMP)entityplayer).addChatMessage("Cannot create vehicle with more than 200 blocks"); - } - else if (filler.getResult() == 2) - { - ((EntityPlayerMP)entityplayer).addChatMessage("Cannot create vehicle with no vehicle marker"); - } - - return false; - } - } - } - - public boolean onLeftClickEntity(ItemStack stack, EntityPlayer player, Entity entity) - { - if (entity instanceof EntityShip) - { - ((EntityShip)entity).decompileToBlocks(true); - return true; - } - else - { - return false; - } - } -} diff --git a/src/shipmod/chunk/ChunkBuilder.java b/src/shipmod/chunk/ChunkBuilder.java deleted file mode 100644 index 447d30c0..00000000 --- a/src/shipmod/chunk/ChunkBuilder.java +++ /dev/null @@ -1,233 +0,0 @@ -package shipmod.chunk; - -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; - -import cr0s.WarpDrive.WarpDrive; -import net.minecraft.block.Block; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.world.ChunkPosition; -import net.minecraft.world.World; -import shipmod.ShipMod; -import shipmod.entity.EntityShip; - -public class ChunkBuilder -{ - public static final int RESULT_OK = 0; - public static final int RESULT_BLOCK_OVERFLOW = 1; - public static final int RESULT_MISSING_MARKER = 2; - public static final int RESULT_ERROR_OCCURED = 3; - private World worldObj; - private int startX; - private int startY; - private int startZ; - private Map<ChunkPosition, LocatedBlock> filledBlocks; - private LocatedBlock shipMarkingBlock; - private int result; - private final int maxBlocks; - public int xOffset; - public int yOffset; - public int zOffset; - - private boolean isActiveCoreOnBoard = false; - - public ChunkBuilder(World world, int x, int y, int z) - { - this.worldObj = world; - this.filledBlocks = new HashMap(256); - this.startX = x; - this.startY = y; - this.startZ = z; - this.maxBlocks = ShipMod.instance.modConfig.maxShipChunkBlocks; - this.result = -1; - } - - public int getBlockCount() - { - return this.filledBlocks.size(); - } - - public int getResult() - { - return this.result; - } - - public Collection<LocatedBlock> getFilledBlocks() - { - return this.filledBlocks.values(); - } - - public LocatedBlock getShipMarker() - { - return this.shipMarkingBlock; - } - - public void doFilling() - { - this.xOffset = this.startX; - this.yOffset = this.startY; - this.zOffset = this.startZ; - - try - { - this.fill(new HashSet(), this.startX, this.startY, this.startZ); - - if (this.shipMarkingBlock == null) - { - this.result = 2; - } - else - { - if (!isActiveCoreOnBoard) - this.result = 0; - else - this.result = 4; - } - } - catch (ShipSizeOverflowException var2) - { - this.result = 1; - } - catch (StackOverflowError var3) - { - System.err.println(var3.toString()); - this.result = 3; - } - catch (Exception var4) - { - var4.printStackTrace(); - this.result = 3; - } - } - - private void fill(HashSet<ChunkPosition> set, int x, int y, int z) throws ShipSizeOverflowException - { - if (this.getBlockCount() > this.maxBlocks) - { - throw new ShipSizeOverflowException(); - } - else - { - ChunkPosition pos = new ChunkPosition(x, y, z); - - if (!set.contains(pos) && !this.filledBlocks.containsKey(pos)) - { - set.add(pos); - int id = this.worldObj.getBlockId(x, y, z); - - if (id != 0 && this.canUseBlockForVehicle(Block.blocksList[id], x, y, z)) - { - this.xOffset = Math.min(this.xOffset, x); - this.yOffset = Math.min(this.yOffset, y); - this.zOffset = Math.min(this.zOffset, z); - - if (id == ShipMod.blockMarkShip.blockID && this.shipMarkingBlock == null) - { - this.shipMarkingBlock = new LocatedBlock(id, this.worldObj.getBlockMetadata(x, y, z), pos); - this.filledBlocks.put(pos, this.shipMarkingBlock); - } - else - { - if (id == WarpDrive.WARP_CORE_BLOCKID) { - isActiveCoreOnBoard = worldObj.getBlockMetadata(x, y, z) != 0; - } - this.filledBlocks.put(pos, new LocatedBlock(id, this.worldObj.getBlockMetadata(x, y, z), pos)); - } - - this.fill(set, x - 1, y, z); - this.fill(set, x, y - 1, z); - this.fill(set, x, y, z - 1); - this.fill(set, x + 1, y, z); - this.fill(set, x, y + 1, z); - this.fill(set, x, y, z + 1); - - if (ShipMod.instance.modConfig.connectDiagonalBlocks1) - { - this.fill(set, x - 1, y - 1, z); - this.fill(set, x + 1, y - 1, z); - this.fill(set, x + 1, y + 1, z); - this.fill(set, x - 1, y + 1, z); - this.fill(set, x - 1, y, z - 1); - this.fill(set, x + 1, y, z - 1); - this.fill(set, x + 1, y, z + 1); - this.fill(set, x - 1, y, z + 1); - this.fill(set, x, y - 1, z - 1); - this.fill(set, x, y + 1, z - 1); - this.fill(set, x, y + 1, z + 1); - this.fill(set, x, y - 1, z + 1); - } - } - } - } - } - - public boolean canUseBlockForVehicle(Block block, int x, int y, int z) - { - return block != null && !block.isAirBlock(this.worldObj, x, y, z) && !block.blockMaterial.isLiquid() && !ShipMod.instance.modConfig.forbiddenBlocks.contains(Integer.valueOf(block.blockID)); - } - - public EntityShip getEntity(World world) - { - if (this.result != 0) - { - return null; - } - else - { - EntityShip entity = new EntityShip(world); - Iterator i$ = this.getFilledBlocks().iterator(); - LocatedBlock block; - - while (i$.hasNext()) - { - block = (LocatedBlock)i$.next(); - int ix = block.coords.x - this.xOffset; - int iy = block.coords.y - this.yOffset; - int iz = block.coords.z - this.zOffset; - TileEntity tileentity = world.getBlockTileEntity(block.coords.x, block.coords.y, block.coords.z); - - // cloning tile entity - NBTTagCompound nbt = null; - - if (tileentity != null) - { - nbt = new NBTTagCompound(); - tileentity.writeToNBT(nbt); - world.removeBlockTileEntity(block.coords.x, block.coords.y, block.coords.z); - } - - if (entity.getShipChunk().setBlockIDWithMetadata(ix, iy, iz, block.blockID, block.blockMeta)) - { - world.setBlock(block.coords.x, block.coords.y, block.coords.z, 0, 1, 2); - - if (nbt != null) { - TileEntity newTE = TileEntity.createAndLoadEntity(nbt); - entity.getShipChunk().setBlockTileEntity(ix, iy, iz, newTE); - } - } - } - - i$ = this.getFilledBlocks().iterator(); - - while (i$.hasNext()) - { - block = (LocatedBlock)i$.next(); - world.setBlockToAir(block.coords.x, block.coords.y, block.coords.z); - } - - entity.setFrontDirection(this.shipMarkingBlock.blockMeta & 3); - entity.seatX = this.shipMarkingBlock.coords.x - this.xOffset; - entity.seatY = this.shipMarkingBlock.coords.y - this.yOffset; - entity.seatZ = this.shipMarkingBlock.coords.z - this.zOffset; - entity.getShipChunk().setCreationSpotBiomeGen(world.getBiomeGenForCoords(this.shipMarkingBlock.coords.x, this.shipMarkingBlock.coords.z)); - entity.getShipChunk().setChunkModified(); - entity.getShipChunk().onChunkLoad(); - entity.setLocationAndAngles((double)((float)this.xOffset + entity.getShipChunk().getCenterX()), (double)this.yOffset, (double)((float)this.zOffset + entity.getShipChunk().getCenterZ()), 0.0F, 0.0F); - return entity; - } - } -} diff --git a/src/shipmod/chunk/LocatedBlock.java b/src/shipmod/chunk/LocatedBlock.java deleted file mode 100644 index 7c6238f9..00000000 --- a/src/shipmod/chunk/LocatedBlock.java +++ /dev/null @@ -1,22 +0,0 @@ -package shipmod.chunk; - -import net.minecraft.world.ChunkPosition; - -public class LocatedBlock -{ - public final int blockID; - public final int blockMeta; - public final ChunkPosition coords; - - public LocatedBlock(int id, int meta, ChunkPosition coords) - { - this.blockID = id; - this.blockMeta = meta; - this.coords = coords; - } - - public String toString() - { - return "LocatedBlock [id=" + this.blockID + ", meta=" + this.blockMeta + ", coords=[" + this.coords.x + ", " + this.coords.y + ", " + this.coords.z + "]]"; - } -} diff --git a/src/shipmod/chunk/MobileChunk.java b/src/shipmod/chunk/MobileChunk.java deleted file mode 100644 index 832ab25a..00000000 --- a/src/shipmod/chunk/MobileChunk.java +++ /dev/null @@ -1,640 +0,0 @@ -package shipmod.chunk; - -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import net.minecraft.block.Block; -import net.minecraft.block.material.Material; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.Vec3Pool; -import net.minecraft.world.ChunkPosition; -import net.minecraft.world.EnumSkyBlock; -import net.minecraft.world.IBlockAccess; -import net.minecraft.world.World; -import net.minecraft.world.biome.BiomeGenBase; -import net.minecraft.world.chunk.storage.ExtendedBlockStorage; -import net.minecraftforge.common.ForgeDirection; -import shipmod.ShipMod; -import shipmod.entity.EntityShip; -import shipmod.entity.IShipTileEntity; -import shipmod.render.MobileChunkRenderer; - -public class MobileChunk implements IBlockAccess -{ - public static final int CHUNK_SIZE = 16; - public static final int CHUNK_SIZE_EXP = 4; - public static final int CHUNK_MEMORY_USING = 24576; - private World worldObj; - private EntityShip entityShip; - private Map<ChunkPosition, ExtendedBlockStorage> blockStorageMap; - public Map<ChunkPosition, TileEntity> chunkTileEntityMap; - private boolean boundsInit; - private int minX; - private int minY; - private int minZ; - private int maxX; - private int maxY; - private int maxZ; - private int blockCount; - public boolean isChunkLoaded; - public boolean isModified; - public boolean chunkUpdated; - private BiomeGenBase creationSpotBiome; - @SideOnly(Side.CLIENT) - public MobileChunkRenderer renderer; - - public MobileChunk(World world, EntityShip entityship) - { - this.worldObj = world; - this.entityShip = entityship; - this.blockStorageMap = new HashMap(1); - this.chunkTileEntityMap = new HashMap(2); - this.isChunkLoaded = false; - this.isModified = false; - this.chunkUpdated = false; - this.boundsInit = false; - this.minX = this.minY = this.minZ = this.maxX = this.maxY = this.maxZ = -1; - this.blockCount = 0; - - if (FMLCommonHandler.instance().getSide().isClient()) - { - this.renderer = new MobileChunkRenderer(this); - } - - this.creationSpotBiome = BiomeGenBase.ocean; - } - - public ExtendedBlockStorage getBlockStorage(int x, int y, int z) - { - ChunkPosition pos = new ChunkPosition(x >> 4, y >> 4, z >> 4); - return (ExtendedBlockStorage)this.blockStorageMap.get(pos); - } - - public ExtendedBlockStorage getBlockStorageOrCreate(int x, int y, int z) - { - ChunkPosition pos = new ChunkPosition(x >> 4, y >> 4, z >> 4); - ExtendedBlockStorage storage = (ExtendedBlockStorage)this.blockStorageMap.get(pos); - - if (storage != null) - { - return storage; - } - else - { - storage = new ExtendedBlockStorage(pos.y, false); - this.blockStorageMap.put(pos, storage); - return storage; - } - } - - public int getBlockCount() - { - return this.blockCount; - } - - public float getCenterX() - { - return (float)(this.minX + this.maxX) / 2.0F; - } - - public float getCenterY() - { - return (float)(this.minY + this.maxY) / 2.0F; - } - - public float getCenterZ() - { - return (float)(this.minZ + this.maxZ) / 2.0F; - } - - public int minX() - { - return this.minX; - } - - public int maxX() - { - return this.maxX; - } - - public int minY() - { - return this.minY; - } - - public int maxY() - { - return this.maxY; - } - - public int minZ() - { - return this.minZ; - } - - public int maxZ() - { - return this.maxZ; - } - - public void setCreationSpotBiomeGen(BiomeGenBase biomegenbase) - { - this.creationSpotBiome = biomegenbase; - } - - /** - * Returns the block ID at coords x,y,z - */ - public int getBlockId(int x, int y, int z) - { - ExtendedBlockStorage storage = this.getBlockStorage(x, y, z); - return storage == null ? 0 : storage.getExtBlockID(x & 15, y & 15, z & 15); - } - - /** - * Returns the block metadata at coords x,y,z - */ - public int getBlockMetadata(int x, int y, int z) - { - ExtendedBlockStorage storage = this.getBlockStorage(x, y, z); - return storage == null ? 0 : storage.getExtBlockMetadata(x & 15, y & 15, z & 15); - } - - public boolean setBlockIDWithMetadata(int x, int y, int z, int id, int meta) - { - ExtendedBlockStorage storage = this.getBlockStorageOrCreate(x, y, z); - int i = x & 15; - int j = y & 15; - int k = z & 15; - int currentid = storage.getExtBlockID(i, j, k); - int currentmeta = storage.getExtBlockMetadata(i, j, k); - - if (currentid == 0 && (currentid != id || currentmeta != meta)) - { - storage.setExtBlockID(i, j, k, id); - storage.setExtBlockMetadata(i, j, k, meta); - - if (this.boundsInit) - { - this.minX = Math.min(this.minX, x); - this.minY = Math.min(this.minY, y); - this.minZ = Math.min(this.minZ, z); - this.maxX = Math.max(this.maxX, x + 1); - this.maxY = Math.max(this.maxY, y + 1); - this.maxZ = Math.max(this.maxZ, z + 1); - } - else - { - this.boundsInit = true; - this.minX = x; - this.minY = y; - this.minZ = z; - this.maxX = x + 1; - this.maxY = y + 1; - this.maxZ = z + 1; - } - - ++this.blockCount; - this.entityShip.onChunkBlockAdded(id, meta); - this.setChunkModified(); - - if (Block.blocksList[id] != null && Block.blocksList[id].hasTileEntity(meta)) - { - TileEntity tileentity = this.getChunkBlockTileEntity(x, y, z); - - /*if (tileentity == null) - { - tileentity = Block.blocksList[id].createTileEntity(this.worldObj, meta); - this.setBlockTileEntity(x, y, z, tileentity); - }*/ - - if (tileentity != null) - { - tileentity.updateContainingBlockInfo(); - tileentity.blockType = Block.blocksList[id]; - tileentity.blockMetadata = meta; - } - } - - return true; - } - else - { - return false; - } - } - - public boolean setBlockMetadata(int x, int y, int z, int meta) - { - ExtendedBlockStorage storage = this.getBlockStorage(x, y, z); - - if (storage == null) - { - return false; - } - else - { - int currentmeta = storage.getExtBlockMetadata(x, y & 15, z); - - if (currentmeta == meta) - { - return false; - } - else - { - this.setChunkModified(); - storage.setExtBlockMetadata(x & 15, y & 15, z & 15, meta); - int id = storage.getExtBlockID(x & 15, y & 15, z & 15); - - if (id > 0 && Block.blocksList[id] != null && Block.blocksList[id].hasTileEntity(meta)) - { - TileEntity tileentity = this.getChunkBlockTileEntity(x, y, z); - - if (tileentity != null) - { - tileentity.updateContainingBlockInfo(); - tileentity.blockMetadata = meta; - } - } - - return true; - } - } - } - - public boolean setBlockAsFilledAir(int x, int y, int z) - { - ExtendedBlockStorage storage = this.getBlockStorage(x, y, z); - - if (storage == null) - { - return true; - } - else - { - int id = storage.getExtBlockID(x & 15, y & 15, z & 15); - - if (id != 0 && Block.blocksList[id] != null && !Block.blocksList[id].isAirBlock(this.worldObj, x, y, z)) - { - return false; - } - else - { - storage.setExtBlockID(x & 15, y & 15, z & 15, 0); - storage.setExtBlockMetadata(x & 15, y & 15, z & 15, 1); - return true; - } - } - } - - /** - * Returns the TileEntity associated with a given block in X,Y,Z coordinates, or null if no TileEntity exists - */ - public TileEntity getBlockTileEntity(int i, int j, int k) - { - return this.getChunkBlockTileEntity(i, j, k); - } - - private TileEntity getChunkBlockTileEntity(int x, int y, int z) - { - ChunkPosition chunkposition = new ChunkPosition(x, y, z); - TileEntity tileentity = (TileEntity)this.chunkTileEntityMap.get(chunkposition); - - if (tileentity != null && tileentity.isInvalid()) - { - this.chunkTileEntityMap.remove(chunkposition); - tileentity = null; - } - - /*if (tileentity == null) - { - int l = this.getBlockId(x, y, z); - int meta = this.getBlockMetadata(x, y, z); - - if (l <= 0 || !Block.blocksList[l].hasTileEntity(meta)) - { - return null; - } - - // GET OUT! - //tileentity = Block.blocksList[l].createTileEntity(this.worldObj, meta); - this.setBlockTileEntity(x, y, z, tileentity); - tileentity = (TileEntity)this.chunkTileEntityMap.get(chunkposition); - }*/ - - return tileentity; - } - - public void setBlockTileEntity(int x, int y, int z, TileEntity tileentity) - { - if (tileentity != null && !tileentity.isInvalid()) - { - this.setChunkBlockTileEntity(x, y, z, tileentity); - } - } - - private void setChunkBlockTileEntity(int x, int y, int z, TileEntity tileentity) - { - ChunkPosition chunkposition = new ChunkPosition(x, y, z); - tileentity.setWorldObj(this.worldObj); - tileentity.xCoord = x; - tileentity.yCoord = y; - tileentity.zCoord = z; - Block block = Block.blocksList[this.getBlockId(x, y, z)]; - - if (block != null && block.hasTileEntity(this.getBlockMetadata(x, y, z))) - { - if (this.chunkTileEntityMap.containsKey(chunkposition)) - { - ((TileEntity)this.chunkTileEntityMap.get(chunkposition)).invalidate(); - } - - tileentity.blockMetadata = this.getBlockMetadata(x, y, z); - tileentity.validate(); - this.chunkTileEntityMap.put(chunkposition, tileentity); - - if (tileentity instanceof IShipTileEntity) - { - ((IShipTileEntity)tileentity).setVehicle(this.entityShip); - } - - //if (this.isChunkLoaded) - //{ - // this.worldObj.addTileEntity(tileentity); - //} - } - } - - public void addTileEntity(TileEntity tileentity) - { - int i = tileentity.xCoord; - int j = tileentity.yCoord; - int k = tileentity.zCoord; - if (!worldObj.isAirBlock(tileentity.xCoord, tileentity.yCoord, tileentity.zCoord) && worldObj.getBlockTileEntity(tileentity.xCoord, tileentity.yCoord, tileentity.zCoord) != null) { - worldObj.removeBlockTileEntity(tileentity.xCoord, tileentity.yCoord, tileentity.zCoord); - tileentity.validate(); - } - this.setChunkBlockTileEntity(i, j, k, tileentity); - - //if (this.isChunkLoaded) - //{ - // this.worldObj.addTileEntity(tileentity); - //} - } - - public void removeChunkBlockTileEntity(int x, int y, int z) - { - ChunkPosition chunkposition = new ChunkPosition(x, y, z); - - if (this.isChunkLoaded) - { - TileEntity tileentity = (TileEntity)this.chunkTileEntityMap.remove(chunkposition); - - if (tileentity != null) - { - tileentity.invalidate(); - } - } - } - - public void onChunkLoad() - { - this.isChunkLoaded = true; - // do not load mobile chunk entities - //this.worldObj.addTileEntity(this.chunkTileEntityMap.values()); - } - - public void onChunkUnload() - { - this.isChunkLoaded = false; - - if (FMLCommonHandler.instance().getSide().isClient()) - { - this.renderer.markRemoved(); - } - } - - public void setChunkModified() - { - this.isModified = true; - this.chunkUpdated = true; - - if (FMLCommonHandler.instance().getSide().isClient()) - { - this.renderer.markDirty(); - } - } - - /** - * Any Light rendered on a 1.8 Block goes through here - */ - public int getLightBrightnessForSkyBlocks(int i, int j, int k, int l) - { - int i1 = EnumSkyBlock.Sky.defaultLightValue; - return i1 << 20 | l << 4; - } - - public float getBrightness(int i, int j, int k, int l) - { - return 1.0F; - } - - /** - * Returns how bright the block is shown as which is the block's light value looked up in a lookup table (light - * values aren't linear for brightness). Args: x, y, z - */ - public float getLightBrightness(int i, int j, int k) - { - return 1.0F; - } - - /** - * Returns the block's material. - */ - public Material getBlockMaterial(int i, int j, int k) - { - int l = this.getBlockId(i, j, k); - return l == 0 ? Material.air : Block.blocksList[l].blockMaterial; - } - - /** - * Returns true if the block at the specified coordinates is an opaque cube. Args: x, y, z - */ - public boolean isBlockOpaqueCube(int par1, int par2, int par3) - { - Block block = Block.blocksList[this.getBlockId(par1, par2, par3)]; - return block != null && block.isOpaqueCube(); - } - - /** - * Indicate if a material is a normal solid opaque cube. - */ - public boolean isBlockNormalCube(int par1, int par2, int par3) - { - Block block = Block.blocksList[this.getBlockId(par1, par2, par3)]; - return block != null && block.isBlockNormalCube(this.worldObj, par1, par2, par3); - } - - /** - * Returns true if the block at the specified coordinates is empty - */ - public boolean isAirBlock(int x, int y, int z) - { - int id = this.getBlockId(x, y, z); - return id == 0 || Block.blocksList[id] == null || Block.blocksList[id].isAirBlock(this.worldObj, x, y, z); - } - - public boolean isBlockTakingWaterVolume(int x, int y, int z) - { - int id = this.getBlockId(x, y, z); - - if (id == 0) - { - if (this.getBlockMetadata(x, y, z) == 1) - { - return false; - } - } - else if (Block.blocksList[id] == null || Block.blocksList[id].isAirBlock(this.worldObj, x, y, z)) - { - return false; - } - - return true; - } - - /** - * Gets the biome for a given set of x/z coordinates - */ - public BiomeGenBase getBiomeGenForCoords(int i, int j) - { - return this.creationSpotBiome; - } - - /** - * Returns current world height. - */ - public int getHeight() - { - return 16; - } - - /** - * set by !chunk.getAreLevelsEmpty - */ - public boolean extendedLevelsInChunkCache() - { - return false; - } - - public boolean isBlockSolidOnSide(int x, int y, int z, ForgeDirection side, boolean _default) - { - if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) - { - Block block = Block.blocksList[this.getBlockId(x, y, z)]; - return block == null ? false : block.isBlockSolidOnSide(this.worldObj, x, y, z, side); - } - else - { - return _default; - } - } - - /** - * Returns true if the block at the given coordinate has a solid (buildable) top surface. - */ - public boolean doesBlockHaveSolidTopSurface(int i, int j, int k) - { - return this.isBlockSolidOnSide(i, j, k, ForgeDirection.UP, false); - } - - /** - * Return the Vec3Pool object for this world. - */ - public Vec3Pool getWorldVec3Pool() - { - return this.worldObj.getWorldVec3Pool(); - } - - /** - * Is this block powering in the specified direction Args: x, y, z, direction - */ - public int isBlockProvidingPowerTo(int i, int j, int k, int l) - { - return 0; - } - - public void writeChunkData(DataOutput out) throws IOException - { - int count = 0; - int i; - int j; - int k; - int id; - - for (i = this.minX; i < this.maxX; ++i) - { - for (j = this.minY; j < this.maxY; ++j) - { - for (k = this.minZ; k < this.maxZ; ++k) - { - id = this.getBlockId(i, j, k); - - if (id != 0 && Block.blocksList[id] != null) - { - ++count; - } - } - } - } - - ShipMod.modLogger.finest("Writing mobile chunk data: " + count); - out.writeShort(count); - - for (i = this.minX; i < this.maxX; ++i) - { - for (j = this.minY; j < this.maxY; ++j) - { - for (k = this.minZ; k < this.maxZ; ++k) - { - id = this.getBlockId(i, j, k); - - if (id != 0 && Block.blocksList[id] != null) - { - out.writeByte(i); - out.writeByte(j); - out.writeByte(k); - out.writeShort(id); - out.writeInt(this.getBlockMetadata(i, j, k)); - } - } - } - } - } - - public void readChunkData(DataInput in) throws IOException - { - short count = in.readShort(); - ShipMod.modLogger.finest("Reading mobile chunk data: " + count); - - for (int i = 0; i < count; ++i) - { - byte x = in.readByte(); - byte y = in.readByte(); - byte z = in.readByte(); - short id = in.readShort(); - int meta = in.readInt(); - this.setBlockIDWithMetadata(x, y, z, id, meta); - } - } - - public int getMemoryUsage() - { - return 2 + this.blockCount * 9; - } -} diff --git a/src/shipmod/chunk/ShipChunkBuilder$ShipSizeOverflowException.java b/src/shipmod/chunk/ShipChunkBuilder$ShipSizeOverflowException.java deleted file mode 100644 index 002ed485..00000000 --- a/src/shipmod/chunk/ShipChunkBuilder$ShipSizeOverflowException.java +++ /dev/null @@ -1,5 +0,0 @@ -package shipmod.chunk; - -public class ShipChunkBuilder$ShipSizeOverflowException extends Exception -{ -} diff --git a/src/shipmod/chunk/ShipSizeOverflowException.java b/src/shipmod/chunk/ShipSizeOverflowException.java deleted file mode 100644 index f8077b0e..00000000 --- a/src/shipmod/chunk/ShipSizeOverflowException.java +++ /dev/null @@ -1,5 +0,0 @@ -package shipmod.chunk; - -public class ShipSizeOverflowException extends RuntimeException -{ -} diff --git a/src/shipmod/command/CommandAlignShip.java b/src/shipmod/command/CommandAlignShip.java deleted file mode 100644 index 18be0194..00000000 --- a/src/shipmod/command/CommandAlignShip.java +++ /dev/null @@ -1,50 +0,0 @@ -package shipmod.command; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.ICommandSender; -import net.minecraft.entity.Entity; -import net.minecraft.util.ChatMessageComponent; -import shipmod.entity.EntityShip; - -public class CommandAlignShip extends CommandBase -{ - public String getCommandName() - { - return "alignship"; - } - - public void processCommand(ICommandSender icommandsender, String[] astring) - { - if (icommandsender instanceof Entity && ((Entity)icommandsender).ridingEntity instanceof EntityShip) - { - EntityShip ship = (EntityShip)((Entity)icommandsender).ridingEntity; - ship.alignToGrid(); - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d("Ship aligned to world grid")); - } - else - { - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d("Not steering a ship")); - } - } - - /** - * Return the required permission level for this command. - */ - public int getRequiredPermissionLevel() - { - return 0; - } - - /** - * Returns true if the given command sender is allowed to use this command. - */ - public boolean canCommandSenderUseCommand(ICommandSender icommandsender) - { - return icommandsender instanceof Entity; - } - - public String getCommandUsage(ICommandSender icommandsender) - { - return "/" + this.getCommandName(); - } -} diff --git a/src/shipmod/command/CommandDismountShip.java b/src/shipmod/command/CommandDismountShip.java deleted file mode 100644 index e80cde98..00000000 --- a/src/shipmod/command/CommandDismountShip.java +++ /dev/null @@ -1,65 +0,0 @@ -package shipmod.command; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.ICommandSender; -import net.minecraft.entity.Entity; -import net.minecraft.util.ChatMessageComponent; -import shipmod.entity.EntityShip; - -public class CommandDismountShip extends CommandBase -{ - public String getCommandName() - { - return "dismountship"; - } - - /** - * Return the required permission level for this command. - */ - public int getRequiredPermissionLevel() - { - return 4; - } - - public void processCommand(ICommandSender icommandsender, String[] astring) - { - if (icommandsender instanceof Entity) - { - Entity player = (Entity)icommandsender; - - if (player.ridingEntity instanceof EntityShip) - { - boolean flag = false; - - if (astring != null && astring.length > 0 && (astring[0].equals("overwrite") || astring[0].equals("override"))) - { - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d("Overwriting existing blocks with ship blocks")); - flag = true; - } - else - { - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d("Trying to add ship blocks to world")); - } - - ((EntityShip)player.ridingEntity).decompileToBlocks(flag); - player.mountEntity((Entity)null); - return; - } - } - - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d("Not steering a ship")); - } - - /** - * Returns true if the given command sender is allowed to use this command. - */ - public boolean canCommandSenderUseCommand(ICommandSender icommandsender) - { - return icommandsender instanceof Entity; - } - - public String getCommandUsage(ICommandSender icommandsender) - { - return "/" + this.getCommandName() + " [overwrite]"; - } -} diff --git a/src/shipmod/command/CommandHelp.java b/src/shipmod/command/CommandHelp.java deleted file mode 100644 index 6a494aff..00000000 --- a/src/shipmod/command/CommandHelp.java +++ /dev/null @@ -1,58 +0,0 @@ -package shipmod.command; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import net.minecraft.command.CommandBase; -import net.minecraft.command.ICommandSender; -import net.minecraft.entity.Entity; -import net.minecraft.util.ChatMessageComponent; - -public class CommandHelp extends CommandBase -{ - public static List<CommandBase> asCommands = new ArrayList(); - - public String getCommandName() - { - return "smhelp"; - } - - /** - * Return the required permission level for this command. - */ - public int getRequiredPermissionLevel() - { - return 0; - } - - /** - * Returns true if the given command sender is allowed to use this command. - */ - public boolean canCommandSenderUseCommand(ICommandSender icommandsender) - { - return icommandsender instanceof Entity; - } - - public List<String> getCommandAliases() - { - return Arrays.asList(new String[] {"sm"}); - } - - public void processCommand(ICommandSender icommandsender, String[] astring) - { - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d("ShipMod commands:")); - Iterator i$ = asCommands.iterator(); - - while (i$.hasNext()) - { - CommandBase cb = (CommandBase)i$.next(); - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d(cb.getCommandUsage(icommandsender))); - } - } - - public String getCommandUsage(ICommandSender icommandsender) - { - return "/sm or /smhelp"; - } -} diff --git a/src/shipmod/command/CommandKillShip.java b/src/shipmod/command/CommandKillShip.java deleted file mode 100644 index 82150f26..00000000 --- a/src/shipmod/command/CommandKillShip.java +++ /dev/null @@ -1,102 +0,0 @@ -package shipmod.command; - -import java.util.Iterator; -import net.minecraft.command.CommandBase; -import net.minecraft.command.ICommandSender; -import net.minecraft.command.NumberInvalidException; -import net.minecraft.entity.Entity; -import net.minecraft.util.ChatMessageComponent; -import shipmod.entity.EntityShip; - -public class CommandKillShip extends CommandBase -{ - public String getCommandName() - { - return "killship"; - } - - public void processCommand(ICommandSender icommandsender, String[] astring) - { - if (icommandsender instanceof Entity) - { - double range = 16.0D; - - if (astring != null && astring.length > 0) - { - try - { - range = (double)Integer.parseInt(astring[0]); - } - catch (NumberFormatException var13) - { - throw new NumberInvalidException(); - } - } - - range *= range; - Entity player = (Entity)icommandsender; - EntityShip ne = null; - - if (player.ridingEntity instanceof EntityShip) - { - ne = (EntityShip)player.ridingEntity; - } - else - { - double nd = 0.0D; - Iterator i$ = player.worldObj.getLoadedEntityList().iterator(); - - while (i$.hasNext()) - { - Entity entity = (Entity)i$.next(); - - if (entity instanceof EntityShip) - { - double d = player.getDistanceSqToEntity(entity); - - if (d < range && (ne == null || d < nd)) - { - ne = (EntityShip)entity; - nd = d; - } - } - } - } - - if (ne == null) - { - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d("No ship in a " + (int)range + " blocks\' range")); - return; - } - - if (!ne.decompileToBlocks(false)) - { - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d("Failed to decompile ship; dropping to items")); - ne.dropAsItems(); - } - - ne.setDead(); - } - } - - public String getCommandUsage(ICommandSender icommandsender) - { - return "/" + this.getCommandName() + " [range]"; - } - - /** - * Return the required permission level for this command. - */ - public int getRequiredPermissionLevel() - { - return 4; - } - - /** - * Returns true if the given command sender is allowed to use this command. - */ - public boolean canCommandSenderUseCommand(ICommandSender icommandsender) - { - return icommandsender instanceof Entity; - } -} diff --git a/src/shipmod/command/CommandReloadMetaRotations.java b/src/shipmod/command/CommandReloadMetaRotations.java deleted file mode 100644 index b4465492..00000000 --- a/src/shipmod/command/CommandReloadMetaRotations.java +++ /dev/null @@ -1,28 +0,0 @@ -package shipmod.command; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.ICommandSender; -import net.minecraft.util.ChatMessageComponent; -import shipmod.ShipMod; - -public class CommandReloadMetaRotations extends CommandBase -{ - public String getCommandName() - { - return "reloadmeta"; - } - - public void processCommand(ICommandSender icommandsender, String[] astring) - { - if (this.canCommandSenderUseCommand(icommandsender)) - { - ShipMod.instance.metaRotations.readMetaRotationFiles(); - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d("Reloading MetaRotations")); - } - } - - public String getCommandUsage(ICommandSender icommandsender) - { - return "/" + this.getCommandName(); - } -} diff --git a/src/shipmod/command/CommandShipInfo.java b/src/shipmod/command/CommandShipInfo.java deleted file mode 100644 index 8d323afd..00000000 --- a/src/shipmod/command/CommandShipInfo.java +++ /dev/null @@ -1,54 +0,0 @@ -package shipmod.command; - -import java.util.Locale; -import net.minecraft.command.CommandBase; -import net.minecraft.command.ICommandSender; -import net.minecraft.entity.Entity; -import net.minecraft.util.ChatMessageComponent; -import shipmod.entity.EntityShip; - -public class CommandShipInfo extends CommandBase -{ - public String getCommandName() - { - return "sminfo"; - } - - public void processCommand(ICommandSender icommandsender, String[] astring) - { - if (icommandsender instanceof Entity && ((Entity)icommandsender).ridingEntity instanceof EntityShip) - { - EntityShip ship = (EntityShip)((Entity)icommandsender).ridingEntity; - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d("Ship information")); - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d(String.format(Locale.ENGLISH, "Position: %.2f, %.2f, %.2f", new Object[] {Double.valueOf(ship.posX), Double.valueOf(ship.posY), Double.valueOf(ship.posZ)}))); - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d(String.format(Locale.ENGLISH, "Speed: %.2f km/h", new Object[] {Float.valueOf(ship.getHorizontalVelocity() * 20.0F * 3.6F)}))); - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d(String.format(Locale.ENGLISH, "Ship health: %i / %i", new Object[] { Integer.valueOf(ship.health), Integer.valueOf(ship.getShipChunk().getBlockCount())}))); - - } - else - { - icommandsender.sendChatToPlayer(ChatMessageComponent.func_111066_d("Not steering a ship")); - } - } - - /** - * Return the required permission level for this command. - */ - public int getRequiredPermissionLevel() - { - return 0; - } - - /** - * Returns true if the given command sender is allowed to use this command. - */ - public boolean canCommandSenderUseCommand(ICommandSender icommandsender) - { - return icommandsender instanceof Entity; - } - - public String getCommandUsage(ICommandSender icommandsender) - { - return "/".concat(this.getCommandName()); - } -} diff --git a/src/shipmod/command/CommandTpShip.java b/src/shipmod/command/CommandTpShip.java deleted file mode 100644 index c3441503..00000000 --- a/src/shipmod/command/CommandTpShip.java +++ /dev/null @@ -1,115 +0,0 @@ -package shipmod.command; - -import java.util.List; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.ICommandSender; -import net.minecraft.command.PlayerNotFoundException; -import net.minecraft.command.WrongUsageException; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.server.MinecraftServer; - -public class CommandTpShip extends CommandBase -{ - public String getCommandName() - { - return "tpship"; - } - - /** - * Return the required permission level for this command. - */ - public int getRequiredPermissionLevel() - { - return 4; - } - - public String getCommandUsage(ICommandSender par1ICommandSender) - { - return "commands.tp.usage"; - } - - public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) - { - if (par2ArrayOfStr.length < 1) - { - throw new WrongUsageException("Invalid command usage", new Object[0]); - } - else - { - EntityPlayerMP entityplayermp; - - if (par2ArrayOfStr.length != 2 && par2ArrayOfStr.length != 4) - { - entityplayermp = getCommandSenderAsPlayer(par1ICommandSender); - } - else - { - entityplayermp = func_82359_c(par1ICommandSender, par2ArrayOfStr[0]); - - if (entityplayermp == null) - { - throw new PlayerNotFoundException(); - } - } - - if (par2ArrayOfStr.length != 3 && par2ArrayOfStr.length != 4) - { - if (par2ArrayOfStr.length == 1 || par2ArrayOfStr.length == 2) - { - EntityPlayerMP entityplayermp1 = func_82359_c(par1ICommandSender, par2ArrayOfStr[par2ArrayOfStr.length - 1]); - - if (entityplayermp1 == null) - { - throw new PlayerNotFoundException(); - } - - if (entityplayermp1.worldObj != entityplayermp.worldObj) - { - notifyAdmins(par1ICommandSender, "commands.tp.notSameDimension", new Object[0]); - return; - } - - // Entity ship = entityplayermp.ridingEntity; - - //entityplayermp.mountEntity((Entity)null); - entityplayermp.ridingEntity.setPositionAndRotation(entityplayermp1.posX, Math.min(entityplayermp1.posY + 128, 255), entityplayermp1.posZ, entityplayermp.ridingEntity.rotationYaw, entityplayermp.ridingEntity.rotationPitch); - entityplayermp.playerNetServerHandler.setPlayerLocation(entityplayermp1.posX, Math.min(entityplayermp1.posY + 128, 255), entityplayermp1.posZ, entityplayermp1.rotationYaw, entityplayermp1.rotationPitch); - //entityplayermp.mountEntity(ship); - - notifyAdmins(par1ICommandSender, "commands.tp.success", new Object[] {entityplayermp.getEntityName(), entityplayermp1.getEntityName()}); - } - } - else if (entityplayermp.worldObj != null) - { - int i = par2ArrayOfStr.length - 3; - double d0 = func_110666_a(par1ICommandSender, entityplayermp.posX, par2ArrayOfStr[i++]); - double d1 = func_110665_a(par1ICommandSender, entityplayermp.posY, par2ArrayOfStr[i++], 0, 0); - double d2 = func_110666_a(par1ICommandSender, entityplayermp.posZ, par2ArrayOfStr[i++]); - //Entity ship = entityplayermp.ridingEntity; - //entityplayermp.mountEntity((Entity)null); - entityplayermp.ridingEntity.setPositionAndRotation(d0, d1, d2, entityplayermp.ridingEntity.rotationYaw, entityplayermp.ridingEntity.rotationPitch); - entityplayermp.setPositionAndUpdate(d0, d1, d2); - - notifyAdmins(par1ICommandSender, "commands.tp.success.coordinates", new Object[] {entityplayermp.getEntityName(), Double.valueOf(d0), Double.valueOf(d1), Double.valueOf(d2)}); - } - } - } - - /** - * Adds the strings available in this command to the given list of tab completion options. - */ - public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) - { - return par2ArrayOfStr.length != 1 && par2ArrayOfStr.length != 2 ? null : getListOfStringsMatchingLastWord(par2ArrayOfStr, MinecraftServer.getServer().getAllUsernames()); - } - - /** - * Return whether the specified command parameter index is a username parameter. - */ - public boolean isUsernameIndex(String[] par1ArrayOfStr, int par2) - { - return par2 == 0; - } -} diff --git a/src/shipmod/control/ShipController.java b/src/shipmod/control/ShipController.java deleted file mode 100644 index 0bd6648f..00000000 --- a/src/shipmod/control/ShipController.java +++ /dev/null @@ -1,19 +0,0 @@ -package shipmod.control; - -import net.minecraft.entity.player.EntityPlayer; -import shipmod.entity.EntityShip; - -public class ShipController -{ - private int shipControl = 0; - - public void updateControl(EntityShip ship, EntityPlayer player, int i) - { - this.shipControl = i; - } - - public int getShipControl() - { - return this.shipControl; - } -} diff --git a/src/shipmod/control/ShipControllerClient.java b/src/shipmod/control/ShipControllerClient.java deleted file mode 100644 index cd9a7d86..00000000 --- a/src/shipmod/control/ShipControllerClient.java +++ /dev/null @@ -1,20 +0,0 @@ -package shipmod.control; - -import com.google.common.io.ByteArrayDataOutput; -import com.google.common.io.ByteStreams; -import net.minecraft.client.entity.EntityClientPlayerMP; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.network.packet.Packet250CustomPayload; -import shipmod.entity.EntityShip; - -public class ShipControllerClient extends ShipController -{ - public void updateControl(EntityShip ship, EntityPlayer player, int i) - { - super.updateControl(ship, player, i); - ByteArrayDataOutput out = ByteStreams.newDataOutput(5); - out.writeInt(ship.entityId); - out.writeByte(i); - ((EntityClientPlayerMP)player).sendQueue.addToSendQueue(new Packet250CustomPayload("shipControl", out.toByteArray())); - } -} diff --git a/src/shipmod/control/ShipKeyHandler.java b/src/shipmod/control/ShipKeyHandler.java deleted file mode 100644 index ee202c2e..00000000 --- a/src/shipmod/control/ShipKeyHandler.java +++ /dev/null @@ -1,123 +0,0 @@ -package shipmod.control; - -import cpw.mods.fml.client.registry.KeyBindingRegistry.KeyHandler; -import cpw.mods.fml.common.TickType; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; -import java.util.EnumSet; -import net.minecraft.client.Minecraft; -import net.minecraft.client.settings.KeyBinding; -import shipmod.entity.EntityShip; - -@SideOnly(Side.CLIENT) -public class ShipKeyHandler extends KeyHandler -{ - private Minecraft mc = Minecraft.getMinecraft(); - public final KeyBinding kbUp; - public final KeyBinding kbDown; - public final KeyBinding kbBrake; - public final KeyBinding kbAlign; - - public ShipKeyHandler(KeyBinding up, KeyBinding down, KeyBinding brake, KeyBinding align) - { - super(new KeyBinding[] {up, down, brake, align}, new boolean[] {false, false, false, false}); - this.kbUp = up; - this.kbDown = down; - this.kbBrake = brake; - this.kbAlign = align; - } - - public String getLabel() - { - return "ShipMod key handler"; - } - - public void keyDown(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd, boolean isRepeat) - { - if (tickEnd) - { - this.keyEvent(kb, true); - } - } - - public void keyUp(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd) - { - if (tickEnd) - { - this.keyEvent(kb, false); - } - } - - public void keyEvent(KeyBinding kb, boolean down) - { - if (this.mc.thePlayer != null && this.mc.thePlayer.ridingEntity instanceof EntityShip) - { - int c = 0; - - if (down) - { - if (kb == this.kbBrake) - { - c = 3; - } - else if (kb == this.kbAlign) - { - c = 4; - } - } - - if (c == 0) - { - int ship = 0; - - if (this.kbUp.isPressed()) - { - ++ship; - } - - if (this.kbDown.isPressed()) - { - --ship; - } - - c = ship == 0 ? 0 : (ship < 0 ? 1 : (ship > 0 ? 2 : 0)); - } - - EntityShip var5 = (EntityShip)this.mc.thePlayer.ridingEntity; - var5.getController().updateControl(var5, this.mc.thePlayer, c); - } - } - - public EnumSet<TickType> ticks() - { - return EnumSet.of(TickType.CLIENT); - } - - public int getHeightControl() - { - if (this.kbAlign.isPressed()) - { - return 4; - } - else if (this.kbBrake.isPressed()) - { - return 3; - } - else - { - int i = 0; - - if (this.kbUp.isPressed()) - { - ++i; - } - - if (this.kbDown.isPressed()) - { - --i; - } - - return i == 0 ? 0 : (i < 0 ? 1 : (i > 0 ? 2 : 0)); - } - } -} diff --git a/src/shipmod/entity/EntityShip.java b/src/shipmod/entity/EntityShip.java deleted file mode 100644 index bcb462f1..00000000 --- a/src/shipmod/entity/EntityShip.java +++ /dev/null @@ -1,1320 +0,0 @@ -package shipmod.entity; - -import com.google.common.io.ByteArrayDataInput; -import com.google.common.io.ByteArrayDataOutput; -import com.google.common.io.ByteStreams; - -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; -import ic2.api.network.NetworkHelper; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import net.minecraft.block.Block; -import net.minecraft.block.material.Material; -import net.minecraft.client.entity.EntityClientPlayerMP; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.EnumEntitySize; -import net.minecraft.entity.item.EntityBoat; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.network.packet.Packet250CustomPayload; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.AxisAlignedBB; -import net.minecraft.util.ChunkCoordinates; -import net.minecraft.util.DamageSource; -import net.minecraft.util.MathHelper; -import net.minecraft.util.Vec3; -import net.minecraft.world.ChunkPosition; -import net.minecraft.world.World; -import net.minecraftforge.common.ForgeDirection; -import shipmod.ShipMod; -import shipmod.chunk.LocatedBlock; -import shipmod.chunk.MobileChunk; -import shipmod.control.ShipController; -import shipmod.control.ShipControllerClient; -import shipmod.util.AABBRotator; -import shipmod.util.MathHelperMod; - -public class EntityShip extends EntityBoat implements IEntityAdditionalSpawnData -{ - public int fuelLevel = 0; - public static final float BASE_FORWARD_SPEED = 0.006F; - public static final float BASE_TURN_SPEED = 0.34F; - public static final float BASE_LIFT_SPEED = 0.005F; - private MobileChunk shipChunk; - private ShipCapabilities capabilities; - private ShipController controller; - public float motionYaw; - public int frontDirection; - public int seatX; - public int seatY; - public int seatZ; - private Entity prevRiddenByEntity; - private boolean isFlying; - protected float groundFriction; - protected float horFriction; - protected float vertFriction; - private int[] layeredBlockVolumeCount; - private boolean riddenByOtherPlayer; - private boolean syncPosWithServer; - @SideOnly(Side.CLIENT) - private int boatPosRotationIncrements; - @SideOnly(Side.CLIENT) - private double boatX; - @SideOnly(Side.CLIENT) - private double boatY; - @SideOnly(Side.CLIENT) - private double boatZ; - @SideOnly(Side.CLIENT) - private double boatPitch; - @SideOnly(Side.CLIENT) - private double boatYaw; - @SideOnly(Side.CLIENT) - private double boatVelX; - @SideOnly(Side.CLIENT) - private double boalVelY; - @SideOnly(Side.CLIENT) - private double boatVelZ; - - public ArrayList<EntityLivingBase> playersOnShip = new ArrayList<EntityLivingBase>(); - public int health; - - private int sourceYaw; - private boolean explosionFlag = false; - - public static boolean isAABBInLiquidNotFall(World world, AxisAlignedBB aabb) - { - int i = MathHelper.floor_double(aabb.minX); - int j = MathHelper.floor_double(aabb.maxX + 1.0D); - int k = MathHelper.floor_double(aabb.minY); - int l = MathHelper.floor_double(aabb.maxY + 1.0D); - int i1 = MathHelper.floor_double(aabb.minZ); - int j1 = MathHelper.floor_double(aabb.maxZ + 1.0D); - - for (int k1 = i; k1 < j; ++k1) - { - for (int l1 = k; l1 < l; ++l1) - { - for (int i2 = i1; i2 < j1; ++i2) - { - Block block = Block.blocksList[world.getBlockId(k1, l1, i2)]; - - if (block != null && (block.blockMaterial == Material.water || block.blockMaterial == Material.lava)) - { - int j2 = world.getBlockMetadata(k1, l1, i2); - double d0 = (double)(l1 + 1); - - if (j2 < 8) - { - d0 = (double)(l1 + 1) - (double)j2 / 8.0D; - - if (d0 >= aabb.minY) - { - return true; - } - } - } - } - } - } - - return false; - } - - public EntityShip(World world) - { - super(world); - this.shipChunk = new MobileChunk(world, this); - this.capabilities = new ShipCapabilities(); - - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) - { - this.controller = new ShipControllerClient(); - } - else - { - this.controller = new ShipController(); - } - - this.motionYaw = 0.0F; - this.layeredBlockVolumeCount = null; - this.frontDirection = 0; - this.yOffset = 0.0F; - this.groundFriction = 0.9F; - this.horFriction = 0.994F; - this.vertFriction = 0.95F; - this.prevRiddenByEntity = null; - this.isFlying = false; - this.riddenByOtherPlayer = false; - this.syncPosWithServer = true; - - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) - { - this.boatPosRotationIncrements = 0; - this.boatX = this.boatY = this.boatZ = 0.0D; - this.boatPitch = this.boatYaw = 0.0D; - this.boatVelX = this.boalVelY = this.boatVelZ = 0.0D; - } - } - - @Override - protected void entityInit() - { - this.dataWatcher.addObject(30, Byte.valueOf((byte)0)); - } - - public MobileChunk getShipChunk() - { - return this.shipChunk; - } - - public ShipCapabilities getCapabilities() - { - return this.capabilities; - } - - public ShipController getController() - { - return this.controller; - } - - public void setFrontDirection(int dir) - { - this.frontDirection = dir; - } - - public void onChunkBlockAdded(int id, int metadata) - { - if (id != 0) - { - this.capabilities.onChunkBlockAdded(id, metadata); - } - } - - /** - * Will get destroyed next tick. - */ - @Override - public void setDead() - { - super.setDead(); - this.shipChunk.onChunkUnload(); - } - - /** - * Gets called every tick from main Entity class - */ - @Override - public void onEntityUpdate() - { - super.onEntityUpdate(); - - if (this.shipChunk.chunkUpdated) - { - this.shipChunk.chunkUpdated = false; - this.setSize((float)Math.max(this.shipChunk.maxX() - this.shipChunk.minX(), this.shipChunk.maxZ() - this.shipChunk.minZ()), (float)(this.shipChunk.maxY() - this.shipChunk.minY())); - World.MAX_ENTITY_RADIUS = Math.max(World.MAX_ENTITY_RADIUS, (double)Math.max(this.width, this.height)) + 2.0D; - - try - { - this.fillAirBlocks(new HashSet(), -1, -1, -1); - } - catch (StackOverflowError var4) - { - System.err.println(var4.toString()); - } - - this.layeredBlockVolumeCount = new int[this.shipChunk.maxX() - this.shipChunk.minX()]; - - for (int y = 0; y < this.layeredBlockVolumeCount.length; ++y) - { - for (int i = this.shipChunk.minX(); i < this.shipChunk.maxX(); ++i) - { - for (int j = this.shipChunk.minZ(); j < this.shipChunk.maxZ(); ++j) - { - if (this.shipChunk.isBlockTakingWaterVolume(i, y + this.shipChunk.minY(), j)) - { - ++this.layeredBlockVolumeCount[y]; - } - } - } - } - - this.isFlying = this.capabilities.canFly(); - } - } - - public void setRotatedBoundingBox() - { - if (this.shipChunk == null) - { - float hw = this.width / 2.0F; - this.boundingBox.setBounds(this.posX - (double)hw, this.posY, this.posZ - (double)hw, this.posX + (double)hw, this.posY + (double)this.height, this.posZ + (double)hw); - } - else - { - this.boundingBox.setBounds(this.posX - (double)this.shipChunk.getCenterX(), this.posY, this.posZ - (double)this.shipChunk.getCenterZ(), this.posX + (double)this.shipChunk.getCenterX(), this.posY + (double)this.height, this.posZ + (double)this.shipChunk.getCenterZ()); - AABBRotator.rotateAABBAroundY(this.boundingBox, this.posX, this.posZ, (float)Math.toRadians((double)this.rotationYaw)); - } - } - - /** - * Sets the width and height of the entity. Args: width, height - */ - @Override - public void setSize(float w, float h) - { - float f; - - if (w != this.width || h != this.height) - { - this.width = w; - this.height = h; - f = w / 2.0F; - this.boundingBox.setBounds(this.posX - (double)f, this.posY, this.posZ - (double)f, this.posX + (double)f, this.posY + (double)this.height, this.posZ + (double)f); - } - - f = w % 2.0F; - - if ((double)f < 0.375D) - { - this.myEntitySize = EnumEntitySize.SIZE_1; - } - else if ((double)f < 0.75D) - { - this.myEntitySize = EnumEntitySize.SIZE_2; - } - else if ((double)f < 1.0D) - { - this.myEntitySize = EnumEntitySize.SIZE_3; - } - else if ((double)f < 1.375D) - { - this.myEntitySize = EnumEntitySize.SIZE_4; - } - else if ((double)f < 1.75D) - { - this.myEntitySize = EnumEntitySize.SIZE_5; - } - else - { - this.myEntitySize = EnumEntitySize.SIZE_6; - } - } - - @Override - @SideOnly(Side.CLIENT) - - /** - * Sets the position and rotation. Only difference from the other one is no bounding on the rotation. Args: posX, - * posY, posZ, yaw, pitch - */ - public void setPositionAndRotation2(double x, double y, double z, float yaw, float pitch, int incr) - { - if (this.riddenByOtherPlayer) - { - this.boatPosRotationIncrements = incr + 5; - } - else - { - double dx = x - this.posX; - double dy = y - this.posY; - double dz = z - this.posZ; - double d = dx * dx + dy * dy + dz * dz; - - if (d < 0.3D) - { - return; - } - - this.syncPosWithServer = true; - this.boatPosRotationIncrements = incr; - } - - this.boatX = x; - this.boatY = y; - this.boatZ = z; - this.boatYaw = (double)yaw; - this.boatPitch = (double)pitch; - this.motionX = this.boatVelX; - this.motionY = this.boalVelY; - this.motionZ = this.boatVelZ; - } - - @Override - @SideOnly(Side.CLIENT) - - /** - * Sets the velocity to the args. Args: x, y, z - */ - public void setVelocity(double x, double y, double z) - { - this.boatVelX = this.motionX = x; - this.boalVelY = this.motionY = y; - this.boatVelZ = this.motionZ = z; - } - - /** - * Called to update the entity's position/logic. - */ - @Override - public void onUpdate() - { - this.onEntityUpdate(); - this.prevPosX = this.posX; - this.prevPosY = this.posY; - this.prevPosZ = this.posZ; - double horvel = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ); - - if (FMLCommonHandler.instance().getEffectiveSide().isClient() && (this.riddenByOtherPlayer || this.syncPosWithServer)) - { - this.handleClientUpdate(); - - if (this.boatPosRotationIncrements == 0) - { - this.syncPosWithServer = false; - } - } - else - { - this.handleServerUpdate(horvel); - } - } - - @SideOnly(Side.CLIENT) - protected void handleClientUpdate() - { - if (this.boatPosRotationIncrements > 0) - { - double dx = this.posX + (this.boatX - this.posX) / (double)this.boatPosRotationIncrements; - double dy = this.posY + (this.boatY - this.posY) / (double)this.boatPosRotationIncrements; - double dz = this.posZ + (this.boatZ - this.posZ) / (double)this.boatPosRotationIncrements; - double ang = MathHelper.wrapAngleTo180_double(this.boatYaw - (double)this.rotationYaw); - this.rotationYaw = (float)((double)this.rotationYaw + ang / (double)this.boatPosRotationIncrements); - this.rotationPitch = (float)((double)this.rotationPitch + (this.boatPitch - (double)this.rotationPitch) / (double)this.boatPosRotationIncrements); - --this.boatPosRotationIncrements; - this.setPosition(dx, dy, dz); - this.setRotation(this.rotationYaw, this.rotationPitch); - } - else - { - this.setPosition(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ); - - if (this.onGround) - { - this.motionX *= (double)this.groundFriction; - this.motionY *= (double)this.groundFriction; - this.motionZ *= (double)this.groundFriction; - } - - this.motionX *= (double)this.horFriction; - this.motionY *= (double)this.vertFriction; - this.motionZ *= (double)this.horFriction; - } - - this.setRotatedBoundingBox(); - movePlayers(); - } - - private void movePlayers() { - // Grab players on ship - List entities = worldObj.getEntitiesWithinAABBExcludingEntity(riddenByEntity, this.boundingBox); - if (entities != null && !entities.isEmpty()) { - for (Object o : entities) { - if (o != null && o instanceof EntityPlayer) { - EntityPlayer e = (EntityPlayer)o; - - if (!e.isSneaking()) { - updateRiderPosition(e, seatX, seatY, seatZ); - } - } - } - } - } - - protected void handleServerUpdate(double horvel) - { - if (this.riddenByEntity == null && this.prevRiddenByEntity != null) - { - this.prevRiddenByEntity.mountEntity(this); - - if (!this.decompileToBlocks(false) && !ShipMod.instance.modConfig.remountOnDecompilationFail) - { - this.riddenByEntity.mountEntity((Entity)null); - } - - this.prevRiddenByEntity = null; - } - - if (this.riddenByEntity != null) - { - this.handlePlayerControl(); - this.prevRiddenByEntity = this.riddenByEntity; - } - - this.fuelLevel--; - if (!FMLCommonHandler.instance().getEffectiveSide().isClient()) { - if (fuelLevel == 20 * 10) { - ((EntityPlayer)this.riddenByEntity).addChatMessage("[ShipMod] Low fuel level. 10 seconds remaining"); - } - - if (fuelLevel <= 0) { - ((EntityPlayer)this.riddenByEntity).addChatMessage("[ShipMod] Ship is out of fuel"); - - if (!this.decompileToBlocks(false)) { - dropAsItems(); - } - } - } - double var25 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ); - double maxvel = (double)ShipMod.instance.modConfig.speedLimit; - double list; - - if (var25 > maxvel) - { - list = maxvel / var25; - this.motionX *= list; - this.motionZ *= list; - } - - this.motionY = MathHelperMod.clamp_double(this.motionY, -maxvel, maxvel); - - if (this.onGround) - { - this.motionX *= (double)this.groundFriction; - this.motionY *= (double)this.groundFriction; - this.motionZ *= (double)this.groundFriction; - } - - this.motionYaw *= 0.7F; - this.rotationYaw += this.motionYaw; - this.setRotatedBoundingBox(); - this.moveEntity(this.motionX, this.motionY, this.motionZ); - this.posY = Math.min(this.posY, (double)this.worldObj.getHeight()); - this.motionX *= (double)this.horFriction; - this.motionY *= (double)this.vertFriction; - this.motionZ *= (double)this.horFriction; - this.rotationPitch = 0.0F; - - if (ShipMod.instance.modConfig.shipControlType == 0) - { - list = (double)this.rotationYaw; - double i1 = this.prevPosX - this.posX; - double k1 = this.prevPosZ - this.posZ; - - if (this.riddenByEntity != null && !this.isBraking() && i1 * i1 + k1 * k1 > 0.01D) - { - list = 270.0D - Math.toDegrees(Math.atan2(k1, i1)) + (double)((float)this.frontDirection * 90.0F); - } - - double i2 = MathHelper.wrapAngleTo180_double(list - (double)this.rotationYaw); - double maxyawspeed = 2.0D; - - if (i2 > maxyawspeed) - { - i2 = maxyawspeed; - } - - if (i2 < -maxyawspeed) - { - i2 = -maxyawspeed; - } - - this.rotationYaw = (float)((double)this.rotationYaw + i2); - } - - this.setRotation(this.rotationYaw, this.rotationPitch); - - movePlayers(); - } - - private void handlePlayerControl() - { - if (this.riddenByEntity instanceof EntityLivingBase) - { - double i = (double)((EntityLivingBase)this.riddenByEntity).moveForward; - - if (this.isFlying()) - { - i *= 0.5D; - } - - if (ShipMod.instance.modConfig.shipControlType == 1) - { - Vec3 dsin = this.worldObj.getWorldVec3Pool().getVecFromPool(this.riddenByEntity.motionX, 0.0D, this.riddenByEntity.motionZ); - dsin.rotateAroundY((float)Math.toRadians((double)this.riddenByEntity.rotationYaw)); - double steer = (double)((EntityLivingBase)this.riddenByEntity).moveStrafing; - this.motionYaw = (float)((double)this.motionYaw + steer * 0.3499999940395355D * (double)this.capabilities.rotationMultiplier * (double)ShipMod.instance.modConfig.turnSpeed); - float yaw = (float)Math.toRadians((double)(180.0F - this.rotationYaw + (float)this.frontDirection * 90.0F)); - dsin.xCoord = this.motionX; - dsin.zCoord = this.motionZ; - dsin.rotateAroundY(yaw); - dsin.xCoord *= 0.9D; - dsin.zCoord -= i * 0.004999999888241291D * (double)this.capabilities.speedMultiplier; - dsin.rotateAroundY(-yaw); - this.motionX = dsin.xCoord; - this.motionZ = dsin.zCoord; - } - else if (ShipMod.instance.modConfig.shipControlType == 0 && i > 0.0D) - { - double dsin1 = -Math.sin(Math.toRadians((double)this.riddenByEntity.rotationYaw)); - double dcos = Math.cos(Math.toRadians((double)this.riddenByEntity.rotationYaw)); - this.motionX += dsin1 * 0.004999999888241291D * (double)this.capabilities.speedMultiplier; - this.motionZ += dcos * 0.004999999888241291D * (double)this.capabilities.speedMultiplier; - } - } - - if (this.controller.getShipControl() != 0) - { - if (this.controller.getShipControl() == 4) - { - this.alignToGrid(); - } - else if (this.isBraking()) - { - this.motionX *= (double)this.capabilities.brakeMult; - this.motionZ *= (double)this.capabilities.brakeMult; - - if (this.isFlying()) - { - this.motionY *= (double)this.capabilities.brakeMult; - } - } - else if (this.controller.getShipControl() < 3 && this.capabilities.canFly()) - { - byte i1; - - if (this.controller.getShipControl() == 2) - { - this.isFlying = true; - i1 = 1; - } - else - { - i1 = -1; - } - - this.motionY += (double)((float)i1 * 0.004F * this.capabilities.liftMultiplier); - } - } - } - - public boolean isFlying() - { - return true; - } - - public boolean isBraking() - { - return this.controller.getShipControl() == 3; - } - - @Override - public boolean func_96092_aw() - { - return this.ticksExisted > 60; - } - - @Override - @SideOnly(Side.CLIENT) - public void func_70270_d(boolean flag) - { - this.riddenByOtherPlayer = flag; - } - - @Override - public boolean shouldRiderSit() - { - return true; - } - - @Override - public void updateRiderPosition() - { - this.updateRiderPosition(this.riddenByEntity, this.seatX, this.seatY, this.seatZ); - } - - public void updateRiderPosition(Entity entity, int seatx, int seaty, int seatz) - { - if (entity != null) - { - float yaw = (float)Math.toRadians((double)this.rotationYaw); - int x1 = seatx; - int y1 = seaty; - int z1 = seatz; - - if (this.frontDirection == 0) - { - z1 = seatz - 1; - } - else if (this.frontDirection == 1) - { - x1 = seatx + 1; - } - else if (this.frontDirection == 2) - { - z1 = seatz + 1; - } - else if (this.frontDirection == 3) - { - x1 = seatx - 1; - } - - int id = this.shipChunk.getBlockId(x1, MathHelper.floor_double((double)seaty + this.getMountedYOffset() + entity.getYOffset()), z1); - - if (id != 0 && Block.blocksList[id] != null && Block.blocksList[id].isOpaqueCube()) - { - x1 = seatx; - y1 = seaty; - z1 = seatz; - } - - Vec3 vec = this.worldObj.getWorldVec3Pool().getVecFromPool((double)((float)x1 - this.shipChunk.getCenterX()) + 0.5D, (double)(y1 - this.shipChunk.minY()) + this.getMountedYOffset(), (double)((float)z1 - this.shipChunk.getCenterZ()) + 0.5D); - vec.rotateAroundY(yaw); - entity.setPosition(this.posX + vec.xCoord, this.posY + vec.yCoord + entity.getYOffset(), this.posZ + vec.zCoord); - } - } - - /** - * Returns the Y offset from the entity's position for any entity riding this one. - */ - @Override - public double getMountedYOffset() - { - return (double)this.yOffset + 0.5D; - } - - /** - * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to - * prevent them from trampling crops - */ - @Override - protected boolean canTriggerWalking() - { - return false; - } - - /** - * Returns a boundingBox used to collide the entity with other entities and blocks. This enables the entity to be - * pushable on contact, like boats or minecarts. - */ - @Override - public AxisAlignedBB getCollisionBox(Entity entity) - { - return null; - } - - /** - * returns the bounding box for this entity - */ - @Override - public AxisAlignedBB getBoundingBox() - { - return this.boundingBox; - } - - /** - * Returns true if this entity should push and be pushed by other entities when colliding. - */ - @Override - public boolean canBePushed() - { - return false; - } - - /** - * Returns true if other Entities should be prevented from moving through this Entity. - */ - @Override - public boolean canBeCollidedWith() - { - return !this.isDead; - } - - /** - * Called when the entity is attacked. - */ - @Override - public boolean attackEntityFrom(DamageSource source, float damage) - { - this.health -= damage; - System.out.println("[SHIP] Entity damaged: -" + damage + ". Health: " + this.health + "/" + shipChunk.getBlockCount()); - - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { - return true; - } - - if (this.health <= 0 && !this.isDead) { - ((EntityPlayer)this.riddenByEntity).addChatMessage("[ShipMod] MOVEABLE SHIP IS DESTROYED"); - - this.explosionFlag = true; - - if (!this.decompileToBlocks(false)) { - dropAsItems(); - this.setDead(); - return true; - } - } - - return true; - } - - @Override - @SideOnly(Side.CLIENT) - public float getShadowSize() - { - return 0.5F; - } - - public float getHorizontalVelocity() - { - return (float)Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ); - } - - @Override - public boolean func_130002_c(EntityPlayer entityplayer) - { - if (this.riddenByEntity != null && this.riddenByEntity != entityplayer) - { - return true; - } - else - { - if (FMLCommonHandler.instance().getEffectiveSide().isClient() && entityplayer.getDistanceSqToEntity(this) >= 36.0D) - { - ByteArrayDataOutput out = ByteStreams.newDataOutput(4); - out.writeInt(this.entityId); - Packet250CustomPayload packet = new Packet250CustomPayload("shipInteract", out.toByteArray()); - ((EntityClientPlayerMP)entityplayer).sendQueue.addToSendQueue(packet); - } - - if (this.riddenByEntity == entityplayer) - { - if (ShipMod.instance.modConfig.enableRightClickDismount) - { - this.decompileToBlocks(false); - } - } - else if (!FMLCommonHandler.instance().getEffectiveSide().isClient()) - { - entityplayer.mountEntity(this); - } - - return true; - } - } - - public void alignToGrid() - { - this.rotationYaw = (float)Math.round(this.rotationYaw / 90.0F) * 90.0F; - this.rotationPitch = 0.0F; - this.posX = (double)MathHelperMod.round_double(this.posX); - this.posY = (double)MathHelperMod.round_double(this.posY); - this.posZ = (double)MathHelperMod.round_double(this.posZ); - this.motionX = this.motionY = this.motionZ = 0.0D; - } - - public boolean canDecompile() - { - float yaw = (float)Math.round(this.rotationYaw / 90.0F) * 90.0F; - yaw = (float)Math.toRadians((double)this.rotationYaw); - float ox = -this.shipChunk.getCenterX(); - float oy = (float)(-this.shipChunk.minY()); - float oz = -this.shipChunk.getCenterZ(); - Vec3 vec = this.worldObj.getWorldVec3Pool().getVecFromPool(0.0D, 0.0D, 0.0D); - - for (int i = this.shipChunk.minX(); i < this.shipChunk.maxX(); ++i) - { - for (int j = this.shipChunk.minY(); j < this.shipChunk.maxY(); ++j) - { - for (int k = this.shipChunk.minZ(); k < this.shipChunk.maxZ(); ++k) - { - if (!this.shipChunk.isAirBlock(i, j, k)) - { - vec.xCoord = (double)((float)i + ox); - vec.yCoord = (double)((float)j + oy); - vec.zCoord = (double)((float)k + oz); - vec.rotateAroundY(yaw); - int ix = MathHelperMod.round_double(vec.xCoord + this.posX); - int iy = MathHelperMod.round_double(vec.yCoord + this.posY); - int iz = MathHelperMod.round_double(vec.zCoord + this.posZ); - int id = this.worldObj.getBlockId(ix, iy, iz); - - if (id != 0 && Block.blocksList[id] != null && !Block.blocksList[id].isAirBlock(this.worldObj, ix, iy, iz) && !Block.blocksList[id].blockMaterial.isLiquid() && !ShipMod.instance.modConfig.overwritableBlocks.contains(Integer.valueOf(id))) - { - return false; - } - } - } - } - } - - return true; - } - - public boolean decompileToBlocks(boolean overwrite) - { - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) - { - return true; - } - else if (!overwrite && !this.canDecompile()) - { - if (this.prevRiddenByEntity instanceof EntityPlayer) - { - ((EntityPlayer)this.prevRiddenByEntity).addChatMessage("Cannot decompile ship here"); - } - - return false; - } - else - { - ArrayList<ChunkCoordinates> explosions = new ArrayList<ChunkCoordinates>(); - ArrayList<TileEntity> IC2MachinesToUpdateFacing = new ArrayList<TileEntity>(); - - int currentrotation = Math.round(this.rotationYaw / 90.0F); - int deltarotation = -(currentrotation & 3); - this.rotationYaw = (float)currentrotation * 90.0F; - this.rotationPitch = 0.0F; - float yaw = (float)Math.toRadians((double)this.rotationYaw); - this.updateRiderPosition(); - - if (!FMLCommonHandler.instance().getEffectiveSide().isClient()) - { - this.worldObj.isRemote = true; // lock world from changes - boolean flag = this.worldObj.getGameRules().getGameRuleBooleanValue("doTileDrops"); - this.worldObj.getGameRules().setOrCreateGameRule("doTileDrops", "false"); - ArrayList list = new ArrayList(); - float ox = -this.shipChunk.getCenterX(); - float oy = (float)(-this.shipChunk.minY()); - float oz = -this.shipChunk.getCenterZ(); - Vec3 vec = this.worldObj.getWorldVec3Pool().getVecFromPool(0.0D, 0.0D, 0.0D); - - for (int x = this.shipChunk.minX(); x <= this.shipChunk.maxX(); x++) - { - for (int z = this.shipChunk.minZ(); z <= this.shipChunk.maxZ(); z++) - { - for (int y = this.shipChunk.minY(); y <= this.shipChunk.maxY(); y++) - { - TileEntity tileentity = this.shipChunk.getBlockTileEntity(x, y, z); - int id = this.shipChunk.getBlockId(x, y, z); - int meta = this.shipChunk.getBlockMetadata(x, y, z); - - if (id == 0) - { - if (meta == 1) - { - continue; - } - } - else if (Block.blocksList[id] == null || Block.blocksList[id].isAirBlock(this.worldObj, x, y, z)) - { - continue; - } - - int newMeta = meta; - - for (int i = 0; i < -deltarotation; i++) { - newMeta = ShipMod.instance.metaRotations.rotate90Reverse(id, newMeta); - } - - if (id == 1225) { - // Rotate computer - for (int i = 0; i < -deltarotation; i++) { - newMeta = ShipMod.instance.metaRotations.rotateComputer90Reverse(newMeta); - } - } else if (id == 1226) { // Rotate peripherals (Disk drive, printer, modem, monitors) - NBTTagCompound NBT = new NBTTagCompound(); - tileentity.writeToNBT(NBT); - int oldDir = NBT.getInteger("dir"); - int newDir = oldDir; - int subType = ShipMod.instance.metaRotations.getCCSubtypeFromMetadata(meta); - - - if (subType == 0) { // Disk drive - for (int i = 0; i < -deltarotation; i++) { - newMeta = ShipMod.instance.metaRotations.rotateCCBlock90Reverse(newMeta); - } - } else if (subType == 1) { // Modems - /*System.out.println("Delta: " + deltarotation); - System.out.println("Old dir: " + oldDir); - System.out.println("Old meta: " + meta); - System.out.println("Rot from meta: " + ShipMod.instance.metaRotations.getCCDirectionFromMetadata(meta)); - */ - newMeta = ShipMod.instance.metaRotations.getCCDirectionFromMetadata(meta); - - for (int i = 0; i < -deltarotation; i++) { - newMeta = ShipMod.instance.metaRotations.rotateCCBlock90Reverse(newMeta); - newDir = ShipMod.instance.metaRotations.rotateCCBlock90Reverse(newDir); - } - - if (newDir >= 2) { - newMeta = 4 + newMeta; - } - //System.out.println("newDir: " + newDir); - NBT.setInteger("dir", newDir); - tileentity.readFromNBT(NBT); - //System.out.println("New meta: " + newMeta); - } else { // Printer, monitors - //System.out.println("Delta: " + deltarotation); - //System.out.println("Old dir: " + oldDir); - - // Rotate peripheral - for (int i = 0; i < -deltarotation; i++) { - newDir = ShipMod.instance.metaRotations.rotateCCBlock90Reverse(newDir); - } - - NBT.setInteger("dir", newDir); - tileentity.readFromNBT(NBT); - - //System.out.println("New dir: " + newDir); - } - } else if (id == 1229) { - int subType = meta >= 0 && meta < 6 ? 1 : (meta >= 6 && meta < 12 ? 2 : 0); - int dir = meta % 6; - /* - System.out.println("Old meta: " + meta); - System.out.println("Subtype: " + subType); - System.out.println("Dir: " + dir); - */ - if (subType == 1 || subType == 2) { - //System.out.println("Found wired modem"); - for (int i = 0; i < -deltarotation; i++) { - newMeta = ShipMod.instance.metaRotations.rotateCCBlock90Reverse(newMeta); - } - - newMeta += 6 * (subType - 1); - - //System.out.println("New meta: " + newMeta); - } - } - - if (newMeta == meta) { - newMeta = ShipMod.instance.metaRotations.getRotatedMeta(id, newMeta, deltarotation); - } - - // Rotate specific machines - if (ShipMod.instance.metaRotations.examForIC2Machine(tileentity)) { - short newFacing, oldFacing; - NBTTagCompound NBT = new NBTTagCompound(); - tileentity.writeToNBT(NBT); - oldFacing = NBT.getShort("facing"); - newFacing = oldFacing; - for (int i = 0; i < -deltarotation; i++) { - newFacing = ShipMod.instance.metaRotations.rotateIC2MachineFacing90Reverse(newFacing); - } - NBT.setShort("facing", newFacing); - tileentity.readFromNBT(NBT); - - // Updating via network - try { - NetworkHelper.updateTileEntityField(tileentity, "facing"); - } catch (Exception e) { - e.printStackTrace(); - } - IC2MachinesToUpdateFacing.add(tileentity); - } else - if (ShipMod.instance.metaRotations.examForAEMachine(tileentity)) { - int newFacing, oldFacing; - NBTTagCompound NBT = new NBTTagCompound(); - tileentity.writeToNBT(NBT); - String tagName = "unknown"; - // Select tag name - if (NBT.getTag("r") != null) - tagName = "r"; - else if (NBT.getTag("rot") != null) - tagName = "rot"; - else if (NBT.getTag("ori") != null) - tagName = "ori"; - - if (tagName != "unknown") { - boolean isCableOrBus = (tagName == "ori"); - - if (!isCableOrBus) { - oldFacing = NBT.getInteger(tagName); - } else - oldFacing = NBT.getByte(tagName); - - System.out.println(((isCableOrBus) ? "[cable|bus] " : "") + tagName + ": " + oldFacing); - newFacing = oldFacing; - - if (!isCableOrBus) { - for (int i = 0; i < -deltarotation; i++) { - newFacing = ShipMod.instance.metaRotations.rotateAEMachineFacing90Reverse(newFacing); - } - } else { - for (int i = 0; i < -deltarotation; i++) { - newFacing = ShipMod.instance.metaRotations.rotateAECableFacing90Reverse(newFacing); - } - } - - if (tagName != "ori") { - NBT.setInteger(tagName, newFacing); - } else - NBT.setByte(tagName, (byte)newFacing); - - tileentity.readFromNBT(NBT); - } - } - - //meta = ShipMod.instance.metaRotations.getRotatedMeta(id, meta, deltarotation); - vec.xCoord = (double)((float)x + ox); - vec.yCoord = (double)((float)y + oy); - vec.zCoord = (double)((float)z + oz); - vec.rotateAroundY(yaw); - int ix = MathHelperMod.round_double(vec.xCoord + this.posX); - int iy = MathHelperMod.round_double(vec.yCoord + this.posY); - int iz = MathHelperMod.round_double(vec.zCoord + this.posZ); - this.worldObj.setBlock(ix, iy, iz, id, newMeta, 2); - - if (explosionFlag && worldObj.rand.nextInt(30) == 0) { - explosions.add(new ChunkCoordinates(ix, iy, iz)); - } - - if (id != this.worldObj.getBlockId(ix, iy, iz)) - { - list.add(new LocatedBlock(id, newMeta, new ChunkPosition(ix, iy, iz))); - } - else - { - if (newMeta != this.worldObj.getBlockMetadata(ix, iy, iz)) - { - this.worldObj.setBlockMetadataWithNotify(ix, iy, iz, newMeta, 2); - } - - if (tileentity != null) - { - this.worldObj.setBlockTileEntity(ix, iy, iz, tileentity); - tileentity.blockMetadata = newMeta; - } - } - } - } - } - - this.worldObj.getGameRules().setOrCreateGameRule("doTileDrops", String.valueOf(flag)); - Iterator var20 = list.iterator(); - - while (var20.hasNext()) - { - LocatedBlock var21 = (LocatedBlock)var20.next(); - ShipMod.modLogger.finest("Post-rejoining block: " + var21.toString()); - this.worldObj.setBlock(var21.coords.x, var21.coords.y, var21.coords.z, var21.blockID, var21.blockMeta, 2); - } - - worldObj.isRemote = false; - this.setDead(); - - for (TileEntity machine : IC2MachinesToUpdateFacing) { - try { - NetworkHelper.updateTileEntityField(machine, "facing"); - } catch (Exception e) { - e.printStackTrace(); - } - } - - for (ChunkCoordinates e : explosions) { - worldObj.newExplosion(null, e.posX, e.posY, e.posZ, 4F, true, true); - } - - explosionFlag = false; - } - - return true; - } - } - - public void dropAsItems() - { - for (int i = this.shipChunk.minX(); i < this.shipChunk.maxX(); ++i) - { - for (int j = this.shipChunk.minY(); j < this.shipChunk.maxY(); ++j) - { - for (int k = this.shipChunk.minZ(); k < this.shipChunk.maxZ(); ++k) - { - this.shipChunk.getBlockTileEntity(i, j, k); - int id = this.shipChunk.getBlockId(i, j, k); - - if (id != 0 && Block.blocksList[id] != null && (worldObj.rand.nextBoolean())) - { - int meta = this.shipChunk.getBlockMetadata(i, j, k); - Block.blocksList[id].dropBlockAsItem(this.worldObj, i, j, k, meta, 0); - this.shipChunk.setBlockAsFilledAir(i, j, k); - this.shipChunk.setChunkModified(); - } - } - } - } - } - - private void fillAirBlocks(Set<ChunkPosition> set, int x, int y, int z) - { - if (x >= this.shipChunk.minX() - 1 && x <= this.shipChunk.maxX() && y >= this.shipChunk.minY() - 1 && y <= this.shipChunk.maxY() && z >= this.shipChunk.minZ() - 1 && z <= this.shipChunk.maxZ()) - { - ChunkPosition pos = new ChunkPosition(x, y, z); - - if (!set.contains(pos)) - { - set.add(pos); - - if (this.shipChunk.setBlockAsFilledAir(x, y, z)) - { - this.fillAirBlocks(set, x, y + 1, z); - this.fillAirBlocks(set, x - 1, y, z); - this.fillAirBlocks(set, x, y, z - 1); - this.fillAirBlocks(set, x + 1, y, z); - this.fillAirBlocks(set, x, y, z + 1); - } - } - } - } - - /** - * Called when the mob is falling. Calculates and applies fall damage. - */ - protected void fall(float distance) {} - - /** - * (abstract) Protected helper method to write subclass entity data to NBT. - */ - @Override - protected void writeEntityToNBT(NBTTagCompound compound) - { - super.writeEntityToNBT(compound); - ByteArrayOutputStream baos = new ByteArrayOutputStream(this.shipChunk.getMemoryUsage()); - DataOutputStream out = new DataOutputStream(baos); - - try - { - this.shipChunk.writeChunkData(out); - out.flush(); - out.close(); - } - catch (IOException var8) - { - var8.printStackTrace(); - } - - compound.setByteArray("chunk", baos.toByteArray()); - compound.setByte("seatX", (byte)this.seatX); - compound.setByte("seatY", (byte)this.seatY); - compound.setByte("seatZ", (byte)this.seatZ); - compound.setByte("front", (byte)this.frontDirection); - - if (!this.shipChunk.chunkTileEntityMap.isEmpty()) - { - NBTTagList tileentities = new NBTTagList(); - Iterator i$ = this.shipChunk.chunkTileEntityMap.values().iterator(); - - while (i$.hasNext()) - { - TileEntity tileentity = (TileEntity)i$.next(); - NBTTagCompound comp = new NBTTagCompound(); - tileentity.writeToNBT(comp); - tileentities.appendTag(comp); - } - - compound.setTag("tileent", tileentities); - } - } - - /** - * (abstract) Protected helper method to read subclass entity data from NBT. - */ - @Override - protected void readEntityFromNBT(NBTTagCompound compound) - { - super.readEntityFromNBT(compound); - byte[] ab = compound.getByteArray("chunk"); - ByteArrayInputStream bais = new ByteArrayInputStream(ab); - DataInputStream in = new DataInputStream(bais); - - try - { - this.shipChunk.readChunkData(in); - in.close(); - } - catch (IOException var9) - { - var9.printStackTrace(); - } - - if (compound.hasKey("seat")) - { - short tileentities = compound.getShort("seat"); - this.seatX = tileentities & 15; - this.seatY = tileentities >>> 4 & 15; - this.seatZ = tileentities >>> 8 & 15; - this.frontDirection = tileentities >>> 12 & 3; - } - else - { - this.seatX = compound.getByte("seatX"); - this.seatY = compound.getByte("seatZ"); - this.seatZ = compound.getByte("seatZ"); - this.frontDirection = compound.getByte("front"); - } - - NBTTagList var10 = compound.getTagList("tileent"); - - if (var10 != null) - { - for (int i = 0; i < var10.tagCount(); ++i) - { - NBTTagCompound comp = (NBTTagCompound)var10.tagAt(i); - TileEntity tileentity = TileEntity.createAndLoadEntity(comp); - this.shipChunk.setBlockTileEntity(tileentity.xCoord, tileentity.yCoord, tileentity.zCoord, tileentity); - } - } - } - - @Override - public void writeSpawnData(ByteArrayDataOutput out) - { - out.writeByte(this.seatX); - out.writeByte(this.seatY); - out.writeByte(this.seatZ); - out.writeByte(this.frontDirection); - - try - { - this.shipChunk.writeChunkData(out); - } - catch (IOException var3) - { - var3.printStackTrace(); - } - } - - @Override - public void readSpawnData(ByteArrayDataInput in) - { - this.seatX = in.readByte(); - this.seatY = in.readByte(); - this.seatZ = in.readByte(); - this.frontDirection = in.readByte(); - - try - { - this.shipChunk.readChunkData(in); - } - catch (IOException var3) - { - var3.printStackTrace(); - } - } -} diff --git a/src/shipmod/entity/IShipTileEntity.java b/src/shipmod/entity/IShipTileEntity.java deleted file mode 100644 index a4825ffd..00000000 --- a/src/shipmod/entity/IShipTileEntity.java +++ /dev/null @@ -1,6 +0,0 @@ -package shipmod.entity; - -public interface IShipTileEntity -{ - void setVehicle(EntityShip var1); -} diff --git a/src/shipmod/entity/ShipCapabilities.java b/src/shipmod/entity/ShipCapabilities.java deleted file mode 100644 index b4f65faa..00000000 --- a/src/shipmod/entity/ShipCapabilities.java +++ /dev/null @@ -1,42 +0,0 @@ -package shipmod.entity; - -import net.minecraft.block.Block; -import shipmod.ShipMod; - -public class ShipCapabilities -{ - public float speedMultiplier = 1.0F; - public float rotationMultiplier = 1.0F; - public float liftMultiplier = 1.0F; - public float brakeMult = 0.9F; - private int balloons = 0; - private int floaters = 0; - private int blockCount = 0; - private float mass = 0.0F; - private boolean hasSigns = false; - - public boolean canFly() - { - return true; - } - - public float getMass() - { - return this.mass; - } - - public boolean hasSigns() - { - return this.hasSigns; - } - - protected void onChunkBlockAdded(int id, int metadata) - { - if (id == Block.signPost.blockID || id == Block.signWall.blockID) - { - this.hasSigns = true; - } - - ++this.blockCount; - } -} diff --git a/src/shipmod/render/MobileChunkRenderer.java b/src/shipmod/render/MobileChunkRenderer.java deleted file mode 100644 index 8573b62e..00000000 --- a/src/shipmod/render/MobileChunkRenderer.java +++ /dev/null @@ -1,254 +0,0 @@ -package shipmod.render; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.logging.Level; -import net.minecraft.block.Block; -import net.minecraft.client.renderer.GLAllocation; -import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.client.renderer.RenderBlocks; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.tileentity.TileEntityRenderer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.AxisAlignedBB; -import net.minecraft.world.chunk.Chunk; -import org.lwjgl.opengl.GL11; -import shipmod.ShipMod; -import shipmod.chunk.MobileChunk; - -public class MobileChunkRenderer -{ - private MobileChunk chunk; - private RenderBlocks blockRenderer; - private int glRenderList = -1; - public boolean isInFrustum = false; - public boolean[] skipRenderPass = new boolean[2]; - public boolean needsUpdate; - public boolean isRemoved; - public AxisAlignedBB rendererBoundingBox; - private boolean isInitialized = false; - private List<TileEntity> tileEntityRenderers = new ArrayList(); - public List<TileEntity> tileEntities; - private int bytesDrawn; - - public MobileChunkRenderer(MobileChunk vehiclechunk) - { - this.chunk = vehiclechunk; - this.needsUpdate = true; - this.tileEntities = new ArrayList(); - } - - public void render(float partialticks) - { - if (this.isRemoved) - { - if (this.glRenderList != -1) - { - GLAllocation.deleteDisplayLists(this.glRenderList); - this.glRenderList = -1; - } - } - else - { - if (this.needsUpdate) - { - try - { - this.updateRender(); - } - catch (Exception var7) - { - ShipMod.modLogger.log(Level.SEVERE, "A mobile chunk render error has occured", var7); - } - } - - if (this.glRenderList != -1) - { - for (int pass = 0; pass < 2; ++pass) - { - GL11.glCallList(this.glRenderList + pass); - RenderHelper.enableStandardItemLighting(); - Iterator it = this.tileEntityRenderers.iterator(); - - while (it.hasNext()) - { - TileEntity tile = (TileEntity)it.next(); - - try - { - if (tile.shouldRenderInPass(pass)) - { - this.renderTileEntity(tile, partialticks); - } - } - catch (Exception var6) - { - it.remove(); - ShipMod.modLogger.log(Level.SEVERE, "A tile entity render error has occured", var6); - } - } - } - } - } - } - - public void renderTileEntity(TileEntity par1TileEntity, float partialticks) - { - try { - int i = this.chunk.getLightBrightnessForSkyBlocks(par1TileEntity.xCoord, par1TileEntity.yCoord, par1TileEntity.zCoord, 0); - int j = i % 65536; - int k = i / 65536; - OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)j / 1.0F, (float)k / 1.0F); - GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); - - TileEntityRenderer.instance.renderTileEntityAt(par1TileEntity, (double)par1TileEntity.xCoord, (double)par1TileEntity.yCoord, (double)par1TileEntity.zCoord, partialticks); - } catch (Exception e) { - if (Tessellator.instance.isDrawing) { - Tessellator.instance.draw(); - } - } - } - - private void updateRender() - { - if (this.glRenderList == -1) - { - this.glRenderList = GLAllocation.generateDisplayLists(2); - } - - this.needsUpdate = false; - - for (int hashset0 = 0; hashset0 < 2; ++hashset0) - { - this.skipRenderPass[hashset0] = true; - } - - Chunk.isLit = false; - HashSet var14 = new HashSet(); - var14.addAll(this.tileEntityRenderers); - this.tileEntityRenderers.clear(); - boolean b0 = true; - RenderBlocks renderblocks = new RenderBlocks(this.chunk); - this.bytesDrawn = 0; - - for (int hashset1 = 0; hashset1 < 2; ++hashset1) - { - boolean flag = false; - boolean flag1 = false; - boolean isDrawStarted = false; - - for (int y = this.chunk.minY(); y < this.chunk.maxY(); ++y) - { - for (int z = this.chunk.minZ(); z < this.chunk.maxZ(); ++z) - { - for (int x = this.chunk.minX(); x < this.chunk.maxX(); ++x) - { - int l2 = this.chunk.getBlockId(x, y, z); - - if (l2 > 0) - { - if (!isDrawStarted) - { - isDrawStarted = true; - GL11.glNewList(this.glRenderList + hashset1, GL11.GL_COMPILE); - GL11.glPushMatrix(); - float block = 1.000001F; - GL11.glTranslatef(-8.0F, -8.0F, -8.0F); - GL11.glScalef(block, block, block); - GL11.glTranslatef(8.0F, 8.0F, 8.0F); - Tessellator.instance.startDrawingQuads(); - } - - Block var16 = Block.blocksList[l2]; - - if (var16 != null) - { - if (hashset1 == 0 && var16.hasTileEntity(this.chunk.getBlockMetadata(x, y, z))) - { - TileEntity blockpass = this.chunk.getBlockTileEntity(x, y, z); - - if (TileEntityRenderer.instance.hasSpecialRenderer(blockpass)) - { - this.tileEntityRenderers.add(blockpass); - } - } - - int var17 = var16.getRenderBlockPass(); - if (var17 > hashset1) - { - flag = true; - } - - try { - if (var16.canRenderInPass(hashset1)) - { - flag1 |= renderblocks.renderBlockByRenderType(var16, x, y, z); - } - } catch (Exception e) { - flag1 = false; - } - } - } - } - } - } - - if (isDrawStarted) - { - this.bytesDrawn += Tessellator.instance.draw(); - GL11.glPopMatrix(); - GL11.glEndList(); - Tessellator.instance.setTranslation(0.0D, 0.0D, 0.0D); - } - else - { - flag1 = false; - } - - if (flag1) - { - this.skipRenderPass[hashset1] = false; - } - - if (!flag) - { - break; - } - } - - HashSet var15 = new HashSet(); - var15.addAll(this.tileEntityRenderers); - var15.removeAll(var14); - this.tileEntities.addAll(var15); - var14.removeAll(this.tileEntityRenderers); - this.tileEntities.removeAll(var14); - this.isInitialized = true; - } - - public void markDirty() - { - this.needsUpdate = true; - } - - public void markRemoved() - { - this.isRemoved = true; - - try - { - if (this.glRenderList != -1) - { - ShipMod.modLogger.finest("Deleting mobile chunk display list " + this.glRenderList); - GLAllocation.deleteDisplayLists(this.glRenderList); - this.glRenderList = -1; - } - } - catch (Exception var2) - { - ShipMod.modLogger.log(Level.SEVERE, "Failed to destroy mobile chunk display list", var2); - } - } -} diff --git a/src/shipmod/render/RenderShip.java b/src/shipmod/render/RenderShip.java deleted file mode 100644 index 0c6ef0e4..00000000 --- a/src/shipmod/render/RenderShip.java +++ /dev/null @@ -1,50 +0,0 @@ -package shipmod.render; - -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.entity.Render; -import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.entity.Entity; -import net.minecraft.util.ResourceLocation; -import org.lwjgl.opengl.GL11; -import shipmod.entity.EntityShip; - -public class RenderShip extends Render -{ - public RenderShip() - { - this.shadowSize = 1.0F; - } - - public void renderVehicle(EntityShip entity, double x, double y, double z, float yaw, float pitch) - { - GL11.glPushAttrib(8256); - RenderHelper.disableStandardItemLighting(); - GL11.glPushMatrix(); - GL11.glTranslatef((float)x, (float)y, (float)z); - GL11.glRotatef(yaw, 0.0F, 1.0F, 0.0F); - float fx = entity.getShipChunk().getCenterX(); - float fz = entity.getShipChunk().getCenterZ(); - GL11.glTranslatef(-fx, (float)(-entity.getShipChunk().minY()), -fz); - float f4 = 0.75F; - this.func_110777_b(entity); - entity.getShipChunk().renderer.render(0.0F); - GL11.glPopMatrix(); - GL11.glPopAttrib(); - } - - /** - * Actually renders the given argument. This is a synthetic bridge method, always casting down its argument and then - * handing it off to a worker function which does the actual work. In all probabilty, the class Render is generic - * (Render<T extends Entity) and this method has signature public void doRender(T entity, double d, double d1, - * double d2, float f, float f1). But JAD is pre 1.5 so doesn't do that. - */ - public void doRender(Entity entity, double x, double y, double z, float yaw, float pitch) - { - this.renderVehicle((EntityShip)entity, x, y, z, yaw, pitch); - } - - protected ResourceLocation func_110775_a(Entity entity) - { - return TextureMap.field_110575_b; - } -} diff --git a/src/shipmod/util/AABBRotator.java b/src/shipmod/util/AABBRotator.java deleted file mode 100644 index b5a1e550..00000000 --- a/src/shipmod/util/AABBRotator.java +++ /dev/null @@ -1,51 +0,0 @@ -package shipmod.util; - -import net.minecraft.util.AxisAlignedBB; -import net.minecraft.util.Vec3; - -public class AABBRotator -{ - private static Vec3 vec00 = Vec3.createVectorHelper(0.0D, 0.0D, 0.0D); - private static Vec3 vec01 = Vec3.createVectorHelper(0.0D, 0.0D, 0.0D); - private static Vec3 vec10 = Vec3.createVectorHelper(0.0D, 0.0D, 0.0D); - private static Vec3 vec11 = Vec3.createVectorHelper(0.0D, 0.0D, 0.0D); - - public static void rotateAABBAroundY(AxisAlignedBB aabb, double xoff, double zoff, float ang) - { - double y0 = aabb.minY; - double y1 = aabb.maxY; - vec00.xCoord = aabb.minX - xoff; - vec00.zCoord = aabb.minZ - zoff; - vec01.xCoord = aabb.minX - xoff; - vec01.zCoord = aabb.maxZ - zoff; - vec10.xCoord = aabb.maxX - xoff; - vec10.zCoord = aabb.minZ - zoff; - vec11.xCoord = aabb.maxX - xoff; - vec11.zCoord = aabb.maxZ - zoff; - vec00.rotateAroundY(ang); - vec01.rotateAroundY(ang); - vec10.rotateAroundY(ang); - vec11.rotateAroundY(ang); - aabb.setBounds(minX(), y0, minZ(), maxX(), y1, maxZ()).offset(xoff, 0.0D, zoff); - } - - private static double minX() - { - return Math.min(Math.min(Math.min(vec00.xCoord, vec01.xCoord), vec10.xCoord), vec11.xCoord); - } - - private static double minZ() - { - return Math.min(Math.min(Math.min(vec00.zCoord, vec01.zCoord), vec10.zCoord), vec11.zCoord); - } - - private static double maxX() - { - return Math.max(Math.max(Math.max(vec00.xCoord, vec01.xCoord), vec10.xCoord), vec11.xCoord); - } - - private static double maxZ() - { - return Math.max(Math.max(Math.max(vec00.zCoord, vec01.zCoord), vec10.zCoord), vec11.zCoord); - } -} diff --git a/src/shipmod/util/MathHelperMod.java b/src/shipmod/util/MathHelperMod.java deleted file mode 100644 index 514cd97d..00000000 --- a/src/shipmod/util/MathHelperMod.java +++ /dev/null @@ -1,16 +0,0 @@ -package shipmod.util; - -import net.minecraft.util.MathHelper; - -public class MathHelperMod extends MathHelper -{ - public static double clamp_double(double d, double lowerbound, double upperbound) - { - return d < lowerbound ? lowerbound : (d > upperbound ? upperbound : d); - } - - public static int round_double(double d) - { - return (int)Math.round(d); - } -} diff --git a/src/shipmod/util/StackSafeFiller.java b/src/shipmod/util/StackSafeFiller.java deleted file mode 100644 index 0045236c..00000000 --- a/src/shipmod/util/StackSafeFiller.java +++ /dev/null @@ -1,37 +0,0 @@ -package shipmod.util; - -import java.util.HashSet; -import java.util.Set; -import net.minecraft.world.ChunkPosition; - -public class StackSafeFiller -{ - private Set<ChunkPosition> filledCoords = new HashSet(); - private ChunkPosition nextPos = null; - - public void fill(int x, int y, int z) - { - if (!this.hasNext()) - { - ChunkPosition pos = new ChunkPosition(x, y, z); - - if (!this.filledCoords.contains(pos)) - { - this.nextPos = pos; - this.filledCoords.add(pos); - } - } - } - - public ChunkPosition next() - { - ChunkPosition pos = this.nextPos; - this.nextPos = null; - return pos; - } - - public boolean hasNext() - { - return this.nextPos != null; - } -} From 661de6ae375d6cf42938e2e548cc8895e7136139 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Wed, 20 Nov 2013 01:53:50 +0400 Subject: [PATCH 03/56] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=BA=D0=B0=20=D1=88=D0=B0=D1=85=D1=82=D0=B5=D1=80=D0=BB?= =?UTF-8?q?=D0=B0=D0=B7=D0=BE=D1=80=D0=BE=D0=B2=20=D0=9D=D0=BE=D0=B2=D1=8B?= =?UTF-8?q?=D0=B9=20=D0=BA=D0=BE=D0=B4=20=D0=BA=D0=BE=D0=BF=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F,=20=D0=B8=D0=BD=D1=82=D0=B5=D0=B3=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=90=D0=95,=20=D0=BC=D0=BE=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE=20=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B0=D1=82?= =?UTF-8?q?=D1=8C=20=D0=90=D0=95=20=D0=BF=D1=80=D0=BE=D0=B2=D0=BE=D0=B4?= =?UTF-8?q?=D0=B0=D0=BC=D0=B8,=20=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=20=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=B2=D0=B8=D1=82=D1=8C=20=D0=B2=D0=BF=D0=BB=D0=BE?= =?UTF-8?q?=D1=82=D0=BD=D1=83=D1=8E=20=D0=BA=20=D0=B4=D1=80=D1=83=D0=B3?= =?UTF-8?q?=D0=B8=D0=BC=20=D0=90=D0=95=20=D0=BC=D0=B0=D1=88=D0=B8=D0=BD?= =?UTF-8?q?=D0=B0=D0=BC,=20=D0=B0=20=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D1=82=D1=8C=20=D1=81?= =?UTF-8?q?=D1=83=D0=BD=D0=B4=D1=83=D0=BA,=20=D0=BA=D0=B0=D0=BA=20=D0=B1?= =?UTF-8?q?=D1=8B=D0=BB=D0=BE=20=D1=80=D0=B0=D0=BD=D1=8C=D1=88=D0=B5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 1356 +++++++++-------- 1 file changed, 700 insertions(+), 656 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index 6f958507..c6dae0dd 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -30,662 +30,706 @@ import net.minecraft.util.MovingObjectPosition; import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.WorldCoord; +import appeng.api.IAEItemStack; +import appeng.api.Util; +import appeng.api.events.GridTileLoadEvent; +import appeng.api.events.GridTileUnloadEvent; +import appeng.api.me.tiles.IGridMachine; +import appeng.api.me.tiles.ITileCable; +import appeng.api.me.util.IGridInterface; +import appeng.api.me.util.IMEInventoryHandler; -public class TileEntityMiningLaser extends TileEntity implements IPeripheral + +public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IGridMachine, ITileCable { - private final int MAX_BOOSTERS_NUMBER = 1; - - private int dx, dz, dy; - private boolean isMining = false; - private boolean isQuarry = false; - - private String[] methodsArray = - { - "startMining", "stop", // 0, 1 - "isMining", // 2 - "startQuarry", // 3 - "getMinerState", // 4 - "setStartLayerOffset" // 5 - }; - - public static final ArrayList<Integer> valuableOres = new ArrayList<Integer>(Arrays.asList( - Block.oreIron.blockID, - Block.oreGold.blockID, - Block.oreCoal.blockID, - Block.oreEmerald.blockID, - Block.oreLapis.blockID, - Block.oreRedstoneGlowing.blockID, - Block.oreRedstone.blockID, - Block.oreNetherQuartz.blockID, - Items.getItem("uraniumOre").itemID, // IC - Items.getItem("copperOre").itemID, // IC - Items.getItem("tinOre").itemID, // IC - 4095 // AS uranus - )); - - public static final ArrayList<Integer> otherValuables = new ArrayList<Integer>(Arrays.asList( - Block.wood.blockID, - Block.planks.blockID, - Items.getItem("rubberWood").itemID, - Block.rail.blockID, - 902, // Quarz (AE), - Block.oreDiamond.blockID, - Block.obsidian.blockID, - Block.web.blockID, - Block.fence.blockID, - Block.torchWood.blockID - )); - - private final int SCAN_DELAY = 20 * 5; - private int delayTicksScan = 0; - - private final int MINE_DELAY = 10; - private int delayTicksMine = 0; - - private final int EU_PER_LAYER_SPACE = 500; - private final int EU_PER_LAYER_EARTH = 5000; - - private int currentMode = 0; // 0 - scan next layer, 1 - collect valuables - - private int currentLayer; - - private ArrayList<Vector3> valuablesInLayer = new ArrayList<Vector3>(); - private int valuableIndex = 0; - - private int layerOffset = 1; - - private Vector3 minerVector; - //private long uid = 0; - - TileEntityParticleBooster booster = null; - - private final int MFFS_FIELD_BLOCKID = 1681; - - private boolean isOnEarth = false; - //int t = 20; - @Override - public void updateEntity() - { - /*if (uid == 0) { - uid = worldObj.rand.nextInt(99999); - } - if (--t == 0) { - t = 20; - System.out.println("[MINER] Ticked: " + uid + " | " + xCoord + "; " + yCoord + "; " + zCoord); - }*/ - isOnEarth = (worldObj.provider.dimensionId == 0); - - if (isMining) - { - if (minerVector != null) - { - minerVector.x = xCoord; - minerVector.y = yCoord - 1; - minerVector.z = zCoord; - minerVector = minerVector.add(0.5); - } - - if (currentMode == 0) - { - if (++delayTicksScan > SCAN_DELAY) - { - delayTicksScan = 0; - currentMode = 1; - - if (currentLayer <= 0) - { - isMining = false; - return; - } - - int blockID = worldObj.getBlockId(xCoord, currentLayer, zCoord); - int blockMeta = worldObj.getBlockMetadata(xCoord, currentLayer, zCoord); - - // That block is too hard - if (blockID == Block.bedrock.blockID || blockID == MFFS_FIELD_BLOCKID || !canDigDown()) - { - isMining = false; - return; - } - - if (blockID != 0 && worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && Block.blocksList[blockID].blockResistance > Block.obsidian.blockResistance) - { - isMining = false; - return; - } - - sendLaserPacket(minerVector, new Vector3(xCoord, currentLayer, zCoord).add(0.5), 0, 0, 1, 20, 0, 50); - worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); - harvestBlock(new Vector3(xCoord, currentLayer, zCoord)); - - if (collectEnergyPacketFromBooster((isOnEarth) ? EU_PER_LAYER_EARTH : EU_PER_LAYER_SPACE)) - { - scanLayer(); - } - else - { - isMining = false; - } - - currentLayer--; - } - } - else - { - if (++delayTicksMine > MINE_DELAY) - { - delayTicksMine = 0; - - if (valuableIndex < valuablesInLayer.size()) - { - //System.out.println("[ML] Mining: " + (valuableIndex + 1) + "/" + valuablesInLayer.size()); - Vector3 valuable = valuablesInLayer.get(valuableIndex++); - // Mine valuable ore - int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); - - // Skip if block is too hard or its empty block - if (worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && (worldObj.isAirBlock(valuable.intX(), valuable.intY(), valuable.intZ()) || Block.blocksList[blockID].blockResistance > Block.obsidian.blockResistance)) - { - return; - } - - sendLaserPacket(minerVector, new Vector3(valuable.intX(), valuable.intY(), valuable.intZ()).add(0.5), 1, 1, 0, 2 * MINE_DELAY, 0, 50); - worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F); - harvestBlock(valuable); - } - else - { - currentMode = 0; - } - } - } - } - } - - private boolean canDigDown() - { - for (int newY = yCoord - 1; newY > 0; newY--) - { - int blockID = worldObj.getBlockId(xCoord, newY, zCoord); - - if (!worldObj.isAirBlock(xCoord, newY, zCoord)) - { - if (blockID == MFFS_FIELD_BLOCKID || (blockID != Block.bedrock.blockID && Block.blocksList[blockID] != null && Block.blocksList[blockID].blockResistance > Block.obsidian.blockResistance)) - { - if (currentLayer > newY) - { - currentLayer = newY; - } - - return false; - } - } - } - - return true; - } - - private void harvestBlock(Vector3 valuable) - { - int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); - int blockMeta = worldObj.getBlockMetadata(valuable.intX(), valuable.intY(), valuable.intZ()); - - if (blockID != Block.waterMoving.blockID && blockID != Block.waterStill.blockID && blockID != Block.lavaMoving.blockID && blockID != Block.lavaStill.blockID) - { - List<ItemStack> stacks = getItemStackFromBlock(valuable.intX(), valuable.intY(), valuable.intZ(), blockID, blockMeta); - - if (stacks != null) - { - for (ItemStack stack : stacks) - { - putInChest(findChest(), stack); - } - } - - worldObj.playAuxSFXAtEntity(null, 2001, valuable.intX(), valuable.intY(), valuable.intZ(), blockID + (blockMeta << 12)); - // Evaporate water - } - else if (blockID == Block.waterMoving.blockID || blockID == Block.waterStill.blockID) - { - worldObj.playSoundEffect((double)((float)valuable.intX() + 0.5F), (double)((float)valuable.intY() + 0.5F), (double)((float)valuable.intZ() + 0.5F), "random.fizz", 0.5F, 2.6F + (worldObj.rand.nextFloat() - worldObj.rand.nextFloat()) * 0.8F); - } - - worldObj.setBlockToAir(valuable.intX(), valuable.intY(), valuable.intZ()); - } - - private IInventory findChest() - { - TileEntity result = null; - result = worldObj.getBlockTileEntity(xCoord + 1, yCoord, zCoord); - - if (result != null && result instanceof IInventory) - { - return (IInventory) result; - } - - result = worldObj.getBlockTileEntity(xCoord - 1, yCoord, zCoord); - - if (result != null && result instanceof IInventory) - { - return (IInventory) result; - } - - result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord + 1); - - if (result != null && result instanceof IInventory) - { - return (IInventory) result; - } - - result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord - 1); - - if (result != null && result instanceof IInventory) - { - return (IInventory) result; - } - - result = worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord); - - if (result != null && result instanceof IInventory) - { - return (IInventory) result; - } - - return null; - } - - public List<ItemStack> getItemStackFromBlock(int i, int j, int k, int blockID, int blockMeta) - { - Block block = Block.blocksList[blockID]; - - if (block == null) - { - return null; - } - - return block.getBlockDropped(worldObj, i, j, k, blockMeta, 0); - } - - public static int putInChest(IInventory inventory, ItemStack itemStackSource) - { - if (inventory == null || itemStackSource == null) - { - return 0; - } - - int transferred = 0; - - for (int i = 0; i < inventory.getSizeInventory(); i++) - { - if (!inventory.isItemValidForSlot(i, itemStackSource)) - { - continue; - } - - ItemStack itemStack = inventory.getStackInSlot(i); - - if (itemStack == null || !itemStack.isItemEqual(itemStackSource)) - { - continue; - } - - int transfer = Math.min(itemStackSource.stackSize - transferred, itemStack.getMaxStackSize() - itemStack.stackSize); - itemStack.stackSize += transfer; - transferred += transfer; - - if (transferred == itemStackSource.stackSize) - { - return transferred; - } - } - - for (int i = 0; i < inventory.getSizeInventory(); i++) - { - if (!inventory.isItemValidForSlot(i, itemStackSource)) - { - continue; - } - - ItemStack itemStack = inventory.getStackInSlot(i); - - if (itemStack != null) - { - continue; - } - - int transfer = Math.min(itemStackSource.stackSize - transferred, itemStackSource.getMaxStackSize()); - ItemStack dest = copyWithSize(itemStackSource, transfer); - inventory.setInventorySlotContents(i, dest); - transferred += transfer; - - if (transferred == itemStackSource.stackSize) - { - return transferred; - } - } - - return transferred; - } - - public static ItemStack copyWithSize(ItemStack itemStack, int newSize) - { - ItemStack ret = itemStack.copy(); - ret.stackSize = newSize; - return ret; - } - - private void scanLayer() - { - //System.out.println("Scanning layer"); - valuablesInLayer.clear(); - int xmax, zmax, x1, x2, z1, z2; - int xmin, zmin; - final int CUBE_SIDE = 8; - x1 = xCoord + CUBE_SIDE / 2; - x2 = xCoord - CUBE_SIDE / 2; - - if (x1 < x2) - { - xmin = x1; - xmax = x2; - } - else - { - xmin = x2; - xmax = x1; - } - - z1 = zCoord + CUBE_SIDE / 2; - z2 = zCoord - CUBE_SIDE / 2; - - if (z1 < z2) - { - zmin = z1; - zmax = z2; - } - else - { - zmin = z2; - zmax = z1; - } - - //System.out.println("Layer: xmax: " + xmax + ", xmin: " + xmin); - //System.out.println("Layer: zmax: " + zmax + ", zmin: " + zmin); - - // Search for valuable blocks - for (int x = xmin; x <= xmax; x++) - { - for (int z = zmin; z <= zmax; z++) - { - if (isQuarry) // Quarry collects all blocks - { - int blockID = worldObj.getBlockId(x, currentLayer, z); - - if (blockID == Block.bedrock.blockID || blockID == MFFS_FIELD_BLOCKID) - { - continue; - } - - if (!worldObj.isAirBlock(x, currentLayer, z) && blockID != Block.lavaMoving.blockID && blockID != Block.lavaStill.blockID && (Block.blocksList[blockID].blockResistance <= Block.obsidian.blockResistance)) - { - valuablesInLayer.add(new Vector3(x, currentLayer, z)); - } - } - else // Not-quarry collect only valuables blocks - if (valuableOres.contains((worldObj.getBlockId(x, currentLayer, z))) || otherValuables.contains((worldObj.getBlockId(x, currentLayer, z)))) - { - valuablesInLayer.add(new Vector3(x, currentLayer, z)); - } - } - } - - valuableIndex = 0; - //System.out.println("[ML] Found " + valuablesInLayer.size() + " valuables"); - } - private boolean collectEnergyPacketFromBooster(int packet) - { - int energyCollected = 0; - - if (booster == null) - { - booster = findFirstBooster(); - } - - if (booster != null) - { - return booster.consumeEnergy(packet); - } - - return false; - } - - private TileEntityParticleBooster findFirstBooster() - { - TileEntity result; - result = worldObj.getBlockTileEntity(xCoord + 1, yCoord, zCoord); - - if (result != null && result instanceof TileEntityParticleBooster) - { - dx = 1; - dz = 0; - dy = 0; - return (TileEntityParticleBooster) result; - } - - result = worldObj.getBlockTileEntity(xCoord - 1, yCoord, zCoord); - - if (result != null && result instanceof TileEntityParticleBooster) - { - dx = -1; - dz = 0; - dy = 0; - return (TileEntityParticleBooster) result; - } - - result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord + 1); - - if (result != null && result instanceof TileEntityParticleBooster) - { - dx = 0; - dz = 1; - dy = 0; - return (TileEntityParticleBooster) result; - } - - result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord - 1); - - if (result != null && result instanceof TileEntityParticleBooster) - { - dx = 0; - dz = -1; - dy = 0; - return (TileEntityParticleBooster) result; - } - - result = worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord); - - if (result != null && result instanceof TileEntityParticleBooster) - { - dx = 0; - dz = 0; - dy = 1; - return (TileEntityParticleBooster) result; - } - - return null; - } - - public void sendLaserPacket(Vector3 source, Vector3 dest, float r, float g, float b, int age, int energy, int radius) - { - Side side = FMLCommonHandler.instance().getEffectiveSide(); - - if (side == Side.SERVER) - { - if (source == null || dest == null || worldObj == null) - { - return; - } - - ByteArrayOutputStream bos = new ByteArrayOutputStream(8); - DataOutputStream outputStream = new DataOutputStream(bos); - - try - { - // Write source vector - outputStream.writeDouble(source.x); - outputStream.writeDouble(source.y); - outputStream.writeDouble(source.z); - // Write target vector - outputStream.writeDouble(dest.x); - outputStream.writeDouble(dest.y); - outputStream.writeDouble(dest.z); - // Write r, g, b of laser - outputStream.writeFloat(r); - outputStream.writeFloat(g); - outputStream.writeFloat(b); - // Write age - outputStream.writeByte(age); - // Write energy value - outputStream.writeInt(0); - } - catch (Exception ex) - { - ex.printStackTrace(); - } - - Packet250CustomPayload packet = new Packet250CustomPayload(); - packet.channel = "WarpDriveBeam"; - packet.data = bos.toByteArray(); - packet.length = bos.size(); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(source.intX(), source.intY(), source.intZ(), radius, worldObj.provider.dimensionId, packet); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(dest.intX(), dest.intY(), dest.intZ(), radius, worldObj.provider.dimensionId, packet); - } - } - - @Override - public void readFromNBT(NBTTagCompound tag) - { - super.readFromNBT(tag); - isMining = tag.getBoolean("isMining"); - isQuarry = tag.getBoolean("isQuarry"); - currentLayer = tag.getInteger("currentLayer"); - minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); - } - - @Override - public void writeToNBT(NBTTagCompound tag) - { - super.writeToNBT(tag); - tag.setBoolean("isMining", isMining); - tag.setBoolean("isQuarry", isQuarry); - tag.setInteger("currentLayer", currentLayer); - } - - // IPeripheral methods implementation - @Override - public String getType() - { - return "mininglaser"; - } - - @Override - public String[] getMethodNames() - { - return methodsArray; - } - - @Override - public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception - { - switch (method) - { - case 0: // startMining() - isMining = true; - isQuarry = false; - delayTicksScan = 0; - currentMode = 0; - minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); - currentLayer = yCoord - layerOffset; - return new Object[] { 0 }; - - case 1: // stop() - isMining = false; - break; - - case 2: // isMining() - return new Boolean[] { isMining }; - case 3: // startQuarry() - if (isMining) - { - return new Object[] { -1 }; - } - - isMining = true; - isQuarry = true; - delayTicksScan = 0; - currentMode = 0; - minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); - currentLayer = yCoord - layerOffset; - return new Object[] { 0 }; - - // State is: state, energy, currentLayer, valuablesMined, valuablesInLayer = getMinerState() - case 4: // getMinerState() - int energy = 0; - - if (booster != null) - { - energy = booster.getCurrentEnergyValue(); - } - - String state = "not mining"; - Integer valuablesInLayer, valuablesMined; - - if (isMining) - { - valuablesInLayer = this.valuablesInLayer.size(); - valuablesMined = this.valuableIndex; - state = "mining" + ((isQuarry) ? " (quarry mode)" : ""); - - if (energy < 0) - { - state = "out of energy"; - } - - return new Object[] {state, energy, currentLayer, valuablesMined, valuablesInLayer}; - } - - return new Object[] {state, energy, currentLayer, 0, 0}; - - case 5: // setStartLayerOffset - if (arguments.length == 1) - { - int a = ((Double)arguments[0]).intValue(); - - if (a < 1) - { - a = 1; - } - - layerOffset = a; - } - } - - return new Object[] { 0 }; - } - - @Override - public boolean canAttachToSide(int side) - { - return true; - } - - @Override - public void attach(IComputerAccess computer) - { - } - - @Override - public void detach(IComputerAccess computer) - { - } + Boolean powerStatus = false; + private IGridInterface grid; + + private final int MAX_BOOSTERS_NUMBER = 1; + + private int dx, dz, dy; + private boolean isMining = false; + private boolean isQuarry = false; + + private String[] methodsArray = + { + "startMining", "stop", // 0, 1 + "isMining", // 2 + "startQuarry", // 3 + "getMinerState", // 4 + "setStartLayerOffset" // 5 + }; + + public static final ArrayList<Integer> valuableOres = new ArrayList<Integer>(Arrays.asList( + Block.oreIron.blockID, + Block.oreGold.blockID, + Block.oreCoal.blockID, + Block.oreEmerald.blockID, + Block.oreLapis.blockID, + Block.oreRedstoneGlowing.blockID, + Block.oreRedstone.blockID, + Block.oreNetherQuartz.blockID, + Items.getItem("uraniumOre").itemID, // IC + Items.getItem("copperOre").itemID, // IC + Items.getItem("tinOre").itemID, // IC + 4095 // AS uranus + )); + + public static final ArrayList<Integer> otherValuables = new ArrayList<Integer>(Arrays.asList( + Block.wood.blockID, + Block.planks.blockID, + Items.getItem("rubberWood").itemID, + Block.rail.blockID, + 902, // Quarz (AE), + Block.oreDiamond.blockID, + Block.obsidian.blockID, + Block.web.blockID, + Block.fence.blockID, + Block.torchWood.blockID + )); + + private final int SCAN_DELAY = 20 * 5; + private int delayTicksScan = 0; + + private final int MINE_DELAY = 10; + private int delayTicksMine = 0; + + private final int EU_PER_LAYER_SPACE = 500; + private final int EU_PER_LAYER_EARTH = 5000; + + private int currentMode = 0; // 0 - scan next layer, 1 - collect valuables + + private int currentLayer; + + private ArrayList<Vector3> valuablesInLayer = new ArrayList<Vector3>(); + private int valuableIndex = 0; + + private int layerOffset = 1; + + private Vector3 minerVector; + //private long uid = 0; + + TileEntityParticleBooster booster = null; + + private final int MFFS_FIELD_BLOCKID = 1681; + + private boolean isOnEarth = false; + //int t = 20; + @Override + public void updateEntity() + { + isOnEarth = (worldObj.provider.dimensionId == 0); + + if (isMining && powerStatus) + { + if (minerVector != null) + { + minerVector.x = xCoord; + minerVector.y = yCoord - 1; + minerVector.z = zCoord; + minerVector = minerVector.add(0.5); + } + + if (currentMode == 0) + { + if (++delayTicksScan > SCAN_DELAY) + { + delayTicksScan = 0; + currentMode = 1; + + if (currentLayer <= 0) + { + isMining = false; + return; + } + + int blockID = worldObj.getBlockId(xCoord, currentLayer, zCoord); + + if (blockID != 0 && worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && canDig(blockID)) + { + sendLaserPacket(minerVector, new Vector3(xCoord, currentLayer, zCoord).add(0.5), 0, 0, 1, 20, 0, 50); + worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); + harvestBlock(new Vector3(xCoord, currentLayer, zCoord)); + } + + if (collectEnergyPacketFromBooster(isOnEarth ? EU_PER_LAYER_EARTH : EU_PER_LAYER_SPACE)) + scanLayer(); + else + { + isMining = false; + return; + } + } + } + else + { + if (++delayTicksMine > MINE_DELAY) + { + delayTicksMine = 0; + + if (valuableIndex < valuablesInLayer.size()) + { + //System.out.println("[ML] Mining: " + (valuableIndex + 1) + "/" + valuablesInLayer.size()); + Vector3 valuable = valuablesInLayer.get(valuableIndex++); + // Mine valuable ore + int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); + + // Skip if block is too hard or its empty block + if (worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && (worldObj.isAirBlock(valuable.intX(), valuable.intY(), valuable.intZ()) || Block.blocksList[blockID].blockResistance > Block.obsidian.blockResistance)) + return; + + sendLaserPacket(minerVector, new Vector3(valuable.intX(), valuable.intY(), valuable.intZ()).add(0.5), 1, 1, 0, 2 * MINE_DELAY, 0, 50); + worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F); + harvestBlock(valuable); + } + else + { + currentMode = 0; + --currentLayer; + } + } + } + } + } + + + private boolean canDig(int blockID) + { + return (blockID != MFFS_FIELD_BLOCKID && blockID != Block.bedrock.blockID && Block.blocksList[blockID] != null && Block.blocksList[blockID].blockResistance <= Block.obsidian.blockResistance); + } + + private void harvestBlock(Vector3 valuable) + { + int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); + int blockMeta = worldObj.getBlockMetadata(valuable.intX(), valuable.intY(), valuable.intZ()); + + if (blockID != Block.waterMoving.blockID && blockID != Block.waterStill.blockID && blockID != Block.lavaMoving.blockID && blockID != Block.lavaStill.blockID) + { + List<ItemStack> stacks = getItemStackFromBlock(valuable.intX(), valuable.intY(), valuable.intZ(), blockID, blockMeta); + + if (stacks != null) + { + for (ItemStack stack : stacks) + { + if (grid != null) + putInGrid(stack); + else + putInChest(findChest(), stack); + } + } + + worldObj.playAuxSFXAtEntity(null, 2001, valuable.intX(), valuable.intY(), valuable.intZ(), blockID + (blockMeta << 12)); + // Evaporate water + } + else if (blockID == Block.waterMoving.blockID || blockID == Block.waterStill.blockID) + { + worldObj.playSoundEffect((double)((float)valuable.intX() + 0.5F), (double)((float)valuable.intY() + 0.5F), (double)((float)valuable.intZ() + 0.5F), "random.fizz", 0.5F, 2.6F + (worldObj.rand.nextFloat() - worldObj.rand.nextFloat()) * 0.8F); + } + + worldObj.setBlockToAir(valuable.intX(), valuable.intY(), valuable.intZ()); + } + + private IInventory findChest() + { + TileEntity result = null; + result = worldObj.getBlockTileEntity(xCoord + 1, yCoord, zCoord); + + if (result != null && result instanceof IInventory) + { + return (IInventory) result; + } + + result = worldObj.getBlockTileEntity(xCoord - 1, yCoord, zCoord); + + if (result != null && result instanceof IInventory) + { + return (IInventory) result; + } + + result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord + 1); + + if (result != null && result instanceof IInventory) + { + return (IInventory) result; + } + + result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord - 1); + + if (result != null && result instanceof IInventory) + { + return (IInventory) result; + } + + result = worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord); + + if (result != null && result instanceof IInventory) + { + return (IInventory) result; + } + + return null; + } + + public List<ItemStack> getItemStackFromBlock(int i, int j, int k, int blockID, int blockMeta) + { + Block block = Block.blocksList[blockID]; + + if (block == null) + { + return null; + } + + return block.getBlockDropped(worldObj, i, j, k, blockMeta, 0); + } + + public int putInGrid(ItemStack itemStackSource) + { + int transferred = itemStackSource.stackSize; + IMEInventoryHandler cellArray = grid.getCellArray(); + if (cellArray != null) + { + IAEItemStack ret = cellArray.addItems(Util.createItemStack(itemStackSource)); + if (ret != null) + transferred -= ret.getStackSize(); + } + return transferred; + } + + public int putInChest(IInventory inventory, ItemStack itemStackSource) + { + if (inventory == null || itemStackSource == null) + { + return 0; + } + + int transferred = 0; + + for (int i = 0; i < inventory.getSizeInventory(); i++) + { + if (!inventory.isItemValidForSlot(i, itemStackSource)) + { + continue; + } + + ItemStack itemStack = inventory.getStackInSlot(i); + + if (itemStack == null || !itemStack.isItemEqual(itemStackSource)) + { + continue; + } + + int transfer = Math.min(itemStackSource.stackSize - transferred, itemStack.getMaxStackSize() - itemStack.stackSize); + itemStack.stackSize += transfer; + transferred += transfer; + + if (transferred == itemStackSource.stackSize) + { + return transferred; + } + } + + for (int i = 0; i < inventory.getSizeInventory(); i++) + { + if (!inventory.isItemValidForSlot(i, itemStackSource)) + { + continue; + } + + ItemStack itemStack = inventory.getStackInSlot(i); + + if (itemStack != null) + { + continue; + } + + int transfer = Math.min(itemStackSource.stackSize - transferred, itemStackSource.getMaxStackSize()); + ItemStack dest = copyWithSize(itemStackSource, transfer); + inventory.setInventorySlotContents(i, dest); + transferred += transfer; + + if (transferred == itemStackSource.stackSize) + { + return transferred; + } + } + + return transferred; + } + + public ItemStack copyWithSize(ItemStack itemStack, int newSize) + { + ItemStack ret = itemStack.copy(); + ret.stackSize = newSize; + return ret; + } + + private void scanLayer() + { + //System.out.println("Scanning layer"); + valuablesInLayer.clear(); + int xmax, zmax, x1, x2, z1, z2; + int xmin, zmin; + final int CUBE_SIDE = 8; + x1 = xCoord + CUBE_SIDE / 2; + x2 = xCoord - CUBE_SIDE / 2; + + if (x1 < x2) + { + xmin = x1; + xmax = x2; + } + else + { + xmin = x2; + xmax = x1; + } + + z1 = zCoord + CUBE_SIDE / 2; + z2 = zCoord - CUBE_SIDE / 2; + + if (z1 < z2) + { + zmin = z1; + zmax = z2; + } + else + { + zmin = z2; + zmax = z1; + } + + //System.out.println("Layer: xmax: " + xmax + ", xmin: " + xmin); + //System.out.println("Layer: zmax: " + zmax + ", zmin: " + zmin); + + // Search for valuable blocks + for (int x = xmin; x <= xmax; x++) + for (int z = zmin; z <= zmax; z++) + { + int blockID = worldObj.getBlockId(x, currentLayer, z); + if (canDig(blockID)) + if (isQuarry) // Quarry collects all blocks + { + if (!worldObj.isAirBlock(x, currentLayer, z) && blockID != Block.lavaMoving.blockID && blockID != Block.lavaStill.blockID) + valuablesInLayer.add(new Vector3(x, currentLayer, z)); + } + else // Not-quarry collect only valuables blocks + if (valuableOres.contains((worldObj.getBlockId(x, currentLayer, z))) || otherValuables.contains((worldObj.getBlockId(x, currentLayer, z)))) + valuablesInLayer.add(new Vector3(x, currentLayer, z)); + } + + valuableIndex = 0; + //System.out.println("[ML] Found " + valuablesInLayer.size() + " valuables"); + } + private boolean collectEnergyPacketFromBooster(int packet) + { + int energyCollected = 0; + + if (booster == null) + { + booster = findFirstBooster(); + } + + if (booster != null) + { + return booster.consumeEnergy(packet); + } + + return false; + } + + private TileEntityParticleBooster findFirstBooster() + { + TileEntity result; + result = worldObj.getBlockTileEntity(xCoord + 1, yCoord, zCoord); + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = 1; + dz = 0; + dy = 0; + return (TileEntityParticleBooster) result; + } + + result = worldObj.getBlockTileEntity(xCoord - 1, yCoord, zCoord); + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = -1; + dz = 0; + dy = 0; + return (TileEntityParticleBooster) result; + } + + result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord + 1); + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = 0; + dz = 1; + dy = 0; + return (TileEntityParticleBooster) result; + } + + result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord - 1); + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = 0; + dz = -1; + dy = 0; + return (TileEntityParticleBooster) result; + } + + result = worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord); + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = 0; + dz = 0; + dy = 1; + return (TileEntityParticleBooster) result; + } + + return null; + } + + public void sendLaserPacket(Vector3 source, Vector3 dest, float r, float g, float b, int age, int energy, int radius) + { + Side side = FMLCommonHandler.instance().getEffectiveSide(); + + if (side == Side.SERVER) + { + if (source == null || dest == null || worldObj == null) + { + return; + } + + ByteArrayOutputStream bos = new ByteArrayOutputStream(8); + DataOutputStream outputStream = new DataOutputStream(bos); + + try + { + // Write source vector + outputStream.writeDouble(source.x); + outputStream.writeDouble(source.y); + outputStream.writeDouble(source.z); + // Write target vector + outputStream.writeDouble(dest.x); + outputStream.writeDouble(dest.y); + outputStream.writeDouble(dest.z); + // Write r, g, b of laser + outputStream.writeFloat(r); + outputStream.writeFloat(g); + outputStream.writeFloat(b); + // Write age + outputStream.writeByte(age); + // Write energy value + outputStream.writeInt(0); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + Packet250CustomPayload packet = new Packet250CustomPayload(); + packet.channel = "WarpDriveBeam"; + packet.data = bos.toByteArray(); + packet.length = bos.size(); + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(source.intX(), source.intY(), source.intZ(), radius, worldObj.provider.dimensionId, packet); + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(dest.intX(), dest.intY(), dest.intZ(), radius, worldObj.provider.dimensionId, packet); + } + } + + @Override + public void readFromNBT(NBTTagCompound tag) + { + super.readFromNBT(tag); + isMining = tag.getBoolean("isMining"); + isQuarry = tag.getBoolean("isQuarry"); + currentLayer = tag.getInteger("currentLayer"); + minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); + } + + @Override + public void writeToNBT(NBTTagCompound tag) + { + super.writeToNBT(tag); + tag.setBoolean("isMining", isMining); + tag.setBoolean("isQuarry", isQuarry); + tag.setInteger("currentLayer", currentLayer); + } +//CC + // IPeripheral methods implementation + @Override + public String getType() + { + return "mininglaser"; + } + + @Override + public String[] getMethodNames() + { + return methodsArray; + } + + @Override + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception + { + switch (method) + { + case 0: // startMining() + if (isMining) + return new Object[] { -1 }; + isQuarry = false; + delayTicksScan = 0; + currentMode = 0; + minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); + currentLayer = yCoord - layerOffset; + isMining = true; + return new Object[] { 0 }; + + case 1: // stop() + isMining = false; + break; + + case 2: // isMining() + return new Boolean[] { isMining }; + case 3: // startQuarry() + if (isMining) + return new Object[] { -1 }; + + isQuarry = true; + delayTicksScan = 0; + currentMode = 0; + minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); + currentLayer = yCoord - layerOffset; + isMining = true; + return new Object[] { 0 }; + + // State is: state, energy, currentLayer, valuablesMined, valuablesInLayer = getMinerState() + case 4: // getMinerState() + int energy = 0; + + if (booster != null) + { + energy = booster.getCurrentEnergyValue(); + } + + String state = "not mining"; + Integer valuablesInLayer, valuablesMined; + + if (isMining) + { + valuablesInLayer = this.valuablesInLayer.size(); + valuablesMined = this.valuableIndex; + state = "mining" + ((isQuarry) ? " (quarry mode)" : ""); + + if (energy < 0) + { + state = "out of energy"; + } + + return new Object[] {state, energy, currentLayer, valuablesMined, valuablesInLayer}; + } + + return new Object[] {state, energy, currentLayer, 0, 0}; + + case 5: // setStartLayerOffset + if (arguments.length == 1) + { + int a = ((Double)arguments[0]).intValue(); + if (a < 1) + a = 1; + layerOffset = a + 1; + } + } + + return new Object[] { 0 }; + } + + @Override + public boolean canAttachToSide(int side) + { + return true; + } + + @Override + public void attach(IComputerAccess computer) + { + } + + @Override + public void detach(IComputerAccess computer) + { + } +//AE + @Override + public float getPowerDrainPerTick() + { + return 1; + } + + @Override + public void validate() + { + super.validate(); + MinecraftForge.EVENT_BUS.post(new GridTileLoadEvent(this, worldObj, getLocation())); + } + + @Override + public void invalidate() + { + super.invalidate(); + MinecraftForge.EVENT_BUS.post(new GridTileUnloadEvent(this, worldObj, getLocation())); + } + + @Override + public WorldCoord getLocation() + { + return new WorldCoord(xCoord, yCoord, zCoord); + } + + @Override + public boolean isValid() + { + return true; + } + + @Override + public void setPowerStatus(boolean hasPower) + { + powerStatus = hasPower; + } + + @Override + public boolean isPowered() + { + return powerStatus; + } + + @Override + public IGridInterface getGrid() + { + return grid; + } + + @Override + public void setGrid(IGridInterface gi) + { + grid = gi; + } + + @Override + public World getWorld() + { + return worldObj; + } + + @Override + public boolean coveredConnections() + { + return true; + } } From b84ebcb426444364ba9bb520a07a8ead340c2a51 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Wed, 20 Nov 2013 23:45:43 +0400 Subject: [PATCH 04/56] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BC=D0=B5=D1=80=D1=82=D0=B2=D1=8B=D1=85=20=D1=8F=D0=B4=D0=B5?= =?UTF-8?q?=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cr0s/WarpDrive/WarpCoresRegistry.java | 333 +++++++++++----------- 1 file changed, 164 insertions(+), 169 deletions(-) diff --git a/src/cr0s/WarpDrive/WarpCoresRegistry.java b/src/cr0s/WarpDrive/WarpCoresRegistry.java index d84e33c2..62505d28 100644 --- a/src/cr0s/WarpDrive/WarpCoresRegistry.java +++ b/src/cr0s/WarpDrive/WarpCoresRegistry.java @@ -11,210 +11,205 @@ import net.minecraft.util.MathHelper; */ public class WarpCoresRegistry { - private ArrayList<TileEntityReactor> registry; + private ArrayList<TileEntityReactor> registry; - public WarpCoresRegistry() - { - registry = new ArrayList<TileEntityReactor>(); - } + public WarpCoresRegistry() + { + registry = new ArrayList<TileEntityReactor>(); + } - public int searchCoreInRegistry(TileEntityReactor core) - { - int res = -1; + public int searchCoreInRegistry(TileEntityReactor core) + { + int res = -1; - for (int i = 0; i < registry.size(); i++) - { - TileEntityReactor c = registry.get(i); + for (int i = 0; i < registry.size(); i++) + { + TileEntityReactor c = registry.get(i); - if (c.xCoord == core.xCoord && c.yCoord == core.yCoord && c.zCoord == core.zCoord) - { - return i; - } - } + if (c.xCoord == core.xCoord && c.yCoord == core.yCoord && c.zCoord == core.zCoord) + { + return i; + } + } - return res; - } + return res; + } - public boolean isCoreInRegistry(TileEntityReactor core) - { - return (searchCoreInRegistry(core) != -1); - } + public boolean isCoreInRegistry(TileEntityReactor core) + { + return (searchCoreInRegistry(core) != -1); + } - public void updateInRegistry(TileEntityReactor core) - { - int idx = searchCoreInRegistry(core); + public void updateInRegistry(TileEntityReactor core) + { + int idx = searchCoreInRegistry(core); - // update - if (idx != -1) - { - registry.set(idx, core); - } - else - { - registry.add(core); - } - } + // update + if (idx != -1) + { + registry.set(idx, core); + } + else + { + registry.add(core); + } + } - public void removeFromRegistry(TileEntityReactor core) - { - int idx; + public void removeFromRegistry(TileEntityReactor core) + { + int idx; - if ((idx = searchCoreInRegistry(core)) != -1) - { - registry.remove(idx); - } - } + if ((idx = searchCoreInRegistry(core)) != -1) + { + registry.remove(idx); + } + } - public ArrayList<TileEntityReactor> searchWarpCoresInRadius(int x, int y, int z, int radius) - { - ArrayList<TileEntityReactor> res = new ArrayList<TileEntityReactor>(); + public ArrayList<TileEntityReactor> searchWarpCoresInRadius(int x, int y, int z, int radius) + { + ArrayList<TileEntityReactor> res = new ArrayList<TileEntityReactor>(); - for (TileEntityReactor c : registry) - { - double d3 = c.xCoord - x; - double d4 = c.yCoord - y; - double d5 = c.zCoord - z; - double distance = MathHelper.sqrt_double(d3 * d3 + d4 * d4 + d5 * d5); + for (TileEntityReactor c : registry) + { + double d3 = c.xCoord - x; + double d4 = c.yCoord - y; + double d5 = c.zCoord - z; + double distance = MathHelper.sqrt_double(d3 * d3 + d4 * d4 + d5 * d5); - if (distance <= radius && !(c.controller == null || c.controller.getMode() == 0) && !isCoreHidden(c)) - { - res.add(c); - } - } + if (distance <= radius && !(c.controller == null || c.controller.getMode() == 0) && !isCoreHidden(c)) + { + res.add(c); + } + } - return res; - } + return res; + } - public void printRegistry() - { - System.out.println("WarpCores registry:"); - removeDeadCores(); + public void printRegistry() + { + System.out.println("WarpCores registry:"); + removeDeadCores(); - for (TileEntityReactor c : registry) - { - System.out.println(c.coreFrequency + " (" + c.xCoord + "; " + c.yCoord + "; " + c.zCoord + ")"); - } - } + for (TileEntityReactor c : registry) + { + System.out.println(c.coreFrequency + " (" + c.xCoord + "; " + c.yCoord + "; " + c.zCoord + ")"); + } + } - final int LOWER_HIDE_POINT = 18; - private boolean isCoreHidden(TileEntityReactor core) - { - if (core.isolationBlocksCount > 5) - { - int randomNumber = core.worldObj.rand.nextInt(150); + final int LOWER_HIDE_POINT = 18; + private boolean isCoreHidden(TileEntityReactor core) + { + if (core.isolationBlocksCount > 5) + { + int randomNumber = core.worldObj.rand.nextInt(150); - if (randomNumber < LOWER_HIDE_POINT + core.isolationBlocksCount) - { - return true; - } - } + if (randomNumber < LOWER_HIDE_POINT + core.isolationBlocksCount) + { + return true; + } + } - return false; - } + return false; + } - public boolean isWarpCoreIntersectsWithOthers(TileEntityReactor core) - { - AxisAlignedBB aabb1, aabb2; - removeDeadCores(); + public boolean isWarpCoreIntersectsWithOthers(TileEntityReactor core) + { + AxisAlignedBB aabb1, aabb2; + removeDeadCores(); - for (TileEntityReactor c : registry) - { - // Skip cores in other worlds - if (c.worldObj != core.worldObj) - { - continue; - } + for (TileEntityReactor c : registry) + { + // Skip cores in other worlds + if (c.worldObj != core.worldObj) + { + continue; + } - // Skip self - if (c.xCoord == core.xCoord && c.yCoord == core.yCoord && c.zCoord == core.zCoord) - { - continue; - } + // Skip self + if (c.xCoord == core.xCoord && c.yCoord == core.yCoord && c.zCoord == core.zCoord) + { + continue; + } - // Skip offline warp cores - if (c.controller == null || c.controller.getMode() == 0 || !c.prepareToJump()) - { - continue; - } + // Skip offline warp cores + if (c.controller == null || c.controller.getMode() == 0 || !c.prepareToJump()) + { + continue; + } - // Search for nearest warp cores - double d3 = c.xCoord - core.xCoord; - double d4 = c.yCoord - core.yCoord; - double d5 = c.zCoord - core.zCoord; - double distance = MathHelper.sqrt_double(d3 * d3 + d4 * d4 + d5 * d5); + // Search for nearest warp cores + double d3 = c.xCoord - core.xCoord; + double d4 = c.yCoord - core.yCoord; + double d5 = c.zCoord - core.zCoord; + double distance = MathHelper.sqrt_double(d3 * d3 + d4 * d4 + d5 * d5); - if (distance <= (2 * core.MAX_SHIP_SIDE) - 1) - { - // Check for warpfields intersections - core.prepareToJump(); // calculate spatial parameters - c.prepareToJump(); - // Compare warp-fields for intersection - aabb1 = AxisAlignedBB.getBoundingBox(core.minX, core.minY, core.minZ, core.maxX, core.maxY, core.maxZ); - aabb2 = AxisAlignedBB.getBoundingBox(c.minX, c.minY, c.minZ, c.maxX, c.maxY, c.maxZ); + if (distance <= (2 * core.MAX_SHIP_SIDE) - 1) + { + // Check for warpfields intersections + core.prepareToJump(); // calculate spatial parameters + c.prepareToJump(); + // Compare warp-fields for intersection + aabb1 = AxisAlignedBB.getBoundingBox(core.minX, core.minY, core.minZ, core.maxX, core.maxY, core.maxZ); + aabb2 = AxisAlignedBB.getBoundingBox(c.minX, c.minY, c.minZ, c.maxX, c.maxY, c.maxZ); - if (aabb1.intersectsWith(aabb2)) - { - return true; - } - } - } + if (aabb1.intersectsWith(aabb2)) + { + return true; + } + } + } - return false; - } + return false; + } - public void removeDeadCores() - { - LocalProfiler.start("WCR.removeDeadCores()"); - ArrayList<TileEntityReactor> oldRegistry = (ArrayList<TileEntityReactor>) registry.clone(); + public void removeDeadCores() + { + LocalProfiler.start("WCR.removeDeadCores()"); + ArrayList<TileEntityReactor> oldRegistry = (ArrayList<TileEntityReactor>) registry.clone(); - for (TileEntityReactor c : registry) - { - if (c != null && c.worldObj != null && (c.worldObj.getBlockId(c.xCoord, c.yCoord, c.zCoord) != WarpDrive.instance.config.coreID || (c.worldObj.getBlockTileEntity(c.xCoord, c.yCoord, c.zCoord) != null && c.worldObj.getBlockTileEntity(c.xCoord, c.yCoord, c.zCoord).isInvalid()))) - { - oldRegistry.remove(c); - return; - } - } + for (TileEntityReactor c : registry) + if (c == null || c.worldObj == null || c.worldObj.getBlockId(c.xCoord, c.yCoord, c.zCoord) != WarpDrive.instance.config.coreID || c.worldObj.getBlockTileEntity(c.xCoord, c.yCoord, c.zCoord) != c || c.worldObj.getBlockTileEntity(c.xCoord, c.yCoord, c.zCoord).isInvalid()) + oldRegistry.remove(c); - // Update old registry to new witout dead cores - this.registry = (ArrayList<TileEntityReactor>) oldRegistry.clone(); - LocalProfiler.stop(); - } + // Update old registry to new witout dead cores + this.registry = (ArrayList<TileEntityReactor>) oldRegistry.clone(); + LocalProfiler.stop(); + } - // TODO: fix it to normal work in client - /*public boolean isEntityInsideAnyWarpField(Entity e) { - AxisAlignedBB aabb1, aabb2; + // TODO: fix it to normal work in client + /*public boolean isEntityInsideAnyWarpField(Entity e) { + AxisAlignedBB aabb1, aabb2; - double x = e.posX; - double y = e.posY; - double z = e.posZ; + double x = e.posX; + double y = e.posY; + double z = e.posZ; - for (TileEntityReactor c : registry) { - // Skip offline or disassembled warp cores - if (c.controller == null || !c.prepareToJump()) { - System.out.println("Skipping " + c); - if (c.controller == null) { - System.out.println("Controller is null!"); - continue; - } + for (TileEntityReactor c : registry) { + // Skip offline or disassembled warp cores + if (c.controller == null || !c.prepareToJump()) { + System.out.println("Skipping " + c); + if (c.controller == null) { + System.out.println("Controller is null!"); + continue; + } - if (c.controller.getMode() == 0) { - System.out.println("Mode is zero!"); - continue; - } + if (c.controller.getMode() == 0) { + System.out.println("Mode is zero!"); + continue; + } - if (!c.prepareToJump()) { - System.out.println("prepareToJump() returns false!"); - continue; - } - continue; - } + if (!c.prepareToJump()) { + System.out.println("prepareToJump() returns false!"); + continue; + } + continue; + } - if (c.minX <= x && c.maxX >= x && c.minY <= y && c.maxY >= y && c.minZ <= z && c.maxZ >= z) { - return true; - } - } + if (c.minX <= x && c.maxX >= x && c.minY <= y && c.maxY >= y && c.minZ <= z && c.maxZ >= z) { + return true; + } + } - return false; - }*/ + return false; + }*/ } From 1756328289f508b079752260e45b8aa459f5b192 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Sat, 23 Nov 2013 00:43:23 +0400 Subject: [PATCH 05/56] =?UTF-8?q?=D0=93=D1=80=D0=B5=D1=87=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=B8=20=D0=B0=D1=81=D1=81=D0=B5=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/warpdrive/sound/hilaser.ogg | Bin 0 -> 13806 bytes src/assets/warpdrive/sound/lowlaser.ogg | Bin 0 -> 8133 bytes src/assets/warpdrive/sound/midlaser.ogg | Bin 0 -> 9955 bytes src/assets/warpdrive/sound/warp.ogg | Bin 0 -> 81915 bytes .../warpdrive/textures/blocks/airBlock.png | Bin 0 -> 2987 bytes .../textures/blocks/airgenSideActive.png | Bin 0 -> 2027 bytes .../blocks/airgenSideActive.png.mcmeta | 4 + .../textures/blocks/airgenSideInactive.png | Bin 0 -> 926 bytes .../textures/blocks/airgenTopActive.png | Bin 0 -> 2027 bytes .../warpdrive/textures/blocks/boosterSide.png | Bin 0 -> 431 bytes .../warpdrive/textures/blocks/camOverlay.png | Bin 0 -> 2167 bytes .../warpdrive/textures/blocks/cameraSide.png | Bin 0 -> 514 bytes .../warpdrive/textures/blocks/contBottom.png | Bin 0 -> 474 bytes .../textures/blocks/contSideActive0.png | Bin 0 -> 1072 bytes .../textures/blocks/contSideActive1.png | Bin 0 -> 1077 bytes .../blocks/contSideActive1.png.mcmeta | 5 + .../textures/blocks/contSideActive2.png | Bin 0 -> 1080 bytes .../blocks/contSideActive2.png.mcmeta | 5 + .../textures/blocks/contSideActive3.png | Bin 0 -> 1108 bytes .../blocks/contSideActive3.png.mcmeta | 5 + .../textures/blocks/contSideActive4.png | Bin 0 -> 1083 bytes .../blocks/contSideActive4.png.mcmeta | 5 + .../textures/blocks/contSideActive5.png | Bin 0 -> 1109 bytes .../blocks/contSideActive5.png.mcmeta | 5 + .../textures/blocks/contSideActive6.png | Bin 0 -> 1110 bytes .../blocks/contSideActive6.png.mcmeta | 5 + .../textures/blocks/contSideInactive.png | Bin 0 -> 533 bytes .../warpdrive/textures/blocks/contTop.png | Bin 0 -> 594 bytes .../warpdrive/textures/blocks/coreBottom.png | Bin 0 -> 819 bytes .../textures/blocks/coreSideActive.png | Bin 0 -> 1476 bytes .../textures/blocks/coreSideActive.png.mcmeta | 4 + .../textures/blocks/coreSideInactive.png | Bin 0 -> 682 bytes .../warpdrive/textures/blocks/coreTop.png | Bin 0 -> 727 bytes .../warpdrive/textures/blocks/energy.png | Bin 0 -> 5892 bytes .../textures/blocks/energy_green.png | Bin 0 -> 5768 bytes .../textures/blocks/energy_orange.png | Bin 0 -> 5432 bytes .../warpdrive/textures/blocks/energy_red.png | Bin 0 -> 5816 bytes .../warpdrive/textures/blocks/energy_sy.png | Bin 0 -> 5662 bytes .../textures/blocks/energy_violet.png | Bin 0 -> 5834 bytes .../textures/blocks/energy_yellow.png | Bin 0 -> 5465 bytes .../textures/blocks/gasBlockBlue.png | Bin 0 -> 2982 bytes .../textures/blocks/gasBlockDark.png | Bin 0 -> 2884 bytes .../textures/blocks/gasBlockDarkness.png | Bin 0 -> 2883 bytes .../textures/blocks/gasBlockGray.png | Bin 0 -> 2953 bytes .../textures/blocks/gasBlockGreen.png | Bin 0 -> 2993 bytes .../textures/blocks/gasBlockMilk.png | Bin 0 -> 2884 bytes .../textures/blocks/gasBlockOrange.png | Bin 0 -> 2972 bytes .../warpdrive/textures/blocks/gasBlockRed.png | Bin 0 -> 2978 bytes .../textures/blocks/gasBlockSyren.png | Bin 0 -> 2981 bytes .../textures/blocks/gasBlockViolet.png | Bin 0 -> 2982 bytes .../textures/blocks/gasBlockWhite.png | Bin 0 -> 2884 bytes .../textures/blocks/gasBlockYellow.png | Bin 0 -> 2992 bytes .../warpdrive/textures/blocks/iridiumSide.png | Bin 0 -> 295 bytes .../warpdrive/textures/blocks/laserSide.png | Bin 0 -> 649 bytes .../textures/blocks/laserSideCam.png | Bin 0 -> 727 bytes .../textures/blocks/lasercamOverlay.png | Bin 0 -> 2588 bytes .../warpdrive/textures/blocks/liftOutIn.png | Bin 0 -> 1318 bytes .../textures/blocks/liftSideDown.png | Bin 0 -> 572 bytes .../textures/blocks/liftSideOffline.png | Bin 0 -> 366 bytes .../warpdrive/textures/blocks/liftSideUp.png | Bin 0 -> 585 bytes .../textures/blocks/liftUpDown.png.mcmeta | 4 + .../warpdrive/textures/blocks/liftUpIn.png | Bin 0 -> 1318 bytes .../textures/blocks/liftUpIn.png.mcmeta | 4 + .../textures/blocks/liftUpInactive.png | Bin 0 -> 352 bytes .../warpdrive/textures/blocks/liftUpOut.png | Bin 0 -> 1353 bytes .../textures/blocks/liftUpOut.png.mcmeta | 4 + .../textures/blocks/miningLaserSide0.png | Bin 0 -> 545 bytes .../textures/blocks/monitorFront.png | Bin 0 -> 488 bytes .../warpdrive/textures/blocks/monitorSide.png | Bin 0 -> 440 bytes .../textures/blocks/particleBoosterSide0.png | Bin 0 -> 1412 bytes .../blocks/particleBoosterSide0.png.mcmeta | 4 + .../textures/blocks/particleBoosterSide1.png | Bin 0 -> 1413 bytes .../blocks/particleBoosterSide1.png.mcmeta | 4 + .../textures/blocks/particleBoosterSide10.png | Bin 0 -> 1390 bytes .../blocks/particleBoosterSide10.png.mcmeta | 4 + .../textures/blocks/particleBoosterSide2.png | Bin 0 -> 1413 bytes .../blocks/particleBoosterSide2.png.mcmeta | 4 + .../textures/blocks/particleBoosterSide3.png | Bin 0 -> 1412 bytes .../blocks/particleBoosterSide3.png.mcmeta | 4 + .../textures/blocks/particleBoosterSide4.png | Bin 0 -> 1411 bytes .../blocks/particleBoosterSide4.png.mcmeta | 4 + .../textures/blocks/particleBoosterSide5.png | Bin 0 -> 1410 bytes .../blocks/particleBoosterSide5.png.mcmeta | 4 + .../textures/blocks/particleBoosterSide6.png | Bin 0 -> 1408 bytes .../blocks/particleBoosterSide6.png.mcmeta | 4 + .../textures/blocks/particleBoosterSide7.png | Bin 0 -> 1405 bytes .../blocks/particleBoosterSide7.png.mcmeta | 4 + .../textures/blocks/particleBoosterSide8.png | Bin 0 -> 1400 bytes .../blocks/particleBoosterSide8.png.mcmeta | 4 + .../textures/blocks/particleBoosterSide9.png | Bin 0 -> 1395 bytes .../blocks/particleBoosterSide9.png.mcmeta | 4 + .../blocks/particleBoosterTopBottom.png | Bin 0 -> 603 bytes .../textures/blocks/radarSideActive.png | Bin 0 -> 3007 bytes .../blocks/radarSideActive.png.mcmeta | 4 + .../textures/blocks/radarSideActiveScan.png | Bin 0 -> 4612 bytes .../blocks/radarSideActiveScan.png.mcmeta | 4 + .../textures/blocks/radarSideInactive.png | Bin 0 -> 588 bytes .../textures/blocks/warpIsolation.png | Bin 0 -> 1020 bytes .../blocks/warpcont_side_active_7.png | Bin 0 -> 1113 bytes .../blocks/warpcont_side_active_unwrapped.png | Bin 0 -> 981 bytes src/cr0s/WarpDrive/EntityJump.java | 2474 +++++++++-------- 101 files changed, 1342 insertions(+), 1234 deletions(-) create mode 100644 src/assets/warpdrive/sound/hilaser.ogg create mode 100644 src/assets/warpdrive/sound/lowlaser.ogg create mode 100644 src/assets/warpdrive/sound/midlaser.ogg create mode 100644 src/assets/warpdrive/sound/warp.ogg create mode 100644 src/assets/warpdrive/textures/blocks/airBlock.png create mode 100644 src/assets/warpdrive/textures/blocks/airgenSideActive.png create mode 100644 src/assets/warpdrive/textures/blocks/airgenSideActive.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/airgenSideInactive.png create mode 100644 src/assets/warpdrive/textures/blocks/airgenTopActive.png create mode 100644 src/assets/warpdrive/textures/blocks/boosterSide.png create mode 100644 src/assets/warpdrive/textures/blocks/camOverlay.png create mode 100644 src/assets/warpdrive/textures/blocks/cameraSide.png create mode 100644 src/assets/warpdrive/textures/blocks/contBottom.png create mode 100644 src/assets/warpdrive/textures/blocks/contSideActive0.png create mode 100644 src/assets/warpdrive/textures/blocks/contSideActive1.png create mode 100644 src/assets/warpdrive/textures/blocks/contSideActive1.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/contSideActive2.png create mode 100644 src/assets/warpdrive/textures/blocks/contSideActive2.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/contSideActive3.png create mode 100644 src/assets/warpdrive/textures/blocks/contSideActive3.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/contSideActive4.png create mode 100644 src/assets/warpdrive/textures/blocks/contSideActive4.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/contSideActive5.png create mode 100644 src/assets/warpdrive/textures/blocks/contSideActive5.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/contSideActive6.png create mode 100644 src/assets/warpdrive/textures/blocks/contSideActive6.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/contSideInactive.png create mode 100644 src/assets/warpdrive/textures/blocks/contTop.png create mode 100644 src/assets/warpdrive/textures/blocks/coreBottom.png create mode 100644 src/assets/warpdrive/textures/blocks/coreSideActive.png create mode 100644 src/assets/warpdrive/textures/blocks/coreSideActive.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/coreSideInactive.png create mode 100644 src/assets/warpdrive/textures/blocks/coreTop.png create mode 100644 src/assets/warpdrive/textures/blocks/energy.png create mode 100644 src/assets/warpdrive/textures/blocks/energy_green.png create mode 100644 src/assets/warpdrive/textures/blocks/energy_orange.png create mode 100644 src/assets/warpdrive/textures/blocks/energy_red.png create mode 100644 src/assets/warpdrive/textures/blocks/energy_sy.png create mode 100644 src/assets/warpdrive/textures/blocks/energy_violet.png create mode 100644 src/assets/warpdrive/textures/blocks/energy_yellow.png create mode 100644 src/assets/warpdrive/textures/blocks/gasBlockBlue.png create mode 100644 src/assets/warpdrive/textures/blocks/gasBlockDark.png create mode 100644 src/assets/warpdrive/textures/blocks/gasBlockDarkness.png create mode 100644 src/assets/warpdrive/textures/blocks/gasBlockGray.png create mode 100644 src/assets/warpdrive/textures/blocks/gasBlockGreen.png create mode 100644 src/assets/warpdrive/textures/blocks/gasBlockMilk.png create mode 100644 src/assets/warpdrive/textures/blocks/gasBlockOrange.png create mode 100644 src/assets/warpdrive/textures/blocks/gasBlockRed.png create mode 100644 src/assets/warpdrive/textures/blocks/gasBlockSyren.png create mode 100644 src/assets/warpdrive/textures/blocks/gasBlockViolet.png create mode 100644 src/assets/warpdrive/textures/blocks/gasBlockWhite.png create mode 100644 src/assets/warpdrive/textures/blocks/gasBlockYellow.png create mode 100644 src/assets/warpdrive/textures/blocks/iridiumSide.png create mode 100644 src/assets/warpdrive/textures/blocks/laserSide.png create mode 100644 src/assets/warpdrive/textures/blocks/laserSideCam.png create mode 100644 src/assets/warpdrive/textures/blocks/lasercamOverlay.png create mode 100644 src/assets/warpdrive/textures/blocks/liftOutIn.png create mode 100644 src/assets/warpdrive/textures/blocks/liftSideDown.png create mode 100644 src/assets/warpdrive/textures/blocks/liftSideOffline.png create mode 100644 src/assets/warpdrive/textures/blocks/liftSideUp.png create mode 100644 src/assets/warpdrive/textures/blocks/liftUpDown.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/liftUpIn.png create mode 100644 src/assets/warpdrive/textures/blocks/liftUpIn.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/liftUpInactive.png create mode 100644 src/assets/warpdrive/textures/blocks/liftUpOut.png create mode 100644 src/assets/warpdrive/textures/blocks/liftUpOut.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/miningLaserSide0.png create mode 100644 src/assets/warpdrive/textures/blocks/monitorFront.png create mode 100644 src/assets/warpdrive/textures/blocks/monitorSide.png create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide0.png create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide0.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide1.png create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide1.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide10.png create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide10.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide2.png create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide2.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide3.png create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide3.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide4.png create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide4.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide5.png create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide5.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide6.png create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide6.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide7.png create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide7.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide8.png create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide8.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide9.png create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterSide9.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/particleBoosterTopBottom.png create mode 100644 src/assets/warpdrive/textures/blocks/radarSideActive.png create mode 100644 src/assets/warpdrive/textures/blocks/radarSideActive.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/radarSideActiveScan.png create mode 100644 src/assets/warpdrive/textures/blocks/radarSideActiveScan.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/radarSideInactive.png create mode 100644 src/assets/warpdrive/textures/blocks/warpIsolation.png create mode 100644 src/assets/warpdrive/textures/blocks/warpcont_side_active_7.png create mode 100644 src/assets/warpdrive/textures/blocks/warpcont_side_active_unwrapped.png diff --git a/src/assets/warpdrive/sound/hilaser.ogg b/src/assets/warpdrive/sound/hilaser.ogg new file mode 100644 index 0000000000000000000000000000000000000000..edc93fc4a792cae131f2fe582b7e5f0f762b09e1 GIT binary patch literal 13806 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 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/sound/lowlaser.ogg b/src/assets/warpdrive/sound/lowlaser.ogg new file mode 100644 index 0000000000000000000000000000000000000000..823cf770778a8e0fd9b78d87d21130121cf726bd GIT binary patch literal 8133 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 QZ+lzbCH|OCP%I()e|(K@<p2Nx literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/sound/midlaser.ogg b/src/assets/warpdrive/sound/midlaser.ogg new file mode 100644 index 0000000000000000000000000000000000000000..b1252d3f23f8fe5a63dbc20a5ce2d24b538f96cd GIT binary patch literal 9955 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 S3_+q1e|_Q*!>M6h(*Fm9A-PHb literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/sound/warp.ogg b/src/assets/warpdrive/sound/warp.ogg new file mode 100644 index 0000000000000000000000000000000000000000..4a148e70bb94f0b7d316b8c17c7878dc813a3df1 GIT binary patch literal 81915 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ˀgSPa7U?TwZ|X7{JiDJ97Jh{cPd@Nj)}gikn4gzxxXprA4)5VR zhq8jyt_T}`%ixvAIiblauPUy&fN(KC1*=dYFDE;L=*U^*DAEK?)>^>^Ei0N@!KGZe z_LW}?Q}dI3opiK>7j{p|QS{rw4Tb{vowr^6TWl2!AGA!U<Ps5Uz1=?a(3byN;G9hR z@k4Wl)grd+5<-d#y@Q5o9-j~<Y?M8#C){ohTPJde&1%6gz~x(X_T{NHN6ZAv1D^B` zTX=kWd?M#mWWGFNWAiu5h+B_u?f$+YxH;r?JnNUJ*L>}hJvw>Y<~^poI;T=&Y#DeP zpXr+$^7K18cOtGXT+Ner`{wEEPA}g20V-$a+Yt8mBa55nFY}be%Tys}HsQk3kGWgJ z0V{hB0=kh%TIhCEy;NHtYFUgqRCNP(GhG7`5+QB{?Lr-<k!swzK#o*Xi&T5GQXimD zN%pPjG#O7(ADwa2UWy&|EtAV#nii-I`)S%KZDrDEnk<vRrn*=Sixff;RHPbidY~bs z$~$}XcvkxO(=9eve~z?R93cA>*<@jhga@N#S8{;jG5)D_#%qUV#pfS3R^Yd28%t|S zd8nDU&k}Vij_f^2Ume6*`uBGOb>I5>U;Kpb)?a@;IdYp=EA;#IGiv*=ck`FS0l;-& zKMt44Fb(%2>+3d#U7AE6OT4uB`}=(8?z2f31REO88h;&PShXNyID4d_%(hC)VXm@y zD?1Pl@v-9K0H7R4PK{##zsmdyTnjaA^<Lt>t|&82Gn*e}HfT2!yF8@?cHYrJ*GIWL zEz=0)j9l)FJgyrKQD}pHIjZU9VTYn|$*Q2~=c=vm00TvS#kVE-`7*5t#r9!U&tX=W zMvkWV(cP2Rde*tF0NqoUooQjA!^x_BankGpo6O}?5Ez}`+1h1r>P&*|_<@+2F)Ixr zOJ5$^E}$W4nphf|hH_!_SE&@i*R9|Ddi+P>$B3OXZ}yLgKY8WQY~x#xEfI`LAZ-PI zPaWE#1NU}N-3>+j^-@ouwIwF#*S5VIfoR}<%I;0eoK==^3+*1Ba9R+90;ojbAb;PP zIumHm(RJTDubuf|@$&i3CJiwt#e$I4Rl}9<y?_CRFB93J+N==@t`hg1lR#I_&{MJX zX&Lt$!nIssWwCCgm3R5qZ8F2k8afRfk<JdtQ-A^+hQ}u(!@1l?XwZFRuxssfto5`n zUn$q$lcj`dfzA(#b~7IXex|+^R}^MmCv|HPb`jXwJQ=$QS`WqAvN}Wg**PwBDtTB^ z=34XZ%iSrTyP?;6Tr#$4lCe2-rNHFCRFc@#&8_!yw(momz%otOf`+Rb+zlpcvMe1| zy;^_$Y{8*#cR3$xwEl809jQ*3fFdL=R5WqX&Wk!^m5taqGsD<y7f95jyS+;|cRBD{ z715`Q%|@s5RC2ZMEDN|%*nYa-W4^5`a#8v9?uJ$GW-vifvr`X-L+P}kC^+)iQ74T{ z&Pk=v#I{uE*!jTY78EsK^Spfnt=ui`d>t?}bee&y3K+d8ufVMf%<u%)+2PK$#QIV0 zcu5`S6|t@!%W_kUhtdYGAbs3q(lq^+zRXZKst?#|@e`%H#qH6jrH@+jF0NF-oJ}h= z<9t3o@4tP!eWZ`uX#uO&z}>-@6j6&_2kjk5J7ZOQ8b2&%^NE5`w3S3GaKHKKPP4}L z1xCwejjxU$+kDZiU|Qdm_2RV4;(GW+*C(qt3quQq6OA{j(d6m#6Ur-w54w-gJVzc| zYplP`nKs_?Ev#XG>W#q%hq9W3&+gi8#e2&XTHU?~)SjGAI=~57kHxo%b;x)zK$&6( z≈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 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/airBlock.png b/src/assets/warpdrive/textures/blocks/airBlock.png new file mode 100644 index 0000000000000000000000000000000000000000..1be0e96f90744267109924fc05e6cbe5d1f3e4f3 GIT binary patch literal 2987 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 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/airgenSideActive.png b/src/assets/warpdrive/textures/blocks/airgenSideActive.png new file mode 100644 index 0000000000000000000000000000000000000000..e2520225a3a2589c580472ccbd64e5b079023a0c GIT binary patch literal 2027 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 JPDHLkV1fqN*y8{I literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/airgenSideActive.png.mcmeta b/src/assets/warpdrive/textures/blocks/airgenSideActive.png.mcmeta new file mode 100644 index 00000000..f6e326db --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/airgenSideActive.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} diff --git a/src/assets/warpdrive/textures/blocks/airgenSideInactive.png b/src/assets/warpdrive/textures/blocks/airgenSideInactive.png new file mode 100644 index 0000000000000000000000000000000000000000..7760f0033b13b154b523d3a76b81a27f665591df GIT binary patch literal 926 zcmV;P17ZA$P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv0RI60 z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3JX2EGE???7sj202y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00Ra|L_t(I%Vm>GZyRM4hM)Q7 z;?MTPmza>tG?0iw8wt9oR4Vuh5fYV9t4d|Tf9M8Ps4C)5uwj8jMFj#C!2%>&v0>42 zDJ4mxwkdVeOl-%AU3)H`@mxL@uIPfZdUSL)kIwsQCr`bp-aqg1#We?j3uj%fem&vy z@3~z2=Kp-|jLTQoCu{&j0soEXrQBOz!?FsLiVjMFyZeNLjz=6dC`d^XKfl*5f9R;t z2g88DphvG8W0)o<PaVgul<0OlWa)@r&nHg>Wm__i47>sO9*7@qIG84U`gzD_S2OA} z1#aG+VUV508-)CN=LFy1SSAikzWuSvm)Fa9eTzRHI^1tN6NSJ_2>bxMQlV5zky0`W zM+E&0DJ8nD17KMeN-0n}Qc9vILi^;hqaJK@sWmJLmW3rXcDCS^qpy<T6GuLIu4wIg z04N2fQAal_Y&ZAO2jR*Ur!l0Lyn|`K#qxZ{ORry~*)C8kZS%{YN63v8jxA~EjWcMa z<7jaUQ9Vtw6HXM4EY0xuKN+o7n`xuR#&189Wf}Gy2qBnXSU}gC9CrKozE4eQ2whCR zaOt9>k|amvCQ=p&h6X|4qX~g!n#AK6l`Cv}iZs;-{FJBtF<GuN3PbcDUAa;ckGZvR zl+7)J>GA>h+pi&OCs>|Oxbt|CzwQOpi+%2H&vW40G|Gppoc@5j4>|~dbgZ+p-Ng5X zC>62i?ozMU>G%7Xrb(q*B@AK?yIl^u`$$U?jVEc+KK{s2?VSYQOOT}ue<;XOgO`_< z84gDzNlFj|gh7DN4C;*<)oO!Bk6Mhv1o7QZ4u)xRYjcj9x93O_!S7qs_~zRHtna?S z!~F$H#WGK|H<&$kjx-sw7raPcInNXlu&1WTvkavKl}ZJFI3#+Od0DV<78h7uU1fc3 z4cBcy@4|(59TkR<XHd3b6dGi?#4a1;3c@g^R1_G7Nfh~nVTw`^jz9=7HuoGBr(B+R z4tOwIaOuQV@Sv`_^wnfvRW1W<QsLQxizg=hFA2DDLwgFARsaA107*qoM6N<$f(Sa3 ArT_o{ literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/airgenTopActive.png b/src/assets/warpdrive/textures/blocks/airgenTopActive.png new file mode 100644 index 0000000000000000000000000000000000000000..e2520225a3a2589c580472ccbd64e5b079023a0c GIT binary patch literal 2027 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 JPDHLkV1fqN*y8{I literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/boosterSide.png b/src/assets/warpdrive/textures/blocks/boosterSide.png new file mode 100644 index 0000000000000000000000000000000000000000..8d0921532c80e8fa92cc6ab67367e8403d0dc7b9 GIT binary patch literal 431 zcmV;g0Z{&lP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3J{N0yuL1O@sgd02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{009?CL_t(I%cYV{ZUQk3g+Dvt zrz#67X5C@inH>_`{{R(dsConn(g=~bi%Dq$GeT;!iJj-?_u@o0+nw=`<yEzh1h68= zVo7<fB_M`(-e*UKrQ(v3nplcOuABGHC6Wyg%Uo`xK#~Kq<W};ko@jQ3da7X7lSRNg zbr~tYbHAGzBAJiUN-?p&y~1X@8w6&P30>C_LLkP#bpAA0r(cHyr{nQ@@cA(ZplRM% zzARZ)E1Yu$22j^E^?Hqla49;zuDbypxx>^ss;WX`%!l-=;<Nv8i>2p5MbO)#AC>8B z#u!%2AjCN6z-ivw?j58*GV0)bK0kC2V?<@-o|j9YZCcu<<$19fbO7LGMCE<If9OC| Z_y!}FYQLoHwz&WR002ovPDHLkV1hv5uVnxL literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/camOverlay.png b/src/assets/warpdrive/textures/blocks/camOverlay.png new file mode 100644 index 0000000000000000000000000000000000000000..9e3d1e94acdd7491ec8cecbe57e7984f4389be4a GIT binary patch literal 2167 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5Fo{p?&#~tz_78O`%fY(0|PTd zfKP}kP+VS75lD`L(GVDcArMiRG6j@TN`m}?|Br0I5d5886_^A#3p^r=85sBufG}g$ zwN6f;pj3%#L`iUdT1k0gQ7S_~VrE{6o}X)oLYc9ish**M!Iz?iz#`?gr;B4qMcmuj zjgu}bh%kKpZ~tr0fk{G>F3essWpjS{67NRu$$Ja01pcpKJ<edE!*(Fikb$q8u^@t{ z;cyazj2QES4H69PM@g2Ft>3=km;AwA`-Hs@Z5aMZ@H9yCG?Ys))bp?%;AJ~t&C_7d z#{2+?WZ4eLH!~I-&TP;i&7$RozvCZDG58;5U`sIKWPXq-ae%=`Es?>7msz6WqzX^N z@<aw^gPARi9~^${KP~=H>2QTRLk&=2q67o~5r!W^YzGb-FvxW<eo*CUXb0*OV1D2Y zlse4tBlN@aAG|rSP2M>PuT6nMPvRJCc$gnFN-)G9VyKW{JHTwnun%ak0Z#*a5|WwQ z9{??JZm@eSzp<b3g9%RpgW6;RhIws_JO@&M)?GGeV4UFtG(n2ZfMK$y1cSeFO~Xwh zeSOdH=X>qA^Cy`l8QvQZ6QGq1x@-Q~7u*-kF`2{G(S#PI@sIqMow>Hv<mKnZ&hH<j zHB@cd_vgvOx~e>j?e7w6n@lQgF7xaE%49T~Ec<i0+r9sFzV_$*_xDF{-(cfZxuj;{ zW%nqvzGEeMcb)&TSUPT=wBnwD=PkK;$JSQguyg!AQ%<__n(ZIIyt{{gv1ER#Sk~Mf z=05xI<ejDbSA(zWyYq)#yKOi(`um0&^V8-g*5@xRQC$Cg@B8Z}mUchm>JI9jfhV|q zN8U}}X#Qu{w^#iYnGH|>YUgbz=VjjW;Fsxkz3umWe&)ud#d_I%yIiR@`)k{tsBdD^ z*L$9R-RTmw?)s|jovCXNZ~m+I^i}uk!Y$XNb=}kZ+#Y7Em$RLh^IcP1f8}fbHTUIv zYt-uRTE*VCk$!!#)#UEGeD{9!+qI{TW^ezz_~YNEOBZFo-rW3AVSo1b*B2k3ESq2S z@z&cv8CQP0Ur9fIj4S`v->NSao9-@;`SXJL_SSnDmR7|kr*1yl3|9Lk*s$K~*PP?t zVUqXtD@zN1*A<@L6g6Kne)6=L`qe(>*{^ROfAKNpcX@!^qnn3g9$sf(v4656bB%pz p-MdHPpMNv+9K)XT7Sz=KWmeIRF#X>ZVGXJzJYD@<);T3K0RW6@(b)h1 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/cameraSide.png b/src/assets/warpdrive/textures/blocks/cameraSide.png new file mode 100644 index 0000000000000000000000000000000000000000..66332b118a8828f77b125c1f65646b0ee0d1d272 GIT binary patch literal 514 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85p>QK$!8;-MT+OLG}_)Usv|K?6RV4;(ML9-UJFsmbgZgIOpf) zrskC}I2WZRmZYXAlxLP?D7bt2281{Ai31f$ffNPjr<If^7Ns%-BxdH7==r&ZD3lrN znd%uD7<?&O2y~96r;B5Vg@5nFSifcm5w~<#Uf#|rk~0{+req|`M@iRN9ljv6INIQ% z=#R8VtE&qH^St%z3PaXhd}4Fp&igZa#c!N_8(Uwxc6V)Z?pD)VWw+jG<!U8o-8DOA zwruUo(AlMtdg0pFzD<vu_rLv7PN2@Y$XuPh9GZ>Ke=Emyp6Ct^n|Y0M@ruKoT4!%; zyY0BZ>4@dWNz2a9vHxk;IN9G_RppDy1GOdbhc9sUU)E%?NSt%Q!<k)1@o#9whdsYf zKA9bGd#|tt`-Fd*9|GB@JBwH}UTO|__0GI;5ku&#=X;yw?6mtb_Fuf)5<Tm($E30! zKllYW$_+0GwDl^VoSL-MP~d?K%hgDc)}T$kcO5!HsxCN6omn(P_qzDH!}DcY=cpc6 zFPgVHNAHn@@6He>O+``Po_2#iW<4fFCdGRUvX{=W{E0tx0T|Q_p00i_>zopr070b3 AkpKVy literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/contBottom.png b/src/assets/warpdrive/textures/blocks/contBottom.png new file mode 100644 index 0000000000000000000000000000000000000000..b150416abddf0d29b5aff61e2a72a8d88162f478 GIT binary patch literal 474 zcmV<00VV#4P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-sm3>7mde9=P~0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbOR7pfZR5;6}l1*+CK@f$%YLCYb7r<Hh0=_~d5K=&bB@!Hm z3r0j1i^w8!oPk|DtvEen&vbV+3xq{}8j<8}N~%|S_4KOb<EPK5ZCi?>pePDrjQoN3 zp1$u%DRCFxd%CV;@bd8R%h!_=#2DtMr-(6po6iwraL%#aZrSa2EY8jtjmP`?eX*bz z4v{y<Z<Do_r=W2TGZ+lGytn|kSO3OCGa~Xl2X3>$<kSIT2qe|4gCyh~)ax|~cyVyR zWHRA;v$;2OZS8Ld*^q8-SYKT+8jm036XXSkWr>JTmLs~Z%PuK$#B@4kHk+ZUIOnng z*%0fxX0=*TRTb9SY|zg-qpj<IpYgvQ>FCw#)HKbbx5pT1+XhpX<?ZK4iPdt6suF@H z#z+XB<@xz72S2Nd(0k<F`w!_yRqd5kl^7$cimD<2B8bSo*Y_R6a)gG!F9g*7Joki9 Q-2eap07*qoM6N<$f>mS7<NyEw literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/contSideActive0.png b/src/assets/warpdrive/textures/blocks/contSideActive0.png new file mode 100644 index 0000000000000000000000000000000000000000..09d00940b24f0ef177e4d096f7a1113a46f939fa GIT binary patch literal 1072 zcmV-01kd}4P)<h;3K|Lk000e1NJLTq000mG004jp1^@s60+s0^00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-sm3>F9{(wYzG0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbQs!2paRA}Dqn9FYDL==X<va8+gPMmail1ainqv0YzLW(ql zX2Fgf5(rkj1Y*x?@CG~r(rgd{39&$vFhM9F0wKcynJ7#r?yDVNs)~g>?lcJ@&Mdh3 zNLF>rrQfboRiFPlV)gnB!$X7wXti2stpW1ZbzN-RMkz(A6e>;g`&w&)AV6!K3B+;C zU@(|a?)7^4Z{=y!l}w;|zlsSBX_6o-l}tcN2|zHsLaH2$S-=uLt=2S2x`|pydGKC` z^c#nzTTtC{NYivIFb)r+UqQ;(Q0jA}+#yLf!3fl@M28x?X8~YN=3pFMyqQli`fCtF zDo%~?2r9oy9(jKT0J~#n0;616lLGhf4}ChFZ94uQj<XBE_pJ!|K=PxNA`-#Y;t|@I z@f#dxUI@Y5{E6hLCIHXw*CyJh_Z$L~j0G%fG%jN}XwT#V&F1*sUcSFeH;VXf<tmnC zp_DqE10e*9O95#<=d<~}VUo}b!->A91g57wT-QZPiEZ1|YBjpuE&!WPKE)p&c1l2L zMZe#_&=S^X&BEi4u5oAWHm$}wch+w6;`3R%vA)LQ!a5u4YrOU5MxHMKv3mW6X*3#i zI-NqB=<wix*4$h+gyCS23mBzfG(H1}(UTA&`!57WYt(265+F%a8jZ%KwzI`U#^28a z>m(1t;gDXhhwuCJdtK_Tn+c3~u=hs5(Gw9szFH?1k^z$VF#uu(^(luS42$r9iQNeE zKp`H$L3<{@j^n~SfU7i`4UAbp2%j*l0_}_Q0HzuAZ{|#_yW7Qh09_i*&q$MuiMEsw z7vO>C`P8Q(r1Wzh1OX)vN*?_Cc(6jF+01ui6uCgV2oF34{hLHb?=l>`N}4Pe<-w#w zv1O&0Kgb-)GT>)Go3~4UQ1YPULFo@le^Bz^AIO7rIVFA}TT%6|>M)>K{UE*;<G<5E z?@LV8F!j+?!TJGU1{NkV*!y<z`a$i>8VkQkund)ZmE!e-AH10Amcvhn1}m^i9+W)z z-|`^77IU<keb&8CJVd)752BYM`fv9!fxy%>vmeY}f(L1K$zLkx@xWth`Yu|3h$Gth zbk;wvBX=bTaK3fU<3XR{V1*=poiKO?Oh%vWT7vt9%g;LkyK9%{g^~xQKlm$u5DteV zN}-fO+7^q8O9Wwfaewfq=Y@;=gR{>I1^mI;=Y`TAl>VUPL0M0{L_KlRp&WNQj|bKy q56*Td$2@rM?heQOOCJ2Ec<?)ZrQLNL5~>6M0000<MNUMnLSTZRr02>2 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/contSideActive1.png b/src/assets/warpdrive/textures/blocks/contSideActive1.png new file mode 100644 index 0000000000000000000000000000000000000000..1980059b426b2aebecb34d0d570d7f0ba24a9e43 GIT binary patch literal 1077 zcmV-51j_q~P)<h;3K|Lk000e1NJLTq000mG004jp1^@s60+s0^00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-sm3>FF@3D3x10000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbQuSrBfRA}Dqm`!ioL>R|^W6yfmn>g9sBuxV4B~=9okdPv^ zs0VJ`kU((aOCS#1_zE2P27H7{To3{YaX?LI5DJJwNNFLh(r)5?vz@g)GaS6}W=RNf zdf?5EWX-NT`rGr&%+LRM#Ojr+hDQhq&}y~NS_9;*>$=#sjZ%tKDO8%~_qEo9VTjf` z6NuxO!C)|<-0Su7-^$ad3z<OmUKJA=(j-AvDw%+k5`ZwcK&l*!S-=uLt=2S2x`|py zdH8;Z^gD;8kD+?YAx+b<z&JdNeg!FCL#Z#3a+@UG1S3#85*=ymo&|t8nuBq4@n$~9 z=x;#;RGb>o0aSjIJoe!X0CvaD1V*{CCI#-`@B4H*TXg*UIL;0LKemR*hmxPI6p;w- ze((To%=irsGcSZ-ZvIH}R1<(_cWV>v#rNh3O)wU)tkJlPVXr-t3pAVKcYFEX4&C99 zA6715Sr$sE<2evQu(%YG=5s!q-wTq2UKCCAJti<c?cusEQc7&wrdF%b?REj!eClcb z_^@LFN-O&P{+X7rK4})7czlhUYd2^$*15TMgBPFA+Ku%!78lmpSYP9<H#hQp0f^Nr zS52eQpwsCT+C=+%d$i`}vLOV6K`vmFg3<U4AVyC@i0r=*7_CvGAxMBEO=&b5=i1H| zj~IVH53Hj+h=PD#uZQpZ^m|?EuA2#rcyRxXkb@_O0QqX2SV#s);)?*p3hGl1VH6eN z0Ta6s=7B;yfW7uiejUb{c>tGaG#ePRfDk@WR0Y~+=K)MJ=wHj3Sa-LI@c_CsnqQD6 z853<OAuhlJ&-1BI4Uy8%c@Tz_JScha@8iJ=jb=07jl-b}w2Sb-W6;0G@Zep7!K<Xn za#0>kIuu)0iur@gp)3P_2DEv*^amvmN*<K{p!5eN5B`BXNS9OM7qS&q|E3NDiq#L| z%Q5~t9rUimR1H&~Ocksj0A^reh6a1rE?z&VeO+VWfdtD?xl<`#KlsUusorw<W#3?h zR>^~s2mf0h#Ft|ZR<qB#_nC)i7v#b4r6K*d`<PH*YMR-PX3xQcG`r-lmD70OF*SV~ zt*_&Vc0Qf;PwU7X2?Ct&ozr;GCm5`d#IF;D&w$D3vsFuQzjC>|EwH<Gd0r@aQ2K+v z@&{26kSK*x3Tay`E-n#9(b@gMpPm=a?hj5rFBI?xC!ZHee^B~^k_Tly@f`KUNr!US v=`<c#lRP-tp&atyx!c<u_AhzxpW?yqQs3Q0ucSpq00000NkvXXu0mjf>HF>a literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/contSideActive1.png.mcmeta b/src/assets/warpdrive/textures/blocks/contSideActive1.png.mcmeta new file mode 100644 index 00000000..b84e69f2 --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/contSideActive1.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 4 + } +} diff --git a/src/assets/warpdrive/textures/blocks/contSideActive2.png b/src/assets/warpdrive/textures/blocks/contSideActive2.png new file mode 100644 index 0000000000000000000000000000000000000000..a446b7048800e3515716ebfdd6563d218830f63b GIT binary patch literal 1080 zcmV-81jqY{P)<h;3K|Lk000e1NJLTq000mG004jp1^@s60+s0^00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-sm3>FIrQf6Ut0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbQvPnciRA}Dqm`!ioL>R|^W6yfmn>g9syz^2>RbB*0NRe99 z12=9+AbR4=9dUvKU!&iEkATFbsz5><P!k%20wNH#svwC%Hu1jNS=%$i!5eRugb=3( z-uy_GZF%&!=b4$G|MQ5I>o*LK5fY%$XrQ$Q$j+|oV%s)KDH5enNs>L+S`!2TTI*CG ziXwWw-k5Ty)5)%tr&05%KzXN(2@OdcBTJ=JKuQTf(4Qw!4#v!337<w|k~rBw%_Z!A z+#>njVevC4Z#pDNG7=bthtaPi<(nw=6;eJRPBy>@)V4&28oOfwU{2;>6m7hzFEIK$ z5PeEch42VUze=9CJq3W>vQvR!uB>r^NBD<6t=1MTe;3Eu2H>a00J$&O`REW43pN*y z(8i3u;5hR_2xewaBu~`=cww&sz?Bc@0eEiLAu#bsz_Nz@GKPcZR3=cbkG}1-oo(8K z0Y5HZ#j-4vQm1nugkWJYAj!sjI(ycSV>)3t*7lUZ<fMn|x=1OpZJSD^Lc84tVB?u* z`Qyt@2`H`TcDomv!uqUHc>2jz?yugXQCs8w>OEe0DLt>Rt+Ft;#`@YSx87OL@&zDP zuHP`VT8&n#m1_|l9vsk^nMu3Q@AWbPqZADLX8<vL6GEi-LSVE;4Z9!#;v}I~t6ge2 zTRdj`{XDQv@*wQ@>2x~yzE8K)rs}$>z>o*KZwDM*831Inb!;LTAda2_AW~4Ba0tRM z4-XhyjW7%3;sG2qr?TTXF3bbCO08bQm^p;-3Bxkbyf_bFl3w>_#>A?-m5&F|rdI!w zBu<%VO9@d99(bNlbz*>&e#V0!px{BlgMS|nmZ{b2*=igNT%ehU2OhodO$J9F(C@uL z5-;WD!MH=QWhtLONFB-&;HN;FwF`ex@Sxy9;SUObQ1IX%$b)1lA$mETQPpp&&?8^{ zAi5Uezu!XdNle)=ac3fD{QxjM3o|g-dv^Z%LFJnYbH7Qj45de<{PlyMy@>Lr!`^#s ztiURGQ1IY?%Y*1z#L-InTlYTq5Y3!C7`!^5`)(H#2uwvY{mJwtc#x!r{H1gr4?HF& zAENcAIHH*iXZ3Csxh+9}^Mi9954!Yw%f!)Jgu(M*Qu=IFV%)D?_HT8u+jg;ED0oo# zgTL|zVZTqT6iO+iZLzShNDzh>_XmHvU%0qGID5a4!ylZzUnu-R;SUNP6!pYQ)Dy=Y y%5kIfcwmk5;B1F-%!3ynKH#{0!Gr%44}J$_@!NHb`{|_s0000<MNUMnLSTYU+w5Qf literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/contSideActive2.png.mcmeta b/src/assets/warpdrive/textures/blocks/contSideActive2.png.mcmeta new file mode 100644 index 00000000..b84e69f2 --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/contSideActive2.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 4 + } +} diff --git a/src/assets/warpdrive/textures/blocks/contSideActive3.png b/src/assets/warpdrive/textures/blocks/contSideActive3.png new file mode 100644 index 0000000000000000000000000000000000000000..36ef3bdc985974aad8df76775cebc077e4b53905 GIT binary patch literal 1108 zcmV-a1grarP)<h;3K|Lk000e1NJLTq000mG004jp1^@s60+s0^00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-sm3>FLlWcyDM0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbQ&PhZ;RA}Dqm`iIURTze!sycnCPFHuQlS~pXqme;G1tl;e zvvB85P@I)(_u|flf5D~yz@H!pBBCHJWD*mRD2|31q9#Koom6*qT~e2Gj*ChviHR|l zS$L}tit3`O-|Fvt=REzM&se;EL-P<J0Q&ttN-2QiY}+=LWg(>`lM<O_#eJm|VHl#6 z$_0`n!T0?W%AV&HpQWRaS8{>IRs$VrvNT21YPo<A0)Q~MLMH2IJ%eeu^!shnYz;Y+ zvGd-L?E5-%A4B6#oh-|a1dhT%tCtbtRiyk1A?}i9YoHC}ra(ms%QFGc$H(9(MmU`> z(CRxd0&4Xp(LU6E6Fl-k2LNkm<pKv|Wu6q+z}<5h4%ZpF_o>%60r;sOBX$H^@9trw z2EV-j0HyQaU@Tt0p*x)pp63yTA$F@($W2a8;=1ms(kZ0~gMhZ<<SCfuL0($3JLnt} zIQr5{TbqpHm>(CO!Zb~!l&8nQFbrnrLb9Uf-Qr%5rg%|w;@MLI?Y4t$+Xx}BEQ@Bd z$!IhJVC{(~`Qyt@2}mUwkH;69!s@IlJpSksD@(WO_m){%y3O;?=I7PrC1z)qSzTV@ z)*GwEcokLX^?D44!%~ZAZ+Dme)Ks2A;QNJumJ$x~(|~dCCJZCLHVm{<$b%FFK$>Or zdc8|6XOoAFzn=%@aUMiLfaiI*uFKdP(X#Da;D87BUk};88Uqxw^~6NdK$<)TKq8?v zQ74R|GCY8(Y46z8G*F5Musi4!$6;KU2VpQvquE3284Sav(`gU{D;MVhwDHF`3nsSg z^>RFb5xvPT$<myOmJpDX;DO_~v?gMNa0?!UAr%iQ9{l@wut0BevRI9AYy*QbJaF*G zH;MP(A@E-zOXth-V49{qfmTys1a!MKe1EMB4>oZ3=7HQ)Oix>tKd5+6@u2btl|QI> z@DJocHlL9^m(Qryw=M7~*FQ+ECAe=7QQHFD&`f+fQL=vkXx~J~8f)7s-#=)6(`4p> z08>-jsFm*@{Olw&?$p_SYlIn^6%Q&N{BL=XTuazr%>UM%&mD|GNgl*6#Ejn@qeBDT zRCGV=UV;Z%eu!Ud=kdT{qJ0mgKB8_6igLC-YauoT7*PMAejX3T1pWeP@)}Y2H0Yc@ z>&+DVYnz>0W2})??H4K@RQ}+v{6Q21q*5ZKL|7)XvvY(|ba8+1r~8GA`-8Lh3nl!) z+53gcA5{LJ;z89<yhK0oMe2<%N?pY;2DICnIR4~Z9+)S2aJEA^<iRud?sE8i#e@G8 a4}J%4dj0Mzk>w5m0000<MNUMnLSTa5nf>Dc literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/contSideActive3.png.mcmeta b/src/assets/warpdrive/textures/blocks/contSideActive3.png.mcmeta new file mode 100644 index 00000000..f6730e30 --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/contSideActive3.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 4 + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/contSideActive4.png b/src/assets/warpdrive/textures/blocks/contSideActive4.png new file mode 100644 index 0000000000000000000000000000000000000000..2df281d3da298909f6cbb0ede2d0d1f08a27a622 GIT binary patch literal 1083 zcmV-B1jPG^P)<h;3K|Lk000e1NJLTq000mG004jp1^@s60+s0^00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-sm3>FI{V7?8J0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbQwMj%lRA}Dqm`!ioL>R|^W6yfmn{49Uyz^3;s=Nr0kRr9H z2X5SuKyczqAWmEm7cP7Oz5yQrsTYJmLL5*N8iWEOQb{Ro8ij1)eYLZ;XNH3}-Yf|r zP7l2Kku2Nt=x@(6Ge7_55i8fO8y+DfK%>z>YYmW{UDw67ZIn_ZN}-Y@d#<%62m-X$ zsX!D(^m@H9<xZ!QU8|Z#&8Gt8hh<D?Na7e-Dy0HaN&tfXJc)8JW)4gEG#Zn{$p&gJ zVekDG$qx>TH=(@gkR-`SU=%fseg!FCL#eNka*H_G03%S_5*=#njs<`@o`X@esZD)} z(cgpUQ*tVVhfsPTdF<mU0PL2X3Jh~)jSJkvKk#X_?$GjgaGY%b?tiq0+>`ulC5TwC zxp0U!X7mL|nHNGZGkYv~st&-V_vQh3cDDk+(>o4<iAMsKHSCu$>^G+}fqH%PZ7)CE zrac(&)AAK8%R(u2G6zBk78V1NY|N*#XZ<*)6NY1LPY6s-)^J@HDJ8aTQ>j#Fx7z@0 zJaw5rzU+j6(u!`kd#)+0PaB0NA7AD6>Ma`H8n;((@#6F8d3|k_g}F7>*H(G!&Gjr_ z0Al6Zb>n#+tyU}7B0AXLr!g~=cA?+vWdcSi81~NqV)!P6NbiNfXpI_nK?1}{g6DY` zTFw@a7=J$xtm8Zg`+Yi{4!-Zx?X;=7ZYnV3!Oj~2hnEHb*=!w~NCt?bCjf{PR3{vQ zFwDaP##STD0=akq`^~BBIEr)g0IuNGJ&c({2%j)41I_dE04C{mZ)8lYx_9#N0NQx< zuSnvQiMEsw<={cB=2M**Af=!2AP6XUQ1Ia2$Ae|OdOcf>gMkY)^YEZXuX}^R;k)#E zuad+|d3iAIP;6Ps=MPecvIO`k&}Qwz9~3+&cu@F*!XFeo_y_VJSxSgrNM}^_yDId^ zS3iiZM)>cv(7O^-HcWgrk+XgPn4X0h80=j;fBm5HZH2ktBv^*hy;A=A!GjN*ls6rI zIWSm(Rq&wT!T**A(bb5<mGrk>`=W+u=H$WPr2*ZyyO=;=Dw^p}rZ2#QBt7K)(pfyH zF)?`;tv|&P&1^WUpI4FF5(GFuI%n~qOTV{F9KB8$JOd`B&-MrVxZk+^x+SpNcClY5 zcu@F*zw!rRzfY_bN-3mmv9Pd65QgXX2Y<R>IKMwQeZP>yADq5lDEvX;4+<U>^~4L* z6UQCOQKPeXV2$(Obcb@pgXivUan!!x!GDSezXM<_-E~K$N234$002ovPDHLkV1iE} B>No%Z literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/contSideActive4.png.mcmeta b/src/assets/warpdrive/textures/blocks/contSideActive4.png.mcmeta new file mode 100644 index 00000000..f6730e30 --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/contSideActive4.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 4 + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/contSideActive5.png b/src/assets/warpdrive/textures/blocks/contSideActive5.png new file mode 100644 index 0000000000000000000000000000000000000000..ef5dda0c59219537433c7b579e31c5eab925791e GIT binary patch literal 1109 zcmV-b1giUqP)<h;3K|Lk000e1NJLTq000mG004jp1^@s60+s0^00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-sm3>FM5AtV!I0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbQ&q+i<RA}Dqm`iWmR2YVzW1qQrGWR4+!le*YAp}UENG<Au z9XlittoRd%Jz~R#4a@!megYB_LI@<p0yQB)C?G18l(bE&Hj{Y9<4b1ja}EnnoP>lB zrweZWB+Fyj^LoDXo%76lKCyK9is2DL0(84wwAKLG*>N0f+eRrxq7*7gvin+V!Z1W@ zoeGS{V|?E~qU?EI_E|MF>Ov||xmUqNh9r)WrBW&&r34@hE|91)#>`>~mu|OCoUEf} z6Sm*)ll)X>{xhiDD3c_~fxtmDF#1)bd>y5}Mam80WF3q^ZAo;bu{{d_b9f96VnCz$ zHAepkBA`^R6750huH><6O#tk^oeE6G$~r2riM#94@86{F-ltsN0^rU^+sJLnuU3MH z1-Czbh&JhO5KEV@m}awy=Xpe7h*PU&a-B{G*L9DTPHRmV1k@XiGzH6=<Yf#yz2+f- zgD<^uZ;Qcb#4n4_U|AMQspDfHgkWwyB*|*t%I*bmj2A^mo;@Z|uQzZU2Pq}CZBwmQ z84LyhtUvWMe|*_70i_kg;qXjTSf5mdCm&yCb@@8o_6n=Z*Lm^z^t`sR%-rk>Yb(pV z{nlDGURf2|?Kb^>Ki4AK-Pxf#J)Ncy_<kl}l!8fq1`v}sAw+sD1V(GrBn1f&CkgF# z`&`S};t}KT=Ye&Y2T>5<c^<CoGV})2948f+@ZkQNA$u1`0NHFkGLZ}rkDmZwte`ek zCXAvyJb>vL@6go@kc$Vf(`#nOew>*HVK7If+Qyh!gm7s#D+Iyn*?9nU{NdG%i8beD zJ|4h;cIO+CIAx+OC5&_MpwV!tO^uM!&3F)o6g((+@bBZnBJEBmTaBZU1N8Fnpn*TU z%4qLB0{=CVcp)zjW~e$-7(ERlpw%kj`|Ejlu!+070Hmg3X2vf3LBWH92ZcW<{6WEk ze;^N%g@o}7>5QuVPy?TQ{e$tPG48v4^aF{h7^c3M%Go~vjBjB^2K#}Xzkg8uzRK)F z36`O>S<2r(xcgy`%8fF=?Ha7mDtJ)v;D5`5@ue|)OX=Tw<EsXumy-vhmqrZV8Dc_# zscKrEw9dhUBt7Jv(rG+sFjc>W)}K-qy{w$IFKfsx2?EMLmrvutkicIg9=|~pJ_{zL z&(;S!INv$k-VoRWyVx%jJShCZU-^S52#A$JDTTBx=H})Jqv-7Z;7|7pXZHsu?-z3T zgOm3Qg+D0#LBWHfpLmXb;>(mPEwsLf5IyR3!)WyRsXVZb^5A5Lvd@F(Zf&ste8GeN b6c2s}g?0b#>byWC00000NkvXXu0mjf8jt&T literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/contSideActive5.png.mcmeta b/src/assets/warpdrive/textures/blocks/contSideActive5.png.mcmeta new file mode 100644 index 00000000..b84e69f2 --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/contSideActive5.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 4 + } +} diff --git a/src/assets/warpdrive/textures/blocks/contSideActive6.png b/src/assets/warpdrive/textures/blocks/contSideActive6.png new file mode 100644 index 0000000000000000000000000000000000000000..202f50451a073c696cc27b42e9b67de9510c77d8 GIT binary patch literal 1110 zcmV-c1gZOpP)<h;3K|Lk000e1NJLTq000mG004jp1^@s60+s0^00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-sm3>FOqdX2hC0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbQ&`Cr=RA}Dqm`!UWRTPGws=8g>)!*GorV~F#BZG(vN?=B2 z;m)0)I4jrg#hnXr<HkSWKkz3Af`}-H3z@`3B#MDyhA@*1F`ZO*b$z6}>fY<3I+eu4 zn93~tsslxJQPpqtx#!-e-+PRu>o+uy5CWjv?V^+d$j*-AU|AMYN)joNNs`@HN)d)3 zN~u&}GMV7}{t0Ez^Rmyfp^#Tnf%0}49chv{MwCjafDi(JFt|b@ZM2@lG+esfI&rd& zoJ-jKU_kP-&HU$3-mpoM<VfHs8ff(@LcETY-yy_Z;$$7Pf!q?PNMU&<0Q&eC9L11E z^Bc7K35<Y}T_HMv(gVR`pELom239IC9V_#sz$Wg#%V2Paf%_2K-U8tM$GeDK!S?(6 z7_q@d?*OIK-(W0VzoDDWCZ6XJg&|J0n#pxK9bDHvRXU{<VGvMnG}07IbDEdd?Dd<+ z1dhJ+%Jvq+@t9v1pTRUuq?D(}z%UGY^C3xA^Hz2*h-17cI`Ql&fqK1x<2VQ*uq=y8 zrNVGH1YrHCr}^W{P6<dQ8I494n!@U=Dm?l4GONqC>9$u`UB1nW&!^|Lm1TN!E3B<7 zbL*|OY`n56wA*b4gF&uEw7<7UcV;F{A@Kc7KuZbJ{4`)p--KbL*M@;s3OP+d0K`c` zyWPIjayEIy`1^Ta9_K+61bCi@>$;4*Ayvmo1*SZB_-4q#)iFReTTe_R4aAct0GLRq z)@;Hk%EJSgne~oc%>uc20DJvrb{xiqc@PFY%9S=+&tVuY&1RV(SiLw8ppHMfnK7~I z+{woS7}D;1OA@C{w1j|34jwcbF4fu?A>51yVMxJ)f(QRT9xT%Cbh6br9y>rk4-Xpn zqnnHm-Xri|BZ(LC@?e&VQ$wp6Falbw628BlhX<Ru`wKv7DrRS`!XFeoD0oo#gTfya zJopFlAX!M5ypYbQ>W@|M$=5%aT$|v&J3#FSbXimTvX--d0BGMtk2ThgmA`*b`Juwx zZvsqBX|t5SfAHX=KIILYop*+qp;_>t;KBcv2a{_P4wllt^~To?jDAiYj9(fvdV7Qp z4Rl4(`m}Wk9wg}@?w8KvL4#WT9!h<NZS=EpR==tuwgebp|6-rVgAswhNIZFiD0~)l zN}sI{_i(;<*u6Ev8d}AEq2NK`5B|y@L_t6-B~nU+Wzy@-6GqX+{lTB^7cTA(&fYKN z@CRq_7Yct+_=AE6ML+Qp{lu5C%Po|;iedDr*EQqu7w7W8JjsKz9m*jOp1XIK!{-Yg c{HJ*EJEr>m?jIWlp8x;=07*qoM6N<$g0eja5&!@I literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/contSideActive6.png.mcmeta b/src/assets/warpdrive/textures/blocks/contSideActive6.png.mcmeta new file mode 100644 index 00000000..b84e69f2 --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/contSideActive6.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 4 + } +} diff --git a/src/assets/warpdrive/textures/blocks/contSideInactive.png b/src/assets/warpdrive/textures/blocks/contSideInactive.png new file mode 100644 index 0000000000000000000000000000000000000000..2845c4adb016650c68edca0cf3e8067722012bee GIT binary patch literal 533 zcmV+w0_y#VP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-sm3>7mHy4{+p0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbOk4Z#9R5;6}lU;AqFcgL#C*G871JZP;NPJI1NWj&kjo$%3 zd#TnNF5m)*n}LuhZPFwqAIIh*sk^MZ;KP!2Y}tO!dtTe>^z7X7A58<qaf~qrz{M~O z@qHf=p%p>e)~y?3D9aLKOb4jznmo@3<Sff>&FG*_gWlW21JGInur3O+EMu`)u*y;n z!q6SOdVR>}Cl(O_pzRgu>vRh=^&<dkfrG<+%Jmw6swily3JBcZ9RR@i_`39CH#+%( zI}BiZue_Up`H#D<Z`!BHubpVD-745Puap`n5E%jR@_R6dFTU+l+GY#zyiSO<c93~A z+A4ed^@_Br`1t$;&-0v_0}qr^OdgcZVPo#OwW4XrdP6sRcK}C6cL>7}tu?;y69fTi znga0Q=`(I7+X09XR;$$?Jz;a(Ej)ghaG6{XM^i473*Nly;%u5Qxj$t#O?dxq=KKOs zr)TFjiXxWF<zIcGpYu8Kc-)mx<hcV_5$Nl)fa)`$R5w=&YYfttpaGh;C5obd`p&-r Xu7by^E!(cl00000NkvXXu0mjf_g3f| literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/contTop.png b/src/assets/warpdrive/textures/blocks/contTop.png new file mode 100644 index 0000000000000000000000000000000000000000..ec7d79affada019025841ab02cc2989e6ab630ec GIT binary patch literal 594 zcmV-Y0<HatP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-sm3>7p40Z6$#0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbO%t=H+R5;7Mlgm!qKoo{QdyFqhx*=Uxm8z-*Qc9>wdU*hN zg<hV41rOUcB)Afw#7-Q$YDlm>Gnp;|ZY|g$^=xKFnltDB{&U9Ke|unfK-fGmoZHPT zN!V~*jMi9U{jOOVY#~@_&B_=YA@GBMMx%k0vaZ0gU}vk(*>J$qCj*B4J|8~}8T|N8 zI2`c&*%`yrKA%5*!}tA4fpzOamZmJ0OE3nEL9bQ_ApmZw21vc)dbyyp(;-QcI)ZIk zpf%VwuIG{G`TBz6kY8V;v_h4V&Gsf*>$@fz3<tdllW5G#7Z)Uxn4`m((d7lxIO28Z zl4%_A^~-6ctcLI_OS!sQ5Hy=;r6`MHZHzHE?gpxqRnlI!dlvyLq%2|aPmj!cL;}xe zE>(5D7s0YD-t|%@(U{#=F_UP_(cyXxhXdYpBc^f0@o`d{g9>3j|4o*r*tYoF*PDu) z?KaE2AYWYJI1XFe+hkc*M^IAHY&}9NNm<G&*$)EJ*^E+_xEn4?sryIS7J|LqkjwM) z8p8R{kZBz8zLznLBTh~dJkPs};CU|X_G5$)v|6potfDOOTo)k(T5Iw=$8j9OFsvgK gMagJ1`v1T24_9>WiJy)0y8r+H07*qoM6N<$f&?=IqyPW_ literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/coreBottom.png b/src/assets/warpdrive/textures/blocks/coreBottom.png new file mode 100644 index 0000000000000000000000000000000000000000..43f67ed1b8129f7065750ac45194abc291d6d98c GIT binary patch literal 819 zcmV-31I+x1P)<h;3K|Lk000e1NJLTq000mG000mO0ssI2kdbIM00006VoOIv0RI60 z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3AQ+FeQr|YM1~30>DW` zK~yNu1;O2KQ)L(c@aO$F{ovGvZ0*^ZtV}^k42Z#!kr)$=7a}qey+E&s+@Q&BxZsBW zf$#?aH!62t6I@UOgn-awWeO9Av|t@;X}fhj=k$EMAJ60O$3Fk~NFiUy<sHrhFiMjY zfQW!GX3<)05fBkoW{@yR6G@hyx7(77FV38uD7o5LuTnO~y!Xzf`;BjE?_Rli_bX%V z($!1G;%F4eM5RU<<^TiezUt{LYc`u&>p6c|e^B3B9W|C4N|_{05lLGV``(zHKYsFq zPmZcI?QC@8IEluQQN|eR^h-p1b9+*0m5D-O%8&b9X{`C~)KAY|EKIn!FMnS<xc?<% z41o{;4H6L%xvrZp6s$D}Bmv;&o%3UrtTZA30Dy;&eMUr#F|vr(7{iDr+}GOewlyf; zn%nj5V!b+ZFNnY^2M9QS=-;O;f8o<d#iB)o8856<Mhl;<&Fv0;za6uWY6revJh%GS z-&<RoL<9hcaO>7@gLUuZsRPy$kwt@6>sISo+;2-RxJtDU3=tRu03fo1_5JzckrT(R zx1LWB!1D5xGKO&}I2U_n{nKaG-rn<6Y2%f{&MOxHE?#&t*2O1llbvqqbw8S!9)EeF zS)C15>LlKr^(S{PUi%r^|K+?&=vBh$a^OgtbJWJh4j}TqXys4umtS*t?qVJ@2}CBz zs=KPItB;mf%A_qZcE7&!@cRR;b?s0e4TYmHieqou58Fd2rD#0-W3)Y#xqK7^NI+;A z7uMP=Ns>5zP~W*Zc*(gK0|0;|#@8R;<6Mk$Q^r_FN&rgJbiUTPaRZJY>n<&!kj_le zgkf(hNu}Vt(;wuWoN@~sU^E;H>5QYG+0?yW?}s0Gnx&;uX*&pqqcF=9JNn__e_Ahy xz}-;*#t6|`L?Q+R0E{sJ21Hq^48xpo{s-vCwSJlOTz~)o002ovPDHLkV1k*ra*+T4 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/coreSideActive.png b/src/assets/warpdrive/textures/blocks/coreSideActive.png new file mode 100644 index 0000000000000000000000000000000000000000..3c2a0afdc81c43e4b8c3eb6ca1c5c4bd8e5721bc GIT binary patch literal 1476 zcmV;#1v~nQP)<h;3K|Lk000e1NJLTq000mG007_!1^@s63Ss7W00006VoOIv0RI60 z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3AQ+E)))fReb;e1yM;v zK~!ko?c48f6h#=o@$c+zdz1>I1nEzDZSP7kg@S-hY)d5?W1`V${{j=^3lm=&69X!0 zz&G+jB}QN98xx~|0knvKHBqb)LZLwX5fY>=ZAH1m0O|E^XXf$6UJE6(_0;g9%q5rG z&D_pBGqdx_?(D33_>o5?3`3Ms0OWEx0KzaNo6X{R9@bi>`UEApi^Pm&ESts7TTD<C z5avRPV=;W+M{A9UV68<&5D_X$6`rTaWX4d-;^i_YR?L#+Yw<lF6l6v-hzJ1LY!+(_ z#u~&5T5FVoD<l1gSc3Vtm9qSvH|g%#1_A>4((I&?trf&tYN}SzP~XO~_3PQas}<GK zl#s;Qb^weq7;Vrx#Aw6u-ZTJ-r7?`w7_HG-qm98DLs2G8aBYJq040DzfK*cofMi%6 zB`S%2^VJKro}7W?zaXH54!<@k5uHy|QBqVCB7!%$Q&bcH3Weg^?mm9(8Mu1Dc$m?j z(Ap4O+s9GhYGOY&XC5VU7UrYMr;JAeD5VIpxo}byqJ(I><-R(!));Lja!_h=%-(o^ zU*8sr@w%$<oqW9&Z)_R4dL~}i0zCW7A>Mkog@+zEi<PMFtq8mJECQhO$rML>OK#kV z0{r~zVibyG;v!$|uV(MQ%8A4$9>2iyrVO9%Sb&I-%Y}HOnGE0T-kGoaL?^QCy?Z9& zT2eg<3TkS`*z{^ubShjr&!sCF0%H|^;N?S#4ta3>8N>=!EM0pmqHN@9SBeOM?}M*U z@v=K4)PnC_ZC(*UDK#;muHE*1FF*7J9U6kh)ve3|4>~)K(AB+}!Qs9cJrEIUs#dXb z&2yaoX@m2?dEh*lWge_py_ICVjjrx33=H?p=z$eWyy`Lh+<xbQ^T2s9%RDGq*vX=~ z_t8+>&KKQV=s$OCMh`?PNi0q|51a?igIVT5DwpK1^R*=7Z8X%i^ZCKe^bhqq51a?i zgImi3)zXxZR4$3NhU)TW67e>c*0r<e!0Yr69h=4jaUM7ioCmYm0|crnnn}i6Sz5P_ z-3MOd>|pP-9s~d_t!3AEFhV-}F+Ha~K~aY9dpGbvu*O1$$tP0eLDXPIavZz!Yf??A zXplJ%oCnT>o9uxARb?wk*0$1E-@(o=Ut)0hL?Ip+v>v2?-Ul?&K~Pyt&9Wkj=F zFvax&Tq(=(!qcq)G{3Wm;-TWgJShFWh&At5VvHd+>`m!GFqH?l{So8vN2l<Ed91m& z5{-5qI1g?)53IFRm#?6quARpE4tDI_$iUEvLOjr1T6h{RNB0p6R$QiJeyng0KHTsk z04v|Vi~0RU|G|S1=YjLUdGN125V2HOG}BPqPD5=gpY7Ykz`4FcJQyY02iAssec^fL z-absSw5Tu-4sY1U_w0*2P|gGAf%D*h_rUW#E)V@Svj-wVb$N6C-eDa(_rAiwP~Sh9 zPmDY`nNE`&TuW}<FU&o1<M~8yIuHKbnx<#_S7<VY&mTAsoCh;`V6Al?6ykxkmL-)d zNyb}gOmwib>t*_fj{kEH0P1QN5<4<l$n%A~2OFXcD&G!>x$6Vxf%D)dtv@(<{L-}V zFD$88Nkd&5jfoC+bZunhvYy_9v7#(}XVRz~B&$l1D`8<Ch=L1GrH~lZ?~X-dpb!s~ z2p!$EXwlfv6#jgnXe{7|u2b~xA0o*4?)iedU$~{`53XO2R8tw5uq=5$+rQXIvF@JQ z18qW%AI+~nxO)yZs|)l1NH?Vsgrxo#>kmxKvd+c{wMP3I!a_aB`h0ir1V;`H;%m=& e;5?YtgTDcOG#WevUj+;R0000<MNUMnLSTZo@45y6 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/coreSideActive.png.mcmeta b/src/assets/warpdrive/textures/blocks/coreSideActive.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/coreSideActive.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/coreSideInactive.png b/src/assets/warpdrive/textures/blocks/coreSideInactive.png new file mode 100644 index 0000000000000000000000000000000000000000..1ef478923d2b42e19e49be7707378880c5b184f2 GIT binary patch literal 682 zcmV;b0#*HqP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv0RI60 z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3AQ+E*J+j8CC!Q02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00I(8L_t(I%XO1aYZO5c#eX$D z$tFlZ5!ob~KgtFXl8Yb<dJs`WP!RPyc<@{3MbCnWUqKX9FsKIw5y68&Pa=p&E+V)_ zf@Cr?Rb3u>c9RX-FmyGqr|Q*v)pG9q1+VKG5dom8Dgf%brYuXcEF;Fq|5iR;t<kc` zW?2#^+T<fSbyYLkY7s&}RdIJ>jJP}Q&h#!J%Y>rXM2^f)`B-a|*`;HIEPz0<QQ+<X zlx0aY!=mBQQB_7pNBF(^1^0+_7dzgo7KqWn!J(-ZhbqVDct38iPP<1A&^<8;fSF-x zsMeSoA69-5LPqCs3sc2ZQB~BOXb}ohg8mW!aX@gOx7Y(<p`J>hc-ouxYSrNc-hAL7 z&dG2vRYV(55|m2e?qtKJNFsnB2(Mp$<lWoVtsnX{(<M}me7nbqxD3v%u?fb<_BN~< zq|XEp5%RLChgwKLio3@Tp{khLAcM#-=dADdPA!CfuhKs>eG9j4e&3qJ9SU&m>Kks~ z?Q-_?H=-x+qdSkD>;vG+<sR=>#{Vs%1D`&(5rl=#8qZ(Mu>5TQ0K9bZCrgV3_aE%W z-KnaYY@;Z6_4pxXhRDD~?%X>%;59q50RnS#n_RzfAdSNM57z$_<Q9dHXM_+iOJbcl z^%ak4WS=fir!<Z7YKEDShX6s4`N=(As}r&<dEFfm89b=%aR^!S^c}5@zdxNavoBT< QN&o-=07*qoM6N<$f{k4xYXATM literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/coreTop.png b/src/assets/warpdrive/textures/blocks/coreTop.png new file mode 100644 index 0000000000000000000000000000000000000000..da52c058a0e4681db28674af45c391eb2e128345 GIT binary patch literal 727 zcmV;|0x127P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv0F3~G z0P}V*qZ9xD010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3AO58w-Q$oWKA802y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00KWrL_t(I%cavvZ(KzbhT*q{ zJ9d|i+p&N^<_#bvi%4dLl>aXz8wrSz62NTSaSV}rx<gGTiz{)nPi<;*^hkBSuhh%) zABE327U09b|Dlw^Sj)-kgolqF@!;DB?Dl)CF_dM+)jxmp=bJYi4hQa?ow2#Q<LLN! z0#b^2?|FHC&e72^P1ErE>(?ly&|1^?Jt-v??ue7siuLuHoDu*UKm>kz^@_85XLMc1 z)zuYBX|&eloT;jcrfqS~k#gqCufHPYPk_fypYZ(o3-(<{&O*)^m~Ih4L`WfEi-NXY z5MyNN+zfp8{SRDTUeYcWC<SfXqO}I4$yqq;_Gn{3gr;fG+F*>Cf#5yXT5fM{NGZ|O zHCkJS-ZS)`qO1{_!ct0+Q^JQZ11GB$MOFPjG>o3U>$&*(4}Sag2Jfd~5h10->FFss z<r&aQvD<7>N>f%9N+|@WYKL2%QWPb|T5M5}QsU5cjN>r(VDy2m>o7)RtR;p>@FP#3 zeZkT#P)eat1n;Nah!A6#fx}@>)3n6sNg)zrpsq`rwn1x+QXoue#1L4&TjQ3Wr0~nd z1tE-}6vHqeA{c8as}c~5F&Jwx#<1J(8M=;kv7CYJ=8mE7@Z$(fixeP+fVGyC5;;z7 z-EKDAzyA%J&E5Qjs%iM^?OPr`enO0aoCW6`B0}Hyh-9|g9WewJZOeLnO<mP9Fbo66 zTHdX%SvW^o6pVdO-82ltK;L&5W2vi}+uQdz=NQLv>c!`N=Z~~{DdIJU?0x_M002ov JPDHLkV1kO#O2GgC literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/energy.png b/src/assets/warpdrive/textures/blocks/energy.png new file mode 100644 index 0000000000000000000000000000000000000000..184f7faa7f670bab34c3d8b5763ecccfcb574e1c GIT binary patch literal 5892 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 azX1TbcE15~YzGej0000<MNUMnLSTZWHaxii literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/energy_green.png b/src/assets/warpdrive/textures/blocks/energy_green.png new file mode 100644 index 0000000000000000000000000000000000000000..076e194f292fabeac7d70ec528fcb64fd26bd547 GIT binary patch literal 5768 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 GLSTYMg!|P1 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/energy_orange.png b/src/assets/warpdrive/textures/blocks/energy_orange.png new file mode 100644 index 0000000000000000000000000000000000000000..313dbfa71825e8443d2e07faa59f9cd2c54a7195 GIT binary patch literal 5432 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 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/energy_red.png b/src/assets/warpdrive/textures/blocks/energy_red.png new file mode 100644 index 0000000000000000000000000000000000000000..8996066d4333155f8a3416cec927b85da5387769 GIT binary patch literal 5816 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 CR4Cd2 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/energy_sy.png b/src/assets/warpdrive/textures/blocks/energy_sy.png new file mode 100644 index 0000000000000000000000000000000000000000..80393d78bf970ba6c0053b5c5a39b0439a2c9cfb GIT binary patch literal 5662 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 Ef?}T6K>z>% literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/energy_violet.png b/src/assets/warpdrive/textures/blocks/energy_violet.png new file mode 100644 index 0000000000000000000000000000000000000000..31a99f6541cf9409c9aa2203870e2fe2fabdbaeb GIT binary patch literal 5834 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 UvgnK|a{vGU07*qoM6N<$g5wt+f&c&j literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/energy_yellow.png b/src/assets/warpdrive/textures/blocks/energy_yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..465d88364614309ae1faadbba048094ef78481ea GIT binary patch literal 5465 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 P00000NkvXXu0mjflSqg< literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/gasBlockBlue.png b/src/assets/warpdrive/textures/blocks/gasBlockBlue.png new file mode 100644 index 0000000000000000000000000000000000000000..f9916c91af931cc122c195de146220b0b19fe461 GIT binary patch literal 2982 zcmV;X3t9AuP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV000V4X+uL$P-t&- zZ*ypGa3D!TLm+T+Z)Rz1WdHzp+MQEpR8#2|J@?-9LQ9B%luK_?6$l_wLW_VDktQl3 z2@pz%A)(n7QNa;KMFbnjpojyGj)066Q7jCK3fKqaA)=0hqlk*i`{8?|Yu3E?=FR@K z*FNX0^PRKL2fzpnmPj*EHGmAMLLL#|gU7_i;p8qrfeIvW01ybXWFd3?BLM*Temp!Y zBESc}00DT@3kU$fO`E_l9Ebl8>Oz@Z0f2-7z;ux~O9+4z06=<<LZ$#fMgf4Gm?l#I zpacM5%VT2W08lLeU?+d((*S^-_?deF09%wH6#<};03Z`(h(rKrI{>WDR*FRcSTFz- zW=q650N5=6FiBTtNC2?60Km==3$g$R3;-}uh=nNt1bYBr$Ri_o0EC$U6h`t_Jn<{8 z5a%iY0C<_QJh>z}MS)ugEpZ1|S1ukX&Pf+56gFW3VVXcL!g-k)GJ!M?;PcD?0HBc- z5#WRK{dmp}uFlRjj<yb8E$Y7p{~}^y<NoE(t8hR70O53g(f%wivl@Uq27qn;q9yJG zXkH7Tb@z*AvJXJD0HEpGSMzZAemp!yp^&-R+2!Qq*h<7gTVcvqeg0>{U%*%WZ25jX z{P*?XzTzZ-GF^d31o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcq zjPo+3B8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S z1Au6Q;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO002awfhw>;8}z{#EWidF!3EsG z3;bX<ghC|5!a@*23S@vBa$qT}f<h>U&9EIRU@z1_9W=mEXoiz;4lcq~xDGvV5BgyU zp1~-*fe8db$Osc*A=-!mVv1NJjtCc-h4>-CNCXm#Bp}I%6j35eku^v$Qi@a{RY)E3 zJ#qp$hg?Rwkvqr$GJ^buyhkyVfwECO)C{#lxu`c9ghrwZ&}4KmnvWKso6vH!8a<3Q zq36)6Xb;+tK10Vaz~~qUGsJ8#F2=(`u{bOVlVi)VBCHIn#u~6ztOL7=^<&SmcLWlF zMZgI*1b0FpVIDz9SWH+>*hr`#93(Um+6gxa1B6k+CnA%mOSC4s5&6UzVlpv@SV$}* z))J2sFA#f(L&P^E5{W}HC%KRUNwK6<(h|}}(r!{C=`5+6G)NjFlgZj-YqAG9lq?`C z$c5yc<iq4M<QwE6@>>d>VnA`E_*3F2Qp##d8RZb=H01_mm@+|Cqnc9PsG(F5HIG_C zt)aG3uTh7n6Et<2In9F>NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWw<V8OKyGH!<s&=a~<gZ&g?-wkmuTk;)2{N|h#+ z8!9hUsj8-`-l_{#^Hs}KkEvc$eXd4TGgITK3DlOWRjQp(>r)$3XQ?}=hpK0&Z&W{| zep&sA23f;Q!%st`QJ}G3<GjWo3u76xcq}1n4XcKAfi=V?vCY|hb}GA={T;iDJ*ugp zIYTo_Ggq@x^OR;k2jiG=_?&c33Fj!Mm-Bv#-W2aC;wc-ZG)%cMWn62jmY0@Tt4OO+ zt4Hg-Hm>cbou<7-yIK2z4nfCCCtN2-XOGSWo##{8Q{ATurxr~;I`ytDs%xbip}RzP zziy}Qn4Z2~fSycmr`~zJ=lUFdFa1>gZThG6M+{g7vkW8#+YHVaJjFF}Z#*3@$J_By zLtVo_L#1JrVVB{Ak-5=4qt!-@Mh}c>#$4kh<88)m#-k<%CLtzEP3leVno>=<rYWX7 zOgl`+&CJcB&DNPUn>{htGUuD;o7bD)w_sX$S}eAxwzy?UvgBH(S?;#HZiQMoS*2K2 zT3xe7t(~nU*1N5{rxB;QPLocnp4Ml>u<^FZwyC!nu;thW+pe~4wtZn|Vi#w(#jeBd zlf9FDx_yoPJqHbk*$%56S{;6Kv~m<WRyy9A&YbQ)eZ};a=`Uwk&k)bpGvl@s%PGWZ zol~3BM`ssjxpRZ_h>M9!g3B(KJ}#RZ#@)!h<Vtk)ab4kh()FF2vzx;0sN1jZHtuQe zhuojcG@mJ+Su=Cc!^lJ6QRUG;3!jxRYu~JXPeV_EXSL@eFJmu}SFP8ux21Qg_hIiB zKK4FxpW{B`JU8Al-dSJFH^8^Zx64n%Z=PR;-$Q>R|78Dq|Iq-afF%KE1Brn_fm;Im z_<DRHzm7jT+hz8$+3i7$pt(U6L63s1g5|-jA!x|#kgXy2=a|ls&S?&XP=4sv&<A1W zVT;3l3@3$$g;$0@j&O)r8qqPAHFwe6Lv!Cm`b3sQ-kWDJPdTqGN;N7zsxE3g+Bdp1 zx<AG)W?9VDSe;l&Y)c$DE-J1zZfw5a{O$9H;+^6P<9ipFFUVbRd7;k2^o6GusV)*M zI+j38h)y_^@IeqNs1}SR@)LI@jtY6g9l~cKFVQy9h}c71DjrVqNGeTwlI)SZHF+e( zGo>u$xr8UFki1L{Ox>G0o)(&RAZ;=|I=wN2l97;cLaHH6leTB-XXa*h%dBOEvi`+x zi?=Txl?TadvyiL>SuF~-LZ;|cS}4~l2eM~nS7yJ>iOM;atDY;(?aZ^v+mJV$@1Ote z62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~pu715HdQEGA zUct(O!L<Qv>kCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$+<4_1hi}Ti zncS4LsjI}fWY1>OX6feMEuLErma3QLmkw?X+1j)X-&VBk_4Y;EFPF_I+q;9dL%E~B zJh;4Nr^(LEJ3myURP<E(R5tF?-L+xY_-@he8+*L=H0;&eTfF!EKFPk@RRL8^)n?UY z`$_w=_dl+Qs_FQa`)ysVPHl1R#{<#>{Rblsw%57T)g973R8o)DE9*xN#~;4_o$q%o z4K@u`jhx2fBXC4{<mvYb-}fF3I@)%Od#vFH(;s#nXB{tULYnfLMw?Tb`&(jLx=+kL z(bnqTdi+P*9}k=~JXv{4^Hj-c+UbJRlV|eJjGdL8eSR+a++f?HwtMGe&fjVeZ|}Mg zbm7uP|BL54ygSZZ^0;*JvfJeoSGZT2uR33C>U8Qn{*%*B$Ge=nny$HAYq{=vy|sI0 z_vss+H_qMky?OB#|JK!>IX&II^LlUh#rO5!7TtbwC;iULyV-Xq?ybB}ykGP{?LpZ? z-G|jbTmIbG@7#ZCz;~eY(cDM(28Dyq{*m>M4?_iynUBkc4TkHUI6gT!;y-fz>HMcd z&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M!p0uH$#^p{Ui4P` z?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&GcDTy000JJOGiWiApj!) zBm?T9qW}N^32;bRa{vGf6951U69E94oEQKA00(qQO+^RY2ND!61xf}GS^xk5*hxe| zR5;6pQ#%erAq;cXh=J)HqzCLddy+RXAdoun3?}f}EC}**9P_~Y^FmG)08lczS-{pp zeCpMZ&I$|75h8wCPSrOvxzwo(18F4#@o3%CSqB1OI5bJ2GC>kKqV;6upyauGJZ3~A z?n0nWPhN=6sWS^+Z?<eeHz9#b@e8@3<mS*(Sd=Fd$%{0#sj6q5$#>jz1b4&@9$Ima zps$fa@`B+Td0-*oX$WZpZ+Y|ESafhFU$4mJFYJgT>+bXPF_ta(z;xDWgq^@b{Idl` c=b$tG3x0f@&QwY1;{X5v07*qoM6N<$f-6LcQvd(} literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/gasBlockDark.png b/src/assets/warpdrive/textures/blocks/gasBlockDark.png new file mode 100644 index 0000000000000000000000000000000000000000..03e1ecad0296928a4724941d5662cace13ada2d9 GIT binary patch literal 2884 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 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/gasBlockDarkness.png b/src/assets/warpdrive/textures/blocks/gasBlockDarkness.png new file mode 100644 index 0000000000000000000000000000000000000000..20a1d17cad0b87bd92a89b7ac8bcf531d7764d9d GIT binary patch literal 2883 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 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/gasBlockGray.png b/src/assets/warpdrive/textures/blocks/gasBlockGray.png new file mode 100644 index 0000000000000000000000000000000000000000..89dc9f830cd73a5bd2888aeaef21e13e2614fb1b GIT binary patch literal 2953 zcmV;43wHF0P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV000V4X+uL$P-t&- zZ*ypGa3D!TLm+T+Z)Rz1WdHzp+MQEpR8#2|J@?-9LQ9B%luK_?6$l_wLW_VDktQl3 z2@pz%A)(n7QNa;KMFbnjpojyGj)066Q7jCK3fKqaA)=0hqlk*i`{8?|Yu3E?=FR@K z*FNX0^PRKL2fzpnmPj*EHGmAMLLL#|gU7_i;p8qrfeIvW01ybXWFd3?BLM*Temp!Y zBESc}00DT@3kU$fO`E_l9Ebl8>Oz@Z0f2-7z;ux~O9+4z06=<<LZ$#fMgf4Gm?l#I zpacM5%VT2W08lLeU?+d((*S^-_?deF09%wH6#<};03Z`(h(rKrI{>WDR*FRcSTFz- zW=q650N5=6FiBTtNC2?60Km==3$g$R3;-}uh=nNt1bYBr$Ri_o0EC$U6h`t_Jn<{8 z5a%iY0C<_QJh>z}MS)ugEpZ1|S1ukX&Pf+56gFW3VVXcL!g-k)GJ!M?;PcD?0HBc- z5#WRK{dmp}uFlRjj<yb8E$Y7p{~}^y<NoE(t8hR70O53g(f%wivl@Uq27qn;q9yJG zXkH7Tb@z*AvJXJD0HEpGSMzZAemp!yp^&-R+2!Qq*h<7gTVcvqeg0>{U%*%WZ25jX z{P*?XzTzZ-GF^d31o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcq zjPo+3B8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S z1Au6Q;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO002awfhw>;8}z{#EWidF!3EsG z3;bX<ghC|5!a@*23S@vBa$qT}f<h>U&9EIRU@z1_9W=mEXoiz;4lcq~xDGvV5BgyU zp1~-*fe8db$Osc*A=-!mVv1NJjtCc-h4>-CNCXm#Bp}I%6j35eku^v$Qi@a{RY)E3 zJ#qp$hg?Rwkvqr$GJ^buyhkyVfwECO)C{#lxu`c9ghrwZ&}4KmnvWKso6vH!8a<3Q zq36)6Xb;+tK10Vaz~~qUGsJ8#F2=(`u{bOVlVi)VBCHIn#u~6ztOL7=^<&SmcLWlF zMZgI*1b0FpVIDz9SWH+>*hr`#93(Um+6gxa1B6k+CnA%mOSC4s5&6UzVlpv@SV$}* z))J2sFA#f(L&P^E5{W}HC%KRUNwK6<(h|}}(r!{C=`5+6G)NjFlgZj-YqAG9lq?`C z$c5yc<iq4M<QwE6@>>d>VnA`E_*3F2Qp##d8RZb=H01_mm@+|Cqnc9PsG(F5HIG_C zt)aG3uTh7n6Et<2In9F>NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWw<V8OKyGH!<s&=a~<gZ&g?-wkmuTk;)2{N|h#+ z8!9hUsj8-`-l_{#^Hs}KkEvc$eXd4TGgITK3DlOWRjQp(>r)$3XQ?}=hpK0&Z&W{| zep&sA23f;Q!%st`QJ}G3<GjWo3u76xcq}1n4XcKAfi=V?vCY|hb}GA={T;iDJ*ugp zIYTo_Ggq@x^OR;k2jiG=_?&c33Fj!Mm-Bv#-W2aC;wc-ZG)%cMWn62jmY0@Tt4OO+ zt4Hg-Hm>cbou<7-yIK2z4nfCCCtN2-XOGSWo##{8Q{ATurxr~;I`ytDs%xbip}RzP zziy}Qn4Z2~fSycmr`~zJ=lUFdFa1>gZThG6M+{g7vkW8#+YHVaJjFF}Z#*3@$J_By zLtVo_L#1JrVVB{Ak-5=4qt!-@Mh}c>#$4kh<88)m#-k<%CLtzEP3leVno>=<rYWX7 zOgl`+&CJcB&DNPUn>{htGUuD;o7bD)w_sX$S}eAxwzy?UvgBH(S?;#HZiQMoS*2K2 zT3xe7t(~nU*1N5{rxB;QPLocnp4Ml>u<^FZwyC!nu;thW+pe~4wtZn|Vi#w(#jeBd zlf9FDx_yoPJqHbk*$%56S{;6Kv~m<WRyy9A&YbQ)eZ};a=`Uwk&k)bpGvl@s%PGWZ zol~3BM`ssjxpRZ_h>M9!g3B(KJ}#RZ#@)!h<Vtk)ab4kh()FF2vzx;0sN1jZHtuQe zhuojcG@mJ+Su=Cc!^lJ6QRUG;3!jxRYu~JXPeV_EXSL@eFJmu}SFP8ux21Qg_hIiB zKK4FxpW{B`JU8Al-dSJFH^8^Zx64n%Z=PR;-$Q>R|78Dq|Iq-afF%KE1Brn_fm;Im z_<DRHzm7jT+hz8$+3i7$pt(U6L63s1g5|-jA!x|#kgXy2=a|ls&S?&XP=4sv&<A1W zVT;3l3@3$$g;$0@j&O)r8qqPAHFwe6Lv!Cm`b3sQ-kWDJPdTqGN;N7zsxE3g+Bdp1 zx<AG)W?9VDSe;l&Y)c$DE-J1zZfw5a{O$9H;+^6P<9ipFFUVbRd7;k2^o6GusV)*M zI+j38h)y_^@IeqNs1}SR@)LI@jtY6g9l~cKFVQy9h}c71DjrVqNGeTwlI)SZHF+e( zGo>u$xr8UFki1L{Ox>G0o)(&RAZ;=|I=wN2l97;cLaHH6leTB-XXa*h%dBOEvi`+x zi?=Txl?TadvyiL>SuF~-LZ;|cS}4~l2eM~nS7yJ>iOM;atDY;(?aZ^v+mJV$@1Ote z62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~pu715HdQEGA zUct(O!L<Qv>kCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$+<4_1hi}Ti zncS4LsjI}fWY1>OX6feMEuLErma3QLmkw?X+1j)X-&VBk_4Y;EFPF_I+q;9dL%E~B zJh;4Nr^(LEJ3myURP<E(R5tF?-L+xY_-@he8+*L=H0;&eTfF!EKFPk@RRL8^)n?UY z`$_w=_dl+Qs_FQa`)ysVPHl1R#{<#>{Rblsw%57T)g973R8o)DE9*xN#~;4_o$q%o z4K@u`jhx2fBXC4{<mvYb-}fF3I@)%Od#vFH(;s#nXB{tULYnfLMw?Tb`&(jLx=+kL z(bnqTdi+P*9}k=~JXv{4^Hj-c+UbJRlV|eJjGdL8eSR+a++f?HwtMGe&fjVeZ|}Mg zbm7uP|BL54ygSZZ^0;*JvfJeoSGZT2uR33C>U8Qn{*%*B$Ge=nny$HAYq{=vy|sI0 z_vss+H_qMky?OB#|JK!>IX&II^LlUh#rO5!7TtbwC;iULyV-Xq?ybB}ykGP{?LpZ? z-G|jbTmIbG@7#ZCz;~eY(cDM(28Dyq{*m>M4?_iynUBkc4TkHUI6gT!;y-fz>HMcd z&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M!p0uH$#^p{Ui4P` z?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&GcDTy000JJOGiWiApj!) zBm?T9qW}N^32;bRa{vGf6951U69E94oEQKA00(qQO+^RY2ND!878?0(TL1t6yGcYr zR5;6xl0gmxAqWKNz;pIP{{J0>J*-UH9yRM}96`zgj4?iDmS$#EWxW8{VL5N2s&WSV zC8<|xvFHtelq$UM7@yzISxj7~3NO@7;KZg4N@fR3^%;{IS5-d(KHPY4uG|;)zfdXC z3EyG!vt!C(4@{JjxVWk+3qelh2XJ)r5M0DDdMW|8Q70@pp*{3P>?ufG9wyIp9+oGF zJp1F4mxHZ1vhJI+Z5MoldmS(U_bxD<qIdikYW{{o_di3500000NkvXXu0mjfEEIRz literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/gasBlockGreen.png b/src/assets/warpdrive/textures/blocks/gasBlockGreen.png new file mode 100644 index 0000000000000000000000000000000000000000..89d3527153c123a1e4f56eccc182e91c542f223c GIT binary patch literal 2993 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 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/gasBlockMilk.png b/src/assets/warpdrive/textures/blocks/gasBlockMilk.png new file mode 100644 index 0000000000000000000000000000000000000000..cb4181a7a901672ffb09c2cbf97c4c58e7799678 GIT binary patch literal 2884 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 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/gasBlockOrange.png b/src/assets/warpdrive/textures/blocks/gasBlockOrange.png new file mode 100644 index 0000000000000000000000000000000000000000..d248516c04a3cfa78b68e71c69905960590a32a4 GIT binary patch literal 2972 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 SunBYk0000<MNUMnLSTZ<k%>+K literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/gasBlockRed.png b/src/assets/warpdrive/textures/blocks/gasBlockRed.png new file mode 100644 index 0000000000000000000000000000000000000000..b5891426fabfd1c67b7100887e15de12ac8cd05c GIT binary patch literal 2978 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 Y3jk}KYd$F^3;+NC07*qoM6N<$g8Es7+5i9m literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/gasBlockSyren.png b/src/assets/warpdrive/textures/blocks/gasBlockSyren.png new file mode 100644 index 0000000000000000000000000000000000000000..12505967f22887cfecac2ab82d9b3ef7d2c90cd1 GIT binary patch literal 2981 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 bb;bVy70jIe4RF-m00000NkvXXu0mjfc%F@f literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/gasBlockViolet.png b/src/assets/warpdrive/textures/blocks/gasBlockViolet.png new file mode 100644 index 0000000000000000000000000000000000000000..824551a3892dc97d5c90588edd2f99f3554e0bae GIT binary patch literal 2982 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 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/gasBlockWhite.png b/src/assets/warpdrive/textures/blocks/gasBlockWhite.png new file mode 100644 index 0000000000000000000000000000000000000000..27fff93f8cecb87d974966f8d8cd81bccd54fdf2 GIT binary patch literal 2884 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 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/gasBlockYellow.png b/src/assets/warpdrive/textures/blocks/gasBlockYellow.png new file mode 100644 index 0000000000000000000000000000000000000000..dfe886e69b56e980e84c57a0dd19c1d05f3062d1 GIT binary patch literal 2992 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 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/iridiumSide.png b/src/assets/warpdrive/textures/blocks/iridiumSide.png new file mode 100644 index 0000000000000000000000000000000000000000..4bb39440c3350306acfd79f28dbb1f397c71a7b6 GIT binary patch literal 295 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Ea{HEjtmSN`?>!lvI6;>1s;*b z3=G_YAk0{w5<d|r$X?><>&kwYT~?G$e6RD?n?NDS64!_l=ltB<)VvY~=c3falGGH1 z^30M91$R&1fbd2>aiAh8kfPxHw370~qEv=}#LT=BJwMkFg)(D3Q$0figD*u3fvU1S zT^vI!{O?ZM$k(92<MQ|a{8x827K^(-t7~*$H;IqSYR3<@OEK?QnR0%6X6r7mzO$Em zh24{_32FPql$4ei-CecoUSsH|#sl{f6gQYS7zszLQV^M#-Pp@@c;<nvd<(dLG_dps g9V}#jp{m3lyJq<@rELshKx-L1UHx3vIVCg!0LYSH_y7O^ literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/laserSide.png b/src/assets/warpdrive/textures/blocks/laserSide.png new file mode 100644 index 0000000000000000000000000000000000000000..9f505881896d2a70b9b957e3ed3adc48befc3d58 GIT binary patch literal 649 zcmV;40(Sk0P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3J{N1{b|Uwb=jw02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00HqyL_t(I%XO1Wjuux8g+Ke= z>SPEZtbmNj3fLMFERU>!8AzlBG~(6b*;VDo$)J9^6Qo%3=v<%Udu-doN00UP-8;5z zr&V+|a}L1BN-!`PW(EjJ2#DB;2>jK>8}8oyon;wRiBhv|MZ`w6s1(^nq^NEpf~w-{ zm#=JF;IZ%geSXfZTelfLSii5(O{CE&x<w}_lWhxH@bSZYwsj*jnL@1V%8M80-2Uwj z7q8#44gr8U0!#vm$er#aW5;N^i#f*Nm*tFz;^p}T>l!R`Vs?i4!J{^$Br-8?_S~7n zQ5zE+^TBXq`PEpiinI9u_X%bv2GL!>6YxM?h@=~4RWl42lQ|u;1$@E$Dc4~De;$|` z7+?(oH#clJk}+hM+qLlXXTkGl0e~Br8;o)Ia!OYV30k7jjo|-9H-<PpWlBOV+@QKq zixv!ndw(o9b>f5_`aimuM$>{WAr(?U2jc#JOr+z$D4;NFz?o*J_LY3U`bOjm{Poiq zLE4GD!mOxD+`)#J&9QA+L2g&Lg9w^r^gtL=ffepeW}NOpAZK<Kk-_EVB~^9!K%GXV zgP;Z0bQP@zC29x6-1eQ1??2F;2&20W1tn&>HtS!1K?qf067$pN&)9ILFUO7>n1jP{ j!UEZeL<94t>xT6om(qljn4~gS00000NkvXXu0mjfMI9U4 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/laserSideCam.png b/src/assets/warpdrive/textures/blocks/laserSideCam.png new file mode 100644 index 0000000000000000000000000000000000000000..8e8b1accec8af8b7fc845641e873317696c1e9a1 GIT binary patch literal 727 zcmV;|0x127P)<h;3K|Lk000e1NJLTq000mG000mO0ssI2kdbIM00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc00(qQO+^RY2OSj# z7rjHZ*#H0l8FWQhbVF}#ZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b02*{fSaefw zW^{L9a%BKeVQFr3E>1;MAa*k@H7+qQF!XYv0006GNkl<ZI8Sv_OK#gR5Y;h~O?C-# z0b8Q@8Hy4mId<&0vS>=QC|M4I_6RND?h_z6Oz+h@bkqc0rNG00^LaCmLk2(2KOet- z>y9Tk49&rJ!?7F2rt^*WZPz<LIN!JEc7A8=rmBMe@#*{dJU%@|QFL>2V;XOrGp;jj zXWYTGy*+fbZA|OR<*Hn*gVqmi-(&Uf+uL6k7gtwT)&8(U*vZz$ZEIWYo2)33RA=Q~ z(D;74-(zpAMqFNA=4F*HYQ3oQa+jCeBwK<iC{Gv%NK|k*jySa1x7Zu2A$gF>B-sQ! zpd0gof}Rmd7^fhS@YwhPrLVp?Ol$pI6t6}3HlcXc`UQiKE@Q3;7lcccG#+}~&-h>l zscK!km5b9qpo>AN)-l&a$cfMnr*0grJ5}`&W#r{VxW4uXJm8#3o8A(xV<F>@3CGd2 z<F+0!hZUa?(oM`WteyzAJGy?bZdh0Tf09J<SJFG7>3ZC(vHt$^OFv^!B-5p1Ay5@Q zTyOE&_iehsxdo;_S*ysxSP&*+fWUf>AK_tFgUT7?*o>={R2xv(_+F?x20EfJCp=<| z2oc~X*%||B#vmaaD5Ml}E;W-m6&hW_<UHo{h=ehX7!NkPnoC6|eGpO>F%eRjEE8xa zP&OxY7Dcl#nv*z?c_GpaR7&~BP-Id7DgYI~9|-5zKBP3H^bekg;MIUZ3NHWv002ov JPDHLkV1nNgFY5pR literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/lasercamOverlay.png b/src/assets/warpdrive/textures/blocks/lasercamOverlay.png new file mode 100644 index 0000000000000000000000000000000000000000..c0de180638877733900986a71047478d44616745 GIT binary patch literal 2588 zcmc(hX;4#F6vuBu)Ib3Nbri&kU=b?<8Y)YGfPk_FtXg4&1j+z1I6z2RHc3L&3RFZ! zheZg{0-{BO3%ex5s$n`TVW|WqN`#geVn7<!0HN=NDUDwoXS(<y^YXj*opb)@-2Zz? zRv`YMj+T)Y06@pv%i~J`5YSfyK(B@_A&EDlpbIM6&EE}xySbk%gs*~FGr=pE41n%K z_=9N3i<Lo(MikE=%HjAZN>X@YBnS+TiKAHIJ&%}ti?RB`YLAW0Wa2d_ve4VZ?MN~~ z_JWwb{fQCpl`vD=%=G+^nb{^<N<_Q|yD)8|NUNFRHWpDQit8ae1qMD&*;RE<TD7OF zMLd+znfZD&`#NW9@`YhbX%mMq*qp*vDx}h>r&R(eb{zOy#^}Fx16TJT=sXlKS_e+} zeROzp7ZH>{NJqwSw49uPHG#7*e^WVL0M_|1W$d9-8<KY+Hqo|mWgo7$*b%s9*b-Nv zK-9&NDmvh5_ng|G2MXP;R3ni9<0U`p3c^-H_0XW*q~jO@K{qU)``iTBoc{PhT|yjf zqP&Is4LlFDD;a5%1&g}sfGG5U<#&|;KT}xq2|O^*gS)fc0WPUpy0VV$t?Hvgle-=6 zm_C9EGx#skh)nRO`~4N6da813x=EW*Vdr3(A`=wdAFjxCLxW<KhSPdrUj;nfHQT^R zA9(b-`$7L@Sh?{TaAzmni#-|<b{Ot1K@Z8j{tps0Ji=`i`ADLjq9sWQxs#aE991%1 ziF-0k_b0Ip2Nj0=1IxAeN)2O5v;5NkChxs{E?~5`R1B_CnY63Kt>j-k?l#4cr_dtL z>gQ`{l{13+s#`8>{;bE-e*Lno+7zu@No5{Q=yRqjGlc~YHfOzaLlf)W{Uyb&xXWG} zUj;5(%u>pv@p23#rpDPSe`Z83F3vO@G7UZBuCH?Com(vn26jH>KO|TzTRMMgAb$8j z7DZpzQ)OiCJ?dN}EE4&qV5AD736<o(XzHl?o-#$9CJ(980!f`_!`0~zZ*`gpRU_r( zVRc#{tJ7@63ej;oX!sQp7TmJr0*?SO?W>|Wb2XyPZd)NPZLR7>1ofndS;+&@bnpt% zak|>eS#h%_E0NGK&~WOMZl^}X=1lmA=!?*E7S!`~(GrJ5lc0oR8b<YWaUW^|TXWFW zAEEJ9w4@&hL@v2H+_nNz*<(q^+KtG#nSS6jOGFuf20nDlC^TSFs{GMe`hfF3uvU2= zAi+$^Nw8oBjGsgMFVoZm&pg>%X@?6zH!y%}1QO&dmnwvyca7*KkBDkFPiHYrJC9|w zt_JqD@Bg_G;c3=wg9RbjBo0jy;wY~(e&zf&2$@iM{QK>U#>m}_l;R81)EhfMQd6Ww zPZ4Q1!{K&r>{7n(cwUMoml0=}{SzjDl=@;~s#RQ5%5fn^P@!Ow4Zf~3CrvybGk%jN zxJ8YE7uoJ4M;w*!TuqkD^DsM(NB6v}h#rA5r;Y}mADsDB@GMapOK`Mf5gl8bQ6hZ3 zwx=V8Re`CTBFVlgAjpLhKSwOY?fzhl(iT{bslQc$NefA1r!k9|Kq#?Y|4S`dJYUcW zucopm9Bx-)VscXc9*^3r*4r-<Bg8BjvxJGoVOh))+IVuD5Sv6D8?2dGG?p#m>>$OH zh%JJiB424i=XG{0|6t9GGjTxdva(S_P5o5R`%FG1ukI}}doW!Z-Q4R33qR#*%`g-M z@P|_!i-n0JJMq=U1e(ydXKs=$7UOvsiO_j|n2<<SHtN%n0vF4IY2K7Cky+YW+bwCg zV6dOg8s$<y4aF|iF`1hY78J#u^IHq$Q{BlUed6EpF=D*9o)hmx-aB^8IhV!2Ip^Y` zu5+aIE|BWCAYe`}biQ=Lq4D>2f`C94w#=kZWDBz;B}_y9csex>QYg{b3k|ZYx2U^; zrgW}UH2_VrgS7Ng++8almcM>J$L8~MfN*EJE3cL^BCJ>>rH_-(#^TBpaJB&|l;<i} z;+|+FV^%XB)G+%3V(Z^9u(*0bUu;fn8q@kVbp9+xV;zkeH7+NcfiBpgYDe%v(1)#F a(s*c39~w>OT!j9~0dG&d2Wx-WcYgx1vP`o8 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/liftOutIn.png b/src/assets/warpdrive/textures/blocks/liftOutIn.png new file mode 100644 index 0000000000000000000000000000000000000000..5007960452e4537e8202f6540ed3ff2bcd685807 GIT binary patch literal 1318 zcmV+>1=;$EP)<h;3K|Lk000e1NJLTq000mG002M;1^@s66MgrV00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2QGbMlOP(1(u02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00fRnL_t(o!_AlNYTQN?h95~I zjg(!3L-Ql}N4zP)gj`Rdbv|yP&|W~B<N^}NE%YOIWQ-})HN^x%h_~yJR-^gokJV@; z?>f5<DRf|2kTmDadCz&@IVbw&+wXi?mIxsbLSU^WtfpzuTI0Rv>S~&Xx~>r)K73$0 zo$@)WswzYr#{it2p5AEly~zY;Eh0&h!NYA<a27=oq95}%C+RzJ)*?22^eN*$V!eTN zAFng&j3wT5+)v@+;nN1TSz;TsKg+<jDHWgV8NhqLYG7N>T_I_$Z|pg&L?nnT%TP)& z`TA=B0ynN(&bjX2=msIB1n<H7#b)oZ*5aJQIY+cOD^V2ToWoj6UC)W)WP!o%?k+py zF~zN0NGXYW+;6N!YrSyLF6$h|7|OC_I-MevQW#^10Ba0^o!&c~^KDoWQM3%rwHYu? z8$ux^Z-4*oMgSf@e!@S~X%7S7`yYP9ng*>Kj4^oc+H}PTA;_|nM5MfV{facp$g&K9 z_ua9rX*m7!6m@w?t#zl5Ns=J5jL~?^<o=|47KKU-p0sXImzRuoc1Y@aU?7(gHJhPz z(_uu=g8-H>hWUI>l4bmHa)L2tQSU<V;NXDyeBM2C&f}~bma?@L*VchChP!)v0K7Xt zAH4hT^dLzR;wU0X5`+-EJ3sG2=)YSr5XVvXVV>vYQu5&7U<E{*=LjJf><M`W$g-5t zc#N9OR?=v-W;7m?WocI%-g|^?*|nf&%H;lJV<82=t+j}%ERk6Tz?;{vwg#`!8t2<I z&XnTt@e|T4+ejvBEsfU9l%l*;ix4h8exy{2EKMPbaMt3z$N5$dX!XE5v~DO%h4WA< zg~;=qukPF-&vT^AaL#wC)HDrEuRmBA_1w0%Da(?gC=l=8zh^d^bqz+ycXUPCymNyp zHO8QnTJ{HjpPf+@1yV}VG(`wO94!KH-eZjEx{|7@xVyKv><@$x6h*<o!-wpQMguVW zJPF{P93LZuSjf6>#Z*ek&S<nznGPR6K}y*Pun1C~rYUJ#4?&swbnYurnx@2YyzCF+ zIPL%p%5?VE8S|<FATJ8`Crc#~LJ-F>&e$c0{bh_{URCVu?gB8oxS(nD>eUv<UqBCB zk4)V|A;^n@*~LW{LYii4uQ}1(bH*&`D^m6+lkV7Qnh^(l+CmDBI|HF?H?gwOnx<)R z&MovHT%vVduVv-BLaOU}X+Ud@F@~zDI5|EZl=9Wg^h?<oGwcuU?(KE?4Zo{^g<rtH z=mwFdDY~v#jvF?G{=j?RZPvOb&E$ei<MEh#`}_aHd0`y}Tg?lBSbZR`f_Lq_5XUj^ z&d&$R)Q>kP(Y5nJP^O2E9x)n?$fX2eUe_q4I6gWW)W=|62uGGuG8&C|`|B@5C3^a- zQ=%@ktMfuorr`Pci<dlq@p8e)Hl#kdU%o#Gtem%%`TXafx_9%s?pV0iK%bRLDGr}L zTLCe!ux~_MWn5KN93LHBo5rBjYv%>$+zKn#71CDo!lqJQnHO#{sdOQ)(}OS*TsJQ` c=LUN4FSAf*fkOjB7XSbN07*qoM6N<$f;#SNM*si- literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/liftSideDown.png b/src/assets/warpdrive/textures/blocks/liftSideDown.png new file mode 100644 index 0000000000000000000000000000000000000000..5f6b3eff1fd39ff29603cc1ac8a044641b479e4e GIT binary patch literal 572 zcmV-C0>k}@P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2QHaQlY_%{Fm02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00E>)L_t(I%bk<KZWA#SMbEQ6 z6HPuMO*g2Yfm8&Gs+FKg;U627J&1n^-KQjr%*6Jy&7zqhO$iIGWXbaLy}tK7S!SQV zl(ubg&f%ORr9_VyBOwGzDI6oli1!}1TCLb@HvA8|uEQ8(PF{FiE_qxoPu6ov7;EiG z^56D{5E0B_=3~NSI%P7Qo)pO`Vg5z#aZ02JxMP9Ibc%?)>ipUH`Kz<6>5qVjJZBOa zF8tiTcy{0>mqO_mdj}$dF$QA{)>@1)lu{UtMgUZGjfjwQCZ$BqnVd6l5WyHjRaMkg zg>@D|cyn>_Toa*CNSX*S5@UQR(A&4x^5gqA06xv;$UaUfg@?sG0B<kfp{hg89MARY z`UZf9#XZfqp&2&=`Re*+Aojv?`Tj#$uh%%|sOy@hX&8?izAhFoI{tAsqis97t|Nqi zs`BgU3DbX;oHMG5_a49V+|KU?^6mT%zw>zSQB`uzlv1$H;_A9)yWKu_Sd|F0KuT$d zqpJ82h#`>n0stB!uBs}6_d^eQSZe@5_On-2VvKv2JF0p_PKn>VQ};~n+NgT~0000< KMNUMnLSTXcjrC9f literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/liftSideOffline.png b/src/assets/warpdrive/textures/blocks/liftSideOffline.png new file mode 100644 index 0000000000000000000000000000000000000000..f05d96d3655132e25fc97be6fa15ffa5e676a5a7 GIT binary patch literal 366 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}HtrVM81cRZ>Fif|Tq zL>4nJa0`PlBg3pY5<o%r5>H=O_PgxzV#WfRkyGS=LXst}5hc#~xw)x%B@E6*sfi`2 zDGKG8B^e6tp1uL$jeO!jMb|uC978Nl&kb_SJ8ZzSI92tx>qK|n8}sD9%yZ`ROxQW8 zOyZWL<CL<eCnxxHDNV84zppkn+`xE-<f<;~thEAyJFLI0*t%#6)4XMzpKTt?=G<me zTJ+&?sZ62l@eTQ_7R)L3u&dhcq1kwA?)R3{1`mvQ7Iv&`I(MSnMQI+xJ?<?>(o1*C zTKw?u;G4s}hsiG6?e&%g;koXmUCZR|9=tbkw|x4AE|(|A6+2H{{<~PmD81nR_lRjv z*9znZ9gMy1==IZ@&v=E_8J@JZFRw*4m%95dS@7CEVbu@DK-rEm<6|YCfj(sLboFyt I=akR{0FzXT%m4rY literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/liftSideUp.png b/src/assets/warpdrive/textures/blocks/liftSideUp.png new file mode 100644 index 0000000000000000000000000000000000000000..57076224127dc75b05bb9e2a2cabb10b27fef401 GIT binary patch literal 585 zcmV-P0=E5$P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2QHY$=Lx#<7^02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00FT{L_t(I%Y~CmP8&fGhQEHy zG|m+w2ksIH_QX!IK=S>-2nob_z{%RkUU){+kE$$Y#&H~z)UK=R|GHjnX5YSR(=>SR zsj3PQ!8wO>4iO>7NGXM!Go=(%6;&mrMAvor^?J>AyTurTv$hA-HKDHY-UE<xri+mj zV-FHRRcYH6Z><HuT8kURA0`tflL_~Cw*Y*Zf5o*e4WNJy*+?l^=N!fu?C^RBfp8Y~ zVu1U*Tf$i&gn;)RYc0l@URO%lADnY|=Xh8y0k~N#xLGU!cvvp+LvO}-DFw@csVdJ; zj{scH=Cn;q+q7KI<^ViDJ))|=;|-Y4msh&kZ1z*As|x2G27?U2))*9}<U&k|loB~- zHg9kEktQOfln@bYvZyLQS1SOf=jVOOB7O5j`V624s46myMu$s)uIm6uG46db?7>)y zKdfI>5x^LOs`7C<?e}14^kMy@`D4eA*H-{OU0nR(U%kAX^xI>=7%+nV1y$9*0mqQ{ z#0;g{c+j9zkoUv@&O3Zv*X(w?|3Xe#jtO5?6>%8XxDVs3MFi95y5EETi+5CYKuX~k XldTAEVt8pa00000NkvXXu0mjfe`EG? literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/liftUpDown.png.mcmeta b/src/assets/warpdrive/textures/blocks/liftUpDown.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/liftUpDown.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/liftUpIn.png b/src/assets/warpdrive/textures/blocks/liftUpIn.png new file mode 100644 index 0000000000000000000000000000000000000000..5007960452e4537e8202f6540ed3ff2bcd685807 GIT binary patch literal 1318 zcmV+>1=;$EP)<h;3K|Lk000e1NJLTq000mG002M;1^@s66MgrV00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2QGbMlOP(1(u02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00fRnL_t(o!_AlNYTQN?h95~I zjg(!3L-Ql}N4zP)gj`Rdbv|yP&|W~B<N^}NE%YOIWQ-})HN^x%h_~yJR-^gokJV@; z?>f5<DRf|2kTmDadCz&@IVbw&+wXi?mIxsbLSU^WtfpzuTI0Rv>S~&Xx~>r)K73$0 zo$@)WswzYr#{it2p5AEly~zY;Eh0&h!NYA<a27=oq95}%C+RzJ)*?22^eN*$V!eTN zAFng&j3wT5+)v@+;nN1TSz;TsKg+<jDHWgV8NhqLYG7N>T_I_$Z|pg&L?nnT%TP)& z`TA=B0ynN(&bjX2=msIB1n<H7#b)oZ*5aJQIY+cOD^V2ToWoj6UC)W)WP!o%?k+py zF~zN0NGXYW+;6N!YrSyLF6$h|7|OC_I-MevQW#^10Ba0^o!&c~^KDoWQM3%rwHYu? z8$ux^Z-4*oMgSf@e!@S~X%7S7`yYP9ng*>Kj4^oc+H}PTA;_|nM5MfV{facp$g&K9 z_ua9rX*m7!6m@w?t#zl5Ns=J5jL~?^<o=|47KKU-p0sXImzRuoc1Y@aU?7(gHJhPz z(_uu=g8-H>hWUI>l4bmHa)L2tQSU<V;NXDyeBM2C&f}~bma?@L*VchChP!)v0K7Xt zAH4hT^dLzR;wU0X5`+-EJ3sG2=)YSr5XVvXVV>vYQu5&7U<E{*=LjJf><M`W$g-5t zc#N9OR?=v-W;7m?WocI%-g|^?*|nf&%H;lJV<82=t+j}%ERk6Tz?;{vwg#`!8t2<I z&XnTt@e|T4+ejvBEsfU9l%l*;ix4h8exy{2EKMPbaMt3z$N5$dX!XE5v~DO%h4WA< zg~;=qukPF-&vT^AaL#wC)HDrEuRmBA_1w0%Da(?gC=l=8zh^d^bqz+ycXUPCymNyp zHO8QnTJ{HjpPf+@1yV}VG(`wO94!KH-eZjEx{|7@xVyKv><@$x6h*<o!-wpQMguVW zJPF{P93LZuSjf6>#Z*ek&S<nznGPR6K}y*Pun1C~rYUJ#4?&swbnYurnx@2YyzCF+ zIPL%p%5?VE8S|<FATJ8`Crc#~LJ-F>&e$c0{bh_{URCVu?gB8oxS(nD>eUv<UqBCB zk4)V|A;^n@*~LW{LYii4uQ}1(bH*&`D^m6+lkV7Qnh^(l+CmDBI|HF?H?gwOnx<)R z&MovHT%vVduVv-BLaOU}X+Ud@F@~zDI5|EZl=9Wg^h?<oGwcuU?(KE?4Zo{^g<rtH z=mwFdDY~v#jvF?G{=j?RZPvOb&E$ei<MEh#`}_aHd0`y}Tg?lBSbZR`f_Lq_5XUj^ z&d&$R)Q>kP(Y5nJP^O2E9x)n?$fX2eUe_q4I6gWW)W=|62uGGuG8&C|`|B@5C3^a- zQ=%@ktMfuorr`Pci<dlq@p8e)Hl#kdU%o#Gtem%%`TXafx_9%s?pV0iK%bRLDGr}L zTLCe!ux~_MWn5KN93LHBo5rBjYv%>$+zKn#71CDo!lqJQnHO#{sdOQ)(}OS*TsJQ` c=LUN4FSAf*fkOjB7XSbN07*qoM6N<$f;#SNM*si- literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/liftUpIn.png.mcmeta b/src/assets/warpdrive/textures/blocks/liftUpIn.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/liftUpIn.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/liftUpInactive.png b/src/assets/warpdrive/textures/blocks/liftUpInactive.png new file mode 100644 index 0000000000000000000000000000000000000000..3a14f952be420ad3c2d5b3d7cca781c15045e811 GIT binary patch literal 352 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}HtrVM81cRZ>Fif|Tq zL>4nJa0`PlBg3pY5<o%r5>H=O_PgxzVnznsI<3=zLXst}5hc#~xw)x%B@E6*sfi`2 zDGKG8B^e6tp1uL$jeO!jMJGI6978Nl&z<C$ci4c3#a-;}pG7AYb8R`#U-bPT`)vWy zAX^r{%U23g&QDxWHeKZK^Xug^mvIU@x)>OX6`fn5wNxbTq~+uwr(gThCD{55&KqAc z;bpjfI`#VF{?C%;&PhG>U8Xu|iY!kmpUqM^ua?)gC;OI=eq(9l)@P=H`z6or-Vt4` zxj{Fe`AW|32@Y?kp9)NG2s%~Y81?+P;>uTf&s#MFU+(HFlqt8=zhk1DdwY@QU%7Vc sw6@)k-?dbSIdSyQ%3Ac+Z-=D)qW+v+U%YJ#fPP}|boFyt=akR{0Nz=HHvj+t literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/liftUpOut.png b/src/assets/warpdrive/textures/blocks/liftUpOut.png new file mode 100644 index 0000000000000000000000000000000000000000..cd54032a3748aa8adb9c5603acb8c636c75c41fc GIT binary patch literal 1353 zcmV-P1-AN$P)<h;3K|Lk000e1NJLTq000mG002M;1^@s66MgrV00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2QGdBBF5#s;=02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00gl~L_t(o!>yO!P8>HB#y^ie z_6$Rz;)-wqONt12pGs{a@(fjb-zrM(6Xh9-+DC$-O0Y#mT!6yDdS=Iedog1(v%A0+ z;X8KM=NzB&eLoxW{SQC-vMj+E17i%<T7;#whEfXNdrU8_HR`$sySlo<Xf(o8R#jDC zNs<5n{y9DUUz;}v12}8JD5bp*7g-@0Aq1>@=0z&$CUMq+J@%uAf_sAb0p|U9UQlN& zlE=z@s4pIPIKU!{Ez<2L1z2>X?5UXnz<WO%VA0G`NJ^>r$JubW@J0ZjjDiUvP?jYI zFJJb)e5h;yaL&PM1I9UrcMc!~!C2N>IOpJ;18Jgy5YlY27L!Q@lF+6HOG`^wfAQk^ zc`$vHc|qp#AZ!euN8LNu3pAGpTie@6k_41eP)cKvaQ4uf;mOG?4@ld@i}Q2jc@EAw zIOhNWr4*D>sHzI<8ym6886Hqdk>@$~UcW|B6c9oH0P4DiloCgWhv-%uc@VNwO2Iit zQ55*&;P+k+-tNBx=R6*b5HibyBuT(IkD1?p_=xu(J^}!Q5a68mn*01baLz#~g}Sbr z3V!=FeplBulv2psarOdu@8hVHQjk*O?f$!&CMu=kD1#n)6<BLgRTYj75APjgSL!_; zgeulIHfDsBPYEex@9_Wth9@TrOF8m@a}Fux42c#olTjKhO;f10>s{U7$Ae~4HBv4b zDX*-o;Jck2WLX9wIGpoH+U(jG=nfB@_we4qT8FAEQC1b$<>e)AZ*M^<MVh8f^9TW% z>VbC-&U;vEp|ys!7E;PP9{hWD)^j1FH1@%J57TO->&nQ3;KJR#JuEL5;3=Ow1*H|n zV~OLVBhWShbIwH<E-x4O^Wfk??Z4UIkFG=zQg9(p8|D4<^Di*Qz!=lWwFT~%&!50k z9$nev0qZEw7=yFn5Y=STC^5^hxjl#i3;l7%-Zil&5MxkHCRkZr1pwTPM$k&nk~>MB zfd_8N-{H)8mf@zoFY+uy%G22=j&pZBFs*z;fX(eeEIZ{XXhP#AV{M-Yfka9-&iwNE z)4e4tts<Gc_h7!2r&5hb-t6x`Dx^Rr?|s9AK%(QLqn?y|lbMpTwYK3wnx>Fa&X8yx z52neaYt;m(CzIZWz`ZUH0`iP8P^tz?d1I!vwKaUZx{55%k!1n|q$en)HPE4vF$UTg zRAq_L%?+58vdKuA%Q7_2d*6d+d>2s)>nwcx$Y4SUBnf%ch4WlFy1s4#grb8Bl~ORq z^zqGDGo2|{GSWe~F$Tla6G$mBnbdG?GZRXYWdcP}U~8})U6~MaC*^PhNhz_k{0(Tz z<1{Fx5JEtXZxQYh@BJMQLI7h7s<Hx2IsQKW3&z;i8x%XcuTYg$gpBvT;lZ?AgS3sY zSl`$H09>4(N9j(x_j%t3LBf<$Fh+54ejbkyC_HU4*1ZQAW5}0s2qCbu`)a0%b}0vA ztao?z0)z*a9N*52(Q1XFDB_!ewEpP*-^dul)?oWlA;nABIk2*-AOwGuMDxhxTsy{j zB)ZQ`T{4xjY^Z$w^(#s#k){lUByi5cIY0M(ptVLR$8aE!<1zjN1vPY@f%1<W00000 LNkvXXu0mjf+*D!p literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/liftUpOut.png.mcmeta b/src/assets/warpdrive/textures/blocks/liftUpOut.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/liftUpOut.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/miningLaserSide0.png b/src/assets/warpdrive/textures/blocks/miningLaserSide0.png new file mode 100644 index 0000000000000000000000000000000000000000..fad0939f59c8e69ecd192c5ea73bb98a8678fdaa GIT binary patch literal 545 zcmV++0^a?JP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2J7$j|K1w8-&02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00D_fL_t(I%Z-u2Zqq;zhQC>_ z*J)Y~6tz`VTIvdMtpI_d+>j7Y!!vL|;te?SJUjs9jF3>(Hc~H1)!4f`9O5MF*cHrW zz5CDn^UYYEot8S>-ezk!M8q*Do-?n05#t;PEJI|#qn$C+*>_^Rqby5ypX_3kbreO( z+37c&JK^=qbH<|)<I#vg;V9fO$46f%inCR|M#ZKEb$!F1%g=a!gS9WX`1u2X*>p;= zb<5TDSL*tjG)#KQ^F59ZKatx5oXc8?Hhav${zvkBe_d=0CNl<AZ4uP|iV!6!7kuav zh{(eP)%@<C1Pz7s5_qqz#14T7Q5BPAwwECNg`gdR7y^^Y1bOx5t*&u)aPBEp^_x74 z+~3a#ArNC=Fx<oChg9_?F;0{1K${g1v8aYVsT20y`wt77mf!kRRYYVp%1T}ugcv}z zsgaflEDRcH(PFuDK?H2@9!(}mdUfuSOs>s~^&xCLOOH`guFbc|>afB4jdjXKf9>IF jG*N7fk^c_^wDbQ0SU0#r1Uzm@00000NkvXXu0mjfES%;W literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/monitorFront.png b/src/assets/warpdrive/textures/blocks/monitorFront.png new file mode 100644 index 0000000000000000000000000000000000000000..34244816a752415412a58ef367bbebfe264236bb GIT binary patch literal 488 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85p>QK$!8;-MT+OLG}_)Usv|K?6RV4;(ML9-UJFsmbgZgIOpf) zrskC}I2WZRmZYXAlxLP?D7bt2281{Ai31f$ffNPjr<If^7Ns%-BxdH7==r&ZD3lrN znd%uD7<?&O2y~9Tr;B5Vg@5m)-F}A+L>$&1y1u|`1^1JOH~4Z{MV(4A94oI}_mfim z!K(5@ENxm}Pfkxy4gYpSU*}m1ywW$UuYKoiW@Ed53V**=eCjb3?+~@{Wga4G9V;(M z&f+Qcif-+;n0NO1g44f)&%b`0Vqqi4leO%+`GiFanH%ySaoqb|kl=eLrHYmFRg{8E z#p|TE2edgq)v%o2qtIA%#m{)-(jqga$%33qMKyMb+Wp%kTq76g&FY)BIMi;}$D0ZM z9%om1|5%m5?O5Mhrx^D0p>C+?lzYNaCM=G|3EnRf)IB&2AB8QrzOdP^PX3%Y)4NMO zEYiQGpS}LUiEr~!-L-sA&hRVj+9C3|Q>It)d7MPhMF$TxRpCii+qmZ!n<wZc>m}RE YU){B~XTHxfV1P1sy85}Sb4q9e05~kOFaQ7m literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/monitorSide.png b/src/assets/warpdrive/textures/blocks/monitorSide.png new file mode 100644 index 0000000000000000000000000000000000000000..381f1e6d8b16727bdc7f9d39b7d4c8ef62b99945 GIT binary patch literal 440 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85p>QK$!8;-MT+OLG}_)Usv|K?6RV4;(ML9-UJFsmbgZgIOpf) zrskC}I2WZRmZYXAlxLP?D7bt2281{Ai31f$ffNPjr<If^7Ns%-BxdH7==r&ZD3lrN znd%uD7<?&O2vqgn)5S5w!hh<-*Ib7Tc-($lEb7?4lG*WSCs)_M4~K58jkIomq0RB@ z%`&$vbt^R)H}B$4OSO03dw27v(pSTvuHy<*r)fPEvS^s#$)eTd@*wPx9*_BLUGGho zYj$d#Oxl{pB(g54_D=T-2_0!3_a0{_rmsI-PrrV2onxb4p)1q7*ggCDO>WKQS3Eq` zcS#rjhZR9<_p<P*HMTI_YYIq{nEl{UpG(vA&&8Y}Pxzdlv;<^ni#$;A_#FLT!qevd z!Y3YI-6pp(glRm`m6^9xBSF1JmgW4uPeNw9ZNF+TXXV(;=5KzPA@pS3?a!P!nTD2E aZ!z=ixsdYNUt}-P>kOW*elF{r5}E)g*rcHV literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide0.png b/src/assets/warpdrive/textures/blocks/particleBoosterSide0.png new file mode 100644 index 0000000000000000000000000000000000000000..9b717a8543c2f48e7d55721517648d9c09c772f5 GIT binary patch literal 1412 zcmV-~1$+95P)<h;3K|Lk000e1NJLTq000mG007_!1^@s63Ss7W00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2K2N;+olW70|1rbR^ zK~!ko?b*v~RYx4a@$a0+z31lU=Aj17`=NQ*1`UD=&5aSd>#l!5*V(q+wP0Im(Z3*z z(t?XZH#L@8qZTEFYP%@)kyHuNAm$yDo8%@j$$8Fnabr>oO>WYHsmu?C!yGtg&irQP z!yHC*b#<wwr6p3S6k!;$S%hJT>$;4OkF&hIOg5Xva$T31xq0RnmoN<j0N?isf&jxX zKnM)Oz_x7+AwUQUi%SR<kj-M*woTx!B4RP3wU(rm2qi%(gb)Z6p%<~ZxX9}2>Us&o z5X<*{4%NIz-!I*uKmk&MQlOMXN{LbmDHTeZ)K+!STz`_<$~XC{=NO`^t4j?H4dFNr zK@hC>*ECHA9|cGm(b8m-OeS$%mz9+j78VxBWHPxgux%ULDPV440n0K0P)adAGEC;R zLL$%SK(?4rK|CJEj}-BOLQ3{Rb~b}$Sr$PM;CU{dw~_H!qJZN2b10=)+7rtq?Jp5U zxr|w!=OKh39(Qn@I4dhFD5WSZEhUvoZH&f0gazO@PA;pSi=iY!2n+#<f&@xA00<$7 zq6pV@@xo~11wjy?P!I*&EnR{|porWx$&2-(+(Ts}ixi}C6~ne|qA+}61hxv-bx|sp z6yy2y-K?K~55q7pO%o|4Rv3nOzK@g=B0#>7>fF8OMGBA*i^Vo_;JPkh7-HBlTBakG zmzN2rLRME-@qHiP_t#q#LSWlACFK?C3(tD?>=~Zx;;l`BctH{?ig1#J1ip`HS-JHf z#Cofq=Me-!ZYDl{{Fu49xxD)?)>fyK62maC(&;p>fCq1NeoJrPIYuY?xAZ`%B(+s( zPPBD!^QU(=_u%263$Sw!W?NGLWT%~-c~Ek1cFlvm+5_!@_8=b*8f)LDu`W$--+4wR z`nU8zsswda#~7Qqq&?6cXb)a74^StmIq(Ke^&MR4JJ0agy)8XZN@1JBScyae)B26c z*$0eFb>k$UxzWHhZ5|G~n5MCb2WStp2ik+(<-yoQg3A4^G}fhQYUtqmo97rFznhl_ zdVioj&>p;c9!MEcU4E29b!nO#I=Fn}Gls|S<+nemt@hVE=x6k4Kci2(Nfn!j3H1Iz zd!Rk|e|ms|s*0mD*0s~zaEkA4e9Dv2yW8;~0CFZwWIjjG^6xyDetjJFXb-dp+Jl$l zfdZ-yw9#1KPRqegdaixM=)}NwJOCJAa`quD2RpGUW3-kyJM-ZBm+b%?e>=4^4=PS% z*F3Pa2igPe!A?Ao5~|DFXlm%7<zOclubyFKd|*2s7?|cD&;dY6=^s>9?c0F|w?E8z za7}xlJ<uM!JP(wD>WU*Y)pyWT-_E7$XBipm-;M`1OA8=nz>mMaLsfN>ePu=4^We$t zC;ZHHy+6<%Xb)bx2TDn*%a5-8JDj5D>L*N2_2=)wouWm=C``_N!J_*$W&2%{DLa1; zW^Oyo@Pqb1d!Rko6&^?_si|zEv96udCpzir{g}Dz{ro)uNX-wj<c)Ca&IJmKR;W^L z{vH5i-ww0~+5_#uuJAx9MNLH;O$}*U4s~*|_YAZ1{abs`pIt`y(7M+lnH*(i;R3_A zx{+#uL_7}<G9MJ6;!xS0+?fYuXP<juXb-dp+Jpbf11S}?mB%^KlIC#ZX}-B~hRLbR zn|ttJa23N89BzuQoi7YAGBv>OkIs|HWOBo}nFn*NDHMwAbV8puY7cg~2Y&(*p=ac$ S^eM0a0000<MNUMnLSTXd_=>0i literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide0.png.mcmeta b/src/assets/warpdrive/textures/blocks/particleBoosterSide0.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/particleBoosterSide0.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide1.png b/src/assets/warpdrive/textures/blocks/particleBoosterSide1.png new file mode 100644 index 0000000000000000000000000000000000000000..1e8ec965d4b3de9fa22ad334c0059ec77cfe6c16 GIT binary patch literal 1413 zcmV;01$z34P)<h;3K|Lk000e1NJLTq000mG007_!1^@s63Ss7W00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2K2`x|+dc*(#1rkX_ zK~!ko?b*v~RYx4a@$a0+z31lU=Ai~P??m&k4H^U$nj0f@*IoaBuCpq%-L+s_Y0*X3 zDU=pm6uPOg)Ec!Y7OL%{)JIY!NJY#$nw#V%G0Az(baAhV7Mk3o1yh+H48z%+IrE#D z55L2R?(S~2u&_WXl_Cs7)`~C;ab1_Ou`w1G7s+O`Sgz|bH8acX`~s$70O0#RK@eaV z1_*&+7}&OrAp{6PacLQ$0<u{w+qMbZWkf7Slpje-iBJ-xLI{CC5qc5x^Ybh(FR!#P z46%IQXK(GhT>Z5N6evJSPzsciNGVZDA*Dh|le+3oS{jZ}SM@qy_Z~!acXzA%_wVC4 z4nYvC%-1wc2JZz(8PVEolT0RYU6-Y$CFbVl$Ye6PFR*PJ+bLpZZVt;b0Z>XYHatY; zm0}{#XIHkAP(eH%$Bz{8qGHOnLv}iYWmy(M5a4+(p0}FuSfYs1+cPMoSlAZJCGDAr zqFlx-&+`yM5RW@JPMoEsC6rQ>mzR@DrB+wtAHo7~94D7m&&5y@Aq0kiL{S2z8~}t6 zL{Wt6x_Du<`hp+`P$-B3Zoa($p93YpJdn)yCC~Ig#qc~usoaBM+cr@cKDPqvh3mQ~ zl}n28bo;I~&%cLZ7?`GsloBfpLp<L{N}1n=&!rk7R+|(cAr_0R=D>Ab!Z5_JW3+x2 zvADQMI2p3Myo~Sr_`bg~q7VYxwkg|PxpMHVCr_T>xh`IQ6U2*>SW$$NEGF=MOv}oh z2O(BQ^*oOt2y#2|!Gj0P%*+%#e~~|(Qc4WNz)GjnyaXP+(e)jDS5GoB-oLH~N+qeQ zPII`ulPf>Jv$h9!2VH>8dobOW0wDX?*_;Pux2E$RY}X!W53~n`c+gb$9!>RW`mUa0 zc)WjI52Q*^Uwx3#@w3_k?Sb~-CG!AvgxX!N(cI9<`KzZG8ojly2TCbya|kPuNMKsO zGckRK;mIDH1hh06n5NC$K^N0B*6;xBf%ZUqu(doG9ZyiTvyG<uG|i2j{BY$YLt{4! z@<7)I+5_#u%jbcV5jDFHu(v)<OJgVJE`Q3<*sa3qgSr|&??FE!kNO#T)I+M&M2w^B z1MPwK;Q#3X3aTp)&{W?+OXE?#zx)XgM{aJ!g8;~xFrN7WLF>Qs;PI<tuuXfQJ<uM! z7!MRsy{nz3h7MZybkTe9Lq^62HsS%m029-9Y2DL>RTZPH%-Ng=m%i!%;Lw|?&3RCH zIGgvt(jI6Jv<I8<KuW0D-A;33C#`$BICJ4R!(#&*@xZ_|2Z2ri%F6$ws(QyJJh=Wr z&V!5E1MPwK;Kg~M6x3Air@5h%=7tW=UOK_>X#Yk$uvwS`DFc4`?JcTnlI*A`*_a0p zuRr7$F6sI}d!Rjd;T|X@so8xX|L<^=-U}ZyG1*_Z2RBOQ5hE}${U!76H&pC&Nv7<= zJ(#-gFvXAB1MPwKU`u!)rKGm1ou>K@jvelzx9=lnvbPKO03bCx$bvV_wHv1?E?J^l zxrKWGkbN`I9%v7=2V24er4+T5?KC&0Y2Dk!nZDyp&-SnHL4S4;;X~VYhh%buskze( zUF$)rITG;#JjlFXgo;B|PjYh}RGfI~fuTLn9%v8#D-Wbp)Kwi~e`}h3O~?55{Bb5G z&#mpjoxx=cQ?Rc&p1)tX&+y~`f80AoCX>l6<60ifw53oevX2w`zEOLy#Xa~7g$q>N TUdCL800000NkvXXu0mjf!tRtE literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide1.png.mcmeta b/src/assets/warpdrive/textures/blocks/particleBoosterSide1.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/particleBoosterSide1.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide10.png b/src/assets/warpdrive/textures/blocks/particleBoosterSide10.png new file mode 100644 index 0000000000000000000000000000000000000000..7d8b2e1766c4f6e19ac2c343c7ba127958d7bebf GIT binary patch literal 1390 zcmV-!1(EuRP)<h;3K|Lk000e1NJLTq000mG007_!1^@s63Ss7W00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2K6ALmm1>yhz1p7%u zK~!ko?b*w3R8<_n@$b2hnLC|MA3y_rKcEk^frbP~?39wYbLSu6x+@cPr6#CE0}Iz( z7)@B1xRGK+3K&RD1YH<;v_cwUL+HEEX*+Fcd!OgHn9{0=?X;Ru$@wLBdmg{vIiLJ) zj_B&@Qj3d=q*5uuFl3_$!w}bX86O{KX=#aUHjCxDF4MDf%q=Wp8U_Hq?-K+8hGBpZ z7>0pu+ZaNC5EK@d5Go*>#j<Uiz+FMaVnnMmNhuLZf>a105GX<~Vqsx{m6esXFAPI0 z-}gCC^EQ1ycY^{2NC`@TQW7a8N-3mNC}~n#)j@OpacV1H<;$KUh_0?KH8eDY<2VFC zu(n^*G#PvlAZ0{LlT9+2#C2VkmzSBJpC^;a<W^wYHnvm1?EE~IWdfj-Vtizn%u9tt zp3lB)F`<HZJdPhJ;su42?1t=22FtQ6f*`>2Ts&_*<FP~m#dl{>O0l>rmP^{7B8qYu zvpmm32thpV;5c!XmzPmWQCeC`DwSHV#y^Aw;5be$tDcLYBti%b0f~YHN;v=sA&8;~ z*LCs2XnlYn2v8`90&c&#NIp^a?g9m=A^;5Awu!><FBRA<T-QaZTvCi@$9JQB{yhxC zz%)&yl(_*s-$zQB_W-e2Y&{3A>k@_`h8?5j(}<;|CBiUdWn~55_wjvyZAKvkwrx{V zUa@xZtfx<(;<+x~>LG|1B(b6hCs|0~`<RxMyAMLF&FXm`K@j9l;=_jznVp@@d--DZ zc1kHR3<E2jPV)kI@LK0L^!A-$bfSM#50pw$Tb1TmTL;&Fd~0J5?hm>E+xK9mH3dNS ziL*TqO76_8dazr2pgqtY<l{kO?K?EqrRnWE%g99krXEO@pswl&V-pv&2igPe!3*XA z>Nqv~UZJVJgG+s986LZ{sRv3aY;zbZkw{=#zcM*<kCCZvoCGvC8knZd{XrMgG&b-6 z?Sb|{d$6-S7@J5?xwn<Zx-?A<9ej8F48!BM^YTFV2igPe!HegClo8eChdEG}rn#Ym zi`PD3c>GR&{XuQDzv@9hqmTO;ecVl|*hEaA`vdKP_Tc~N0Sc-r4%1lIPIJQvzP<J_ zk4A5A#e)FInJ|(03_;7k^We$L<FHG6pgqtYJRc7fP_?g(#`<<z_IJ{A<pV}12Dah> zzyOmo_i5SRiB%b+wZz$;2Uovn2jJ-IsqJ}CaV)#)fu%jr9%v7?<AIb=UEW4hLkBJU zJ2`*(6eHsUTk*iaGzWnW07^=Kr?P6#Haxibe$Im{+5_!@_Tc$>pcGVB9HObdgQog+ zE?hm$$XNeYJg`}u2Pp%7_~i|%s*~&~E83a|k8VEVC$8%LKzpD)c<vr3C8;hyy!!8O zf}YDCF*((rzX!L977(K_IrBLS?pKuUbxEe|{5_by=`hXr+5_!@_FzYNAf=?HvW>>N zc1|Aaq^I{oX0vzm_W&R@H^`zl!i`(!C@fm0O1b%a0FZq>&>m<Hv<ExF1Emx-6>T&% zq-i<O$@$(>%*^#~?m>Tc3E@NQZii%Yl<E0%4BzNRs(BLeJUqy}SAdE`Wp{FW9+aJa z=7FI-&>m<H{woipRMb`;<xoqSgN-No`qC*Tr!H>n!M(v13{!BhDZcu?FvQ5z0KYvr wOD2=am2o2vW?NGz6xk;U{obfO*x?@h0k&zbN0o$hFaQ7m07*qoM6N<$f?)u99{>OV literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide10.png.mcmeta b/src/assets/warpdrive/textures/blocks/particleBoosterSide10.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/particleBoosterSide10.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide2.png b/src/assets/warpdrive/textures/blocks/particleBoosterSide2.png new file mode 100644 index 0000000000000000000000000000000000000000..e8f2723c3d9b771ceb18324059bbb1adf5e58042 GIT binary patch literal 1413 zcmV;01$z34P)<h;3K|Lk000e1NJLTq000mG007_!1^@s63Ss7W00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2K3MZTGz!?Al1rkX_ zK~!ko?b*w3RYe@Y@$a0+z32A!(iUidzFX)6ZJ;3m5_?NY+`01)aNU)Oy3+)eXkg*G z3!@1OjT<ROq=127BIv@%qZQH+8$#cO-nO?bZO?PY#l5tsvAwM(R5HJ0GC3zFXU_a) z=94)Y(bd(Z78VvrrBZ}p$XXGGA+GB(Ha5oM;v(5>7Rz;Are<cDonOE-3;=xJCkO%z z!vG;L3<KM?F@yjiC@v`_R6sV1W!pA^yNrm%i1IB-DG^G7R0tsuC_*n{etw?i<>i$U zh9Q>k`|PWEn`=LJg8~Ie2}*%d5-BB0DWp^=X;NF&L3904YAavmi=IP>uC6XMI5>#o zI0Qkk(qGdw8Mq%HWkgGpO){CpbzPR0mYAEHBa_MGzQDF^Y^R8sxj8J$1VAap*zgdU zmx_rzpWWFKLIv@796wUTi;5}T0omycmStH4L4fDEc;0HpV~HY4?#!T+VqtqMm$YXh zigFpVJkLW2K|Jo@IB}MimQYGjR#rwTm0BH*e+Ub}ahzOMJr_esgb)}45=9A=asUuQ z5JeHL>*9sc>I;G(K%pQCxb@~j?(UbsJdn)S+n%X`^5J=kQn?Gmwr!#?{L=`m7q07~ zR4ysT)9JfbKmQtrVPKjjQcA2a4Doy)Ddpdvj3S6wEmDAlSS+@h1J`v4!w|!c(eg>e z;^HD<7_z*)jPLvSzQ59<5CYq_Dcw`Cvhb`YPoChpE?#~T#EX(xQG}B$Ch&bs%gU_> zAy!)TJdYp<ax?M4g9psa%oN;zkzbusN({rmN~hDj03N*7`3=3-PBAjxx2^|DC8@1S zbEK_<t3STAwg>kHT!77cFx{F0Ap6+aoCl@1r}G}{&>m<Hv<HQF&{+Epjdf{yubpOi zyl-6(q)Jd%b%@dNbJ_##f%f19^8j^}n%%F^RNujcYo{3+y}hmnN-1n}2rH3DU|PR2 zF@2Ze$!?qkG&dTUrp>(p7t=J>@Br<B_CR~EwLBOdPf)q5mBzX>O${A<cl8uQW48+O zK<^K<2ik)d&jTqVs`ngZUtOB!h7QhO`Iw=x+lB29YODRc2Yrk@>SN?lH>na6F^=9J zXb-dp|4$E4P*rh|#=3Tz8;<eqm5+Eha%&?V1VGM&@yw?PTK=5}k6#{x?b-wFf%f3} zc%Xo)-EB11x6`t>lb%cOGcw-45f1?RnV7yu%id0`${4Ms&gMM0{CPV7hhI-^&V!00 z*}Mmq_CR}}J=lx~QbP5fHkukbXxZDz*^4I_9_!zT2L`4&0CWIQTJ}4YRXaD~!HxHF z9$eBMXb-dp&(8y;pt|A!P4yi#)wgr*@=1nA`!?c%&B7c=8Suj|Z%|d8WM}!djd}3! z#zTJMvfdwP53~o*-2<g0)q4)+{~eCebMZqaCi@Ea;O4e@#0X4Gf5yD~73I5Jk}11z z52kK7O!2+;KzpD)*b*K{DXFP!qp_}?<3~E_>HUD2?480r07%Uau;2}I{pJ~pw=Gen z+`>Ho$i5zE53~o`gDv5KQi__2HkumJwCwBTZ0`xCXZzOopf9_K@S$~wLozwS)Z7_{ zu6HBV9Eo@V9%SAvLdBu7JGnUz%1=J^z|bCO53~pWl?PHPYAX+Ope4=z#^Zc_;RF+t z=hyb&?!YpJDcIi>&z~<0GCbMOZ}(4=$z*cFxRwVqttk|W?Bj$!Z`2-aaS#3g0EtKt T)a;HA00000NkvXXu0mjf1<aC+ literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide2.png.mcmeta b/src/assets/warpdrive/textures/blocks/particleBoosterSide2.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/particleBoosterSide2.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide3.png b/src/assets/warpdrive/textures/blocks/particleBoosterSide3.png new file mode 100644 index 0000000000000000000000000000000000000000..0dd5644c9c272259274cb5876e09e2273bb76c71 GIT binary patch literal 1412 zcmV-~1$+95P)<h;3K|Lk000e1NJLTq000mG007_!1^@s63Ss7W00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2K3p55uu!aBt1rbR^ zK~!ko?b*v~T}2$g@$a0+z31lUHc8vi=KW~%sD?Ha+Jd=h3hvzb2e{5kP<IMdi_$J! zM-YWB1UEJnYtvR*BG~Fe>?5%y6hmp=X>*g@Bu#RjGcInLRK?^b3XNrcFdPmX&Ybzp z%!l7$L}zEGT3A>hl}ZtYA?rmLhPbZF*w`40i;HBlSuEFenVOkpc76fVFaYp<pCAY@ z3<HF~Fbr(l#t;I8ps=WzPyyL2mTlVv?lK}4BU<T6N{LVsq(TURKoNQo^Yim8FE6jQ zFbuJL-)DdI+w}h21qu`(B`5_-Nu-o0rI1pgq)AO>J56=RsHu3BFS`#TIy*bn;NT#R z;}8VF>Ud4lWZ-^)lo8F1HpyfX*L7K1T4HW)j!Y(#`vTjxv7G{D=H{?069A<YW5Yva zUMeK=eD-FG2o=QRar{UTFDRsV7i6b1Se9iG1OcAs;(2Qsk0lByx-)}PiiMrAT+*J2 zD9UBb@;nbA1o60o<HT87T0$vBNl6K*RBCND{vj*?$8mC5^;`@k5kg=HNE9Sc$^k$K zK@>%}u8S8&YcB|b0EL1m;MSW9Yp?zkNCNY~j%Thw>F_)SsoafW+cr@c{%Hm_3fFZ} zDwh=F>GEA~oPQ0&FfdIMDJ51IhIqb@l=AOSMiE4;H7P(sEEZeKf$O@2VTfVJX#ON( zadD9_3|U@Y#`k@E-(T%f2!U<e6ql8+ZanMBlP7qti?^}};sr^pD8fk=68Ju*W##sR z5Uag<o<|S_xs~|f!2@PyX7V1tSlOLYN({rmN~hDj03N*7@eMt_rx_XV+t350lGIeD zIojIJwIAPF--CMtF2L43m~Ke{kbUfI&4c3G(<>hA(jI6Jv<LZk&`|RZ4Yg@{de1OC z-nXF#QYEOZJk03$dF_GrKzs0ld4M`b_1;%#tZV0D?-_<hZ*S;<QVQD~!b&6(nAWdM zOy6aAvI{2xO$`R7X>)JD#Wam|JV1M(J<uL(FAqk?6IASJp`kWSV|_c{T|3Rt*sZ)g z(Di}#Kzs1wc_3v(RoNl-*QRNzZ|B0*j~N=fonL)WQ{}IC(8tK5K1LpOkt#9~<LLT8 zd!Rk|e|ms|%JM@r)V9%7f1Gcxe#FC(TbuD90CFabXFfyF{O>$?{PGy=)E;OLv<J_} z0|iv>ZKa{EjpltFbYFg-k@5b`cmUAP#PmIy_jO=Z#AqpYw&uZ=FWLY&@_K4(9+V%= zu6ST+53~o`gROWVB~+EQ(pcY4^S%zwT{_9|SpQ}`Ffh#lpdEnXlHaMQ+`R=4ZoHTC z;Ij5Wd!RjdejX?VRpke1tZS#Su8s3oPBA>%w;2y?7Un?8fFFK&gUYHTyGwU$&Vz?H z9`X}cbbX*b&>lQ@50sKrl^t67cQ{V>r4N~y?91PSn>*$aBQP=jIrHvUl<sj!rtJJZ zn7ZLG#rN6+?Sb}STX-O)q`IP&hT1kx9POaH=L2T4ck=fDAT>L{f;Y_dn`bH9u|%bE z^Y;KC`+A@~&>m<HwuJ{uDXPm`X{=AvyuX8UJtvu-?c3OczU(5xhn8Iq$>a!Ab7vX4 z-i1_iB;t8^ka@QN6^Dwh<kmbWJ@wQBLwle-&>s9(9!ROEsW`&H<}?QyPVn``lT1ur zSl@%Y1Irku;6P)1<$Pg~;mLk}yMKmECX<`S^*oqqNuf|=A1CyAqxN8%d+-OJlR6M) SJ|-*x0000<MNUMnLSTaQjf@Ha literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide3.png.mcmeta b/src/assets/warpdrive/textures/blocks/particleBoosterSide3.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/particleBoosterSide3.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide4.png b/src/assets/warpdrive/textures/blocks/particleBoosterSide4.png new file mode 100644 index 0000000000000000000000000000000000000000..df51cce777ded8af9213f5bb9e50070c0e9c53c4 GIT binary patch literal 1411 zcmV-}1$_F6P)<h;3K|Lk000e1NJLTq000mG007_!1^@s63Ss7W00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2K3@Wn*8zKMz1rSL@ zK~!ko?b*w3R8<_n@$b2hnLC{hZFvOfyM?xcHqej&iJejsckcKDTz6%n?leIq8d$jQ z!f3)m<3_-UybPo!f-a0ara~GbA@p5fTBa@S+~+wirnI23omLYnIltuO<|a4y-19r< zeDb?FqNk@v&Cbq}N~H+HkmVu_LtNKobaa%txjFLrJeKRaJeqpU<C$4Z!vMhdeS#ps zFbog^!!WRI8$$>Xg7S(=LIvdWShj5wxCKNkMzqkAloFvNNQDprfg<!GW@ct66bg$i z3_~p6_t{zh4t>A$f&v9d2}*%d5-BB0DWp^=Y0^;JMO)JW8fsqW%Ts$1Jv}|@?%lgM zjzbUxi{mv-lYu({Qbwd(ZIa0(uIn;CKhN~^G`U=^_yx9YV>@L`O;2N4CICt)Mu!H; zy;4r(`E1Kq5Gshr<M@#xURF-!Cdg0buq?|W2m(CM#q*Xj9!r!_adQf#6tf#+#iTtG zQB=&B<#`@L2;y-E$B8pPKaWz1s;VkdsnpVJ{6km(j^h-w>bV$7B80#YkSI%_lmmbe zf+&h`T^BEmmR=A90SX0C!1cFgpMU*VzzneAnJchmXoj*>@y4)in<xyQn}L<WbzPJy zCdGKVe3u*NU&AmAOw&Y4i4}$+p6?^2{QHwp1QAP33Xl+s#g=m5x-MZDV%Ra#pGM5h z%@Kwng+c+}_wjvyu}2{Uwrx|ny?SxuSx=rk!E;@_g+&lAOJYS4PO_Z9_c1N2xF3XA z?A7x;f*>fa#C!MdF*P++^7zHV?vzqu7zS1*li?-s;EnEYIoEfL;j!$B9w?Qhp*F+* zjxH|$^!D-|+#YZN*6zV%dkTR3LuYLsRNk0e@L-enKzpD)D8+-8hIeUc%y6#nI74IE z6+MtDL1XP+M#fHS53~o`gO|($)B)<Zy+&(O7ias9GdOZ%MGurx*ybQsB9Xwfeq(&{ z7DE%gI0<NLF)&S=+XF79X)NOb+5_!@_F#Q^Ffx{)W@|ewjTu^-yZHX{F$PDkm*j!2 z53~o`gO|?(DI@B(?_p<ShPLJ|&RqJ0!O<I~)dvlA{(=Wth96`Ze$Y#*!bFUr>jUk9 z_Tc~N0SaoX_t4VVNn7(lzPt1>_lK{q#)AMTnlP683_<$edGPSnQP`+G&>m<HUW^9{ zsNL2<OH(K59o?L|@BzbP{j2c+pr7%{+oX4NW7WiHuXNVt!No5+0oZpqwKfl`_vaTp zu(Su-1MR_DJdhIVws+9l+(mjvHz&^@VQ92}H69q4<^a$IKxNe*)YNWXg9lgNFM4o6 zd!Rkg9=tdYl!ChI-Ly7!(c09>>5E4h8p*E41Dn}tkTT%MU*Dv*F3ILC8&>DR{j2x+ znTxtU&>m<HUbqKJN$R%mS@?H2$f@%mF+Pzk-GgfzW)Q<LKKVH_?$>PD>XJ;^rF-z` zs>36G&>m<Hv<K_L11Tl-H664xc5-NcH>b{h$W;Dj=^g;29uF|<4RPh#3CcIjQ>)z4 zJpjlb4zvf_1MR`O@IWa=eRT(|%^A`=yE%F82$PSqD|?X5&mnwh-{g=?4)bXG1cO(4 zk!qSmyaW$&@0FqAP}7@Sn+IEtKJ~!R9%v7=2mh4^QYsp1_OUyiVOPr`zBzk@@rg6b zdvI%@fME)DwZ<3D7w$4N(a-O9j+4vfiqp892UG1S6pH-Agg$T79;|Z@{sbA=IyxZp R*{A>j002ovPDHLkV1m(zkPH9- literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide4.png.mcmeta b/src/assets/warpdrive/textures/blocks/particleBoosterSide4.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/particleBoosterSide4.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide5.png b/src/assets/warpdrive/textures/blocks/particleBoosterSide5.png new file mode 100644 index 0000000000000000000000000000000000000000..19b11ea88cdf5e10b564cef4357657634e680669 GIT binary patch literal 1410 zcmV-|1%3L7P)<h;3K|Lk000e1NJLTq000mG007_!1^@s63Ss7W00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2K4KvPmf};Qc1rJF? zK~!ko?b*v~RYx4a@$a0+z31lUnnVqn_e1lr4H^U$nj0f@*IoaBuCpq%-L+s_Y0*X3 zDU=pm6uPOg)Ec!Y7OL%{)JIY!NQ0PnG&jjjVv_Tm>Ed3KK9ifYpq2T-a5!){bLKZQ zAAW}s-QC@4adDAUDn%HEtQTPz;<_&5<KrwXEs@P;v0T?>dUlSvg+)xm0KoTsf*`;! z3=jgtFtBYKLkJLp;*wHA1!S{Wwrvx*D~MQ(DBqKm5}_nWg%ARPBJ?5_78Y1pSy^pi z7-IRp&)(WMx%y)dC{TcupcE)2ky4_RLP~{_CUw=Fv@{%{uIgnz?>&g<?(SAYLqj-@ zLl6Y3<26l_!FvHxMzl8DB$G*8*JXKmnfdv7GMP;73vAoQc8ZvtpU1LH0F+XUj|`J} zp_s_?*_|yRR1lBH@gqgNsF>0nke$h3S(Zf*1bCi{=dEQtmMEg+_AE*%7PrT8N&8(y zQ7&Va=XnSrh{qiqC(iQnGD<1R%F0NkQfssE4`Bf~j+4u(=VB;{5CTI$q9}n<4gf+3 zqA0?3UA!<_dqEHcC=^5iH(y`;YZo5_+kl1q6(}EBpeU8QF>Ko=3d29lz((P^E=uK+ zVmw*C>y7izVHgIcX(FY>3d0c3_mNWm{nJqd5xFJ>NQlK^YdLUTmoN-5>=>;dMJz2X z5r!cvD=YZEkMH}dJqjVPZJW}H%GHf$J%0Qc&vo(giy&T<#EK%EWHEv7V_H^jKM1kf ztLJ$HL6BRC_wV0lc6PSl@r(TKlu}|C239(q<~i`-m9DSoyLyt*iT({eP%24Xb(+KN zom~0;jrBdaJLm#z-GiC76ad*r&el9Ay)~2fV2AcVd!Rii#Dk`~w`i(Q(|7e0BNP1_ zdLUJT`s#y>O`O#pXb-dp&zT3PBh>DGiROk*&R;#n@Yt;lJy1$vo5NU%L;}<LnaP<u zj7;_5B%r0qz%*^{4!W48v5p6553~o`gJ;Wwv55p#yV_`~Pt)Ak$v0O{GCY2>AP;nX zpgqtYJbxZY8BtSlfW7r;S{ge!clkqx$8Qx@AJo<Oc@O#-eb~?F!yZy4CSn3zA7~G> z2menGP*7cYfTsEmS{je?_2mzEFnV({9t1$ngo(^22wMN02ajGHhwa(}?Sb~->3E=k z>fP-$HFVIrr;FZ;?=m_uuo({k2AG_=OY5F4tg0AorOwtoxb#^E0Eb>pZOwzq!`ZwC zmi9n<pgq`%2U0>!MLW%nowV-h;>?BPjEoO##sdS>90WQ6C@uSys_LCv@ZkD8IS(#s z53~o`gQw?#QczR5pXP>6nj1Ped+7utWBr@)z-DnCqzw4(r`M>iNwTwi+vYrYaQy*4 za7ot(+5_#uQ};kANlnFp{J+CddM~`s<Wzs*9^BZrfEb0znNL}8zo2}VOEP5_?!okR zhiSgm9%v7=2hW5DQc7y8+G(oq;Mn0Vdi&mEHha5p4**hggDiR@T)T0a;%&=RE4OeD z0J5(J+5_!@_TZWDKq*CSWjoD{X<GMoai;G$GjshLd(fX<Lio_O!y%a*WqSTJ!`FI{ zYMw;A01q;67op-%)sx(s2jwT8cwlG`v<KRQ|H=a?6?IjI*x#CFU(+$ZJb#?YsdMXl zaA$A@!xZdmj_1!8h8UR|;Fo)+$Ye6PX<W~P*|ro4MfOobpEqg`o^cO;0}?+TWCg35 Q`Tzg`07*qoM6N<$g0I_+#sB~S literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide5.png.mcmeta b/src/assets/warpdrive/textures/blocks/particleBoosterSide5.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/particleBoosterSide5.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide6.png b/src/assets/warpdrive/textures/blocks/particleBoosterSide6.png new file mode 100644 index 0000000000000000000000000000000000000000..0d26d8aea2c8452e060440f809d1f8f79dae8090 GIT binary patch literal 1408 zcmV-`1%LX9P)<h;3K|Lk000e1NJLTq000mG007_!1^@s63Ss7W00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2K4*@inv7rC}1r13= zK~!ko?b*w3R8<_n@$b2hnLC{hZGi^*en1~+0}Tm~*eNA(=gvRCbyp_pP7_q3fraZX zj3z8JZloBI0tQkOK^I0It&oP;5c)23+D=>A-sd?krnG9LomLYnIltsC?&99xJ->6# zC%>B`Iy*bn!omWnREjVRSuesc#C2W9#>QA&TqK*#V!5u%)XXfi^9z`U0f6uO1VMmd z7$5|OVPM-fh7ceGg+;}L3dm-$Y}+Pqml3fT(Ml#MB|=G%3LyjnMd(G$&(E{Gyu5ma zVTk4XKKrZRruXMAP@n)QK`Bs5BBewrg_H^<O=>FJX{tL$O~tEx(R~=v+1aTE2M2K+ zhad=6$7`A<1NQ@@jA(AONhXuHuFKNW5_5BNWHOoD7udFq?G!LGH-}}J04Svx8y+I_ zQX!G&vo~8rs30DX<41~kK_SJvAUmDGvMh@r2=F`?&s(c_EKxwwof(u;EbNTsiuR|7 zqFlu+&+`yM5RW@JPMoEsC6rQ>l$4N4rPgNS8DRl9j+3jZ=VB;{5CTI$q9B1%4gf+3 zqA0?3UA!<_dqEHcC=^5ix87X%=QLje^T3YWZRzkl1*zPPVcRxQ82)7jHVW5uQ7Tsy z<LUBUZ=8P*!!R&S6DcKD7>0PhkCgJ+Pec(!fD|Ah7K^Rbz;#{1FvPH9G=CDYxVT6d zhAb~H<NH3o@2_SQLSWlA#bxEI8_#<3<O!bZ;;k%#ctH{?ig1#J1ip`HS-Jfn#A;U0 z^9X_<w-O&bc)-leOy1)cE4x!liD4L6>2#VGz=PL1zM-f0G$Z4E8+xErlA6jiM_b#u z_TyXYdvI^S1=zX=(=90gvX7muc~E?Ndc}iX+5_!@_8=b*8fxC5p*BrV?-_>2`!@7I zssy!_hZ!9|uRYKnXb)a64^YRb-unuTb?sd2J;TuG?F~IpN@1HrScyae)B2T(>AMV1 zcHtzTslmWBZSD=Yn5MCg2WStp2ik+}<-zE9f{HyYG}NYPtZ(PLYo{3+yOoy*x<Ak! zXb)aI52TE!Dm%pf+B8k|?OeF}F+*dw^Xm_4s{9oX`WSiC$H=2DQbi_W9Niyi53~pW zPY+N~S$>Fy+BTZ%kMr%-k9at8Ycn1MK+c5m%%=#N|D6YqUmk;<+5_!@_Tc$=pn%G~ ztu)lN(Y&vN?#u5pGTy%#4*>d^n7&8zz7DL47%j!l);zfKc^d#nUQcb!gYu)<6%Q=! zf%ZUquoVxagsQSu8tdC>-q*poOD7o~>)(tA2BtXxv;$CF@;eokySL!MjrVdMT-F|F z53~o*&jY2Ps{A00b?r3PwQ>H+DTYV;HsgWK!W>8$@WU@}P+65^cj=DJdGPSYLw@3l z?hmvF+Joorfl`vHvO_EX4#(-f^dS?IeffKEbH_Yl1SY0GW8VFW(mgK8l%2l^Q#Tx@ z_+ERUJ<uL(3lF4}R9CdpP}|0dqaAeje85chPW~PMq-F<L@P@g5^DKosmZ(&2{vH5i zUk|hg+5_#uw(vkHMRj>AjrD1o_jhov=Ooj!eH(kwmt92o(6Y-RnH*ti?kq#syO3&* zL_7}<GVd0k;!x3*+?ofar=EIXXb-dp+Jpbf11S|X6-PMOoaR8o3BJB~l8MO+>w9o_ zU>U;{9B7QMoG%PAJlW50_s@{YWOCEEo(D56DHMwA<AgqM)E;be5B>lW6%dZSoY=kq O0000<MNUMnLSTZz8HQm1 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide6.png.mcmeta b/src/assets/warpdrive/textures/blocks/particleBoosterSide6.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/particleBoosterSide6.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide7.png b/src/assets/warpdrive/textures/blocks/particleBoosterSide7.png new file mode 100644 index 0000000000000000000000000000000000000000..9d81804c2195ecb0d0d608907ac271c20449d8f6 GIT binary patch literal 1405 zcmV-@1%mpCP)<h;3K|Lk000e1NJLTq000mG007_!1^@s63Ss7W00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2K5D0(~2b%x@1qw+- zK~!ko?b*w36;&L-@$Z?(y>okeX$v&a_XGMs8)!&?#NJX8ckcKDTz6%n?leIq8d$il ziP40Gi5n?Kq=13cM9_tiM=PWuHiW(ly=`w>+RpPF7q_%(LVH_HsO0>TNoE!^XU^~Z z&L_Xgh|bPVwXm>2DwQG(L)MEh3~^nTv9U207Z=H9vskX{GBq>H?EC_zVF2L!K0y#* z7zPM|VHnu9jUfaGL19rbp#rj5EZepT++{>8Mzk`LloFvNNQDprfg<!G=I7^GUS3{3 z!Z5`0eV_f+@6h{87bsAGl%NzSC6Q91ltM~{k|s5k?KIULqo(3@zUn@V=<MuNgM))O zjzbUxtMfHYlYs{TQbsg4+9Z=nT-Rl3X^FYHIWn0{?hS0)#&!yrnVZA1OaPQpj13Qw zd8LrZ^Vyp%B2*BM$MGXYyr7WcU67s5U|E($5CnLhi|4InJeDY+=<W<kDHe9da!LD3 zL{Tndmgjj0A&AEv94F4w(h^E3N=iydrBZ9F@tm*#9LLFJ)pIeFL<oT)AW@J&DF*-{ z1W^>>x-MQAtvw(J0u&0OfZJ~^Jim%Q19s$2ONZwvNaZdJ+qQ|q@NX-yQMj&)Qn{oU z&&qebdHypD!@x96q?A};7~=UpQp)x3iXxB#B*bE|wH&yvOBjY2c8umvBNi7I3B!=( z<z;-|$M^l!5rq)gwoP$a`Rc~Ao<4nw=el?+MG!AYVnq>7vXH>{F)b^%AB0#P)$=@p zAjnnX!-o%<nVHFZ{$gc!N+~f611p_Q^AdRQM#s1G^qyg4yl+DfluA-lndWF~JJ)}D zdwmb?54ZqZ_h7mu1wi(Rvo#Nj?@X_FuuFTOJ<uNH<3U5syEN3M>FGVo@Oa;b9!Qm- zw(>Be;}^6C+5_#uOXdOU7}a}Uqp_}?OTA|q8ojfj2TCbya|kPuNMKsOF)@9Q;mIzX z1T-}mn5NDB0T<IW*6{%Cf%ZUqu)RDO9ZyiPr-g>vG>!G`e1H86Lu0q|@<8_o+5_#u z%jbcV5mjY}*k7BbslJ_y*FIrr>`s3DK~0sv;z1uHkNX&T+(oL$M2w^R1MPwK;Q#3X z3M$JF(NNn)Q~hziyY?}UMs9D$g8;~xFrN7wLG!=!;K{3Fuv2@WJ<uM!7!MRsxwn;u zx;C2kb<lm~14hRCH{$_7KNHjUY2Md?RS~15*x8x~SHEln;K<3;);uUbnqBe0(jI6J zv<F-9KuV}8Yo)Qio#uTVoWFdE;j#YBcwk_f13)_f#U+1GQMr2y9^8CC=fM^2f%ZUq z@ZvmB3aZKv(pc9{V_h2;uAXLiv~M#W*euL}lmS2f`X-fCNp_d+*qjHCZa(5?uIm0k zd!Rjd;T|X@sVY0P^6hY(?#mxBG1-^D2e)?2BSv6i`U~dWuPNQ*l1$n8doXp=VTvEL z2igPe!M5-~N=bD^D-E@6oH*J+ch85+Wbfwh0YGYYfCX=u8@J9;xMPV*<>v1JK=x#y zJ<uL#54ME|N-3(#TWPFM)4acf^F61Sp6%P%gTCw{!iSb!4$0&QQ*-ASy3vJHb0p$< zc#wIo02POduH@D{C_Vkm14DbDJ<uNfR~|^IsHr%@!R9mv8cy)drBh5yUR>XUdjrcD zrr<zheC7YbAj6aW{Qlr9nM@|PjO%$Y(~?4=$UaHv|Bc#%ZSKLJ=`8fAGT3y+00000 LNkvXXu0mjf`0JHY literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide7.png.mcmeta b/src/assets/warpdrive/textures/blocks/particleBoosterSide7.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/particleBoosterSide7.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide8.png b/src/assets/warpdrive/textures/blocks/particleBoosterSide8.png new file mode 100644 index 0000000000000000000000000000000000000000..d20d38340c0e5b1282f79471d336c81d05162708 GIT binary patch literal 1400 zcmV-;1&8{HP)<h;3K|Lk000e1NJLTq000mG007_!1^@s63Ss7W00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2K5eonVXJ7yT1qDe& zK~!ko?b*w3R8<_n@$b2hnLC|MA3y_rKcEk^frbP~?39wYbLSu6x+@cPrwJ<2z`}JG zMiUkqH&Tp90RyRtpbI09R!Bo^2z?hiZKo}5@ADiNQ(85#omLYnIltuQuI@ee{Lb%u z^1C^rtE)>bE-sQvr3k~2jUo&~T-RlMe4M4FC9>Hpmg~Aq&(1Nou!w0G0QkO75Cj;8 z0YYFH2DWWu2mwM+SX@G=fNU1awrv7;1rdu8t&Sw6L?{VTA%sAn2)&4fg#}htR@SaC z46%IQ=RnQd^!?lo3KSqEC<RJMq?9P7kW!(fNo`dJ&GpBrt$dX)dX6Bvy1LZR&=8K} z5Cp;6d`;72@Iio-5iLzN$z&4Oby;3sW`2I2OeT~20^7E+odRa(=dmmk0HqY;Bg14~ zDkSoJ_GOC+6~yCl{74ZmD5PXJWM?v1mSqtH0iNgLdFvUEB?>6MJBw0^#a*#n(*6`t zl*^dqc^*Ot;&BJZiL<=Cj8cly(o#~X)cR`tLs$Tg<K(jHxfn_!guoDxC`h1`1Aq{M zD2i}h7cY#~Ul0TV3I$QX?Kc-UEF`|n-O5H5C`c6nVA!@z6o!9Ufz85oU6jft#dub} z8_o0YVHgIcX(FY>3d0c3_mNU={-l&3Ar_0R=fHJc!Z5_JW3+q{v9z>A7>2B@tl;}T zzVEM%D1^YaZA!{3);6B?^yyPP*Tq{cf_Om^D~fQEg#^BjX<51bAjI0Jp63w+L9P-X zK77dR>}=li7puEdN{L|@Sm|_{7r=wpI=`W}?+l|8{hNBARFc}NG{@RHxc=i?8+&kn z&;{7O2Q#fH0J2Y<?RijgXJ*xd-P!}~f%YID4;pLVp|LJaZ{Jx)Ci*w^K&k|FRYw?` zxS&1I9%v6<Fb`12soD1mP4yjI>O0Hu*qu#1P)cE&!&r$#0@M1H$(ehMOm*WVpt;e& zG;Qt=x|pW1fd^<0v<KRQo#nyUM1sn_tu)r9X=>=;yX$8d9>1NJ2f9Dd9%v6<JP)Ld zs4hRufx0x!4INy(_A$fbck=5GYODQK5BeE>+|TIaZc@c2VglVCXb-dp|4$E4P*ri5 z#=3Tz8&2@;wU2l-dV4D#1VGM&iOi=6TK=5}PhK8}UD^Zff%f3}c%Xo)eQh+>x6`t} zlb$Q@GdeM_6%POgn4Gy!%l=NR${4LB&h|XG`guD5M_*5E&x49%*;NlL?Sb|{d$1i3 zq=f47HkukbXxZP%`OBvm86Vh+2L`4&2y_5YQu;fUReQGK!Oiz_9$e8LXb-dp&(8y; zpt|A^P4yi#)wgru>S;#C`nTeN&Eh;r8Suj|Z%|d8WKUVq);xH0^ASIBRrd$l1MR_c z_dqF0b@}1de}@zFT>g;Bss8*uxK*@(7=_81&scE3qHM2AGG*uQ!SqdsX};GUXb-dp zJHi7gB{h|8G}g6q@>nN5y&o`}y_>%W0I9h_7QGQ}+&V{L(K1!a&EErn?CXK{KzpD) z*byEmrKqWBqp2ZH%YjbL_nu;Au77h6`m;+2A6j=iB$J~|&!1!XMmJK;lZfZxLFU~8 zR2(Y1liTy4?DR7a4DEsTKzs0Cc_5{tw(=;4TGAYBJjvIWPBA%kabpke4X$9Af`d)* z)$@fRMy3Y%?ZH_xnM`gOH}YV%HHAWveUi}UjoO19?!g~d!RFJCwNHcq0000<MNUMn GLSTZKsEFPG literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide8.png.mcmeta b/src/assets/warpdrive/textures/blocks/particleBoosterSide8.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/particleBoosterSide8.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide9.png b/src/assets/warpdrive/textures/blocks/particleBoosterSide9.png new file mode 100644 index 0000000000000000000000000000000000000000..99eb37ecbc05616299069ebcf9aa2e15c1cec9af GIT binary patch literal 1395 zcmV-(1&sQMP)<h;3K|Lk000e1NJLTq000mG007_!1^@s63Ss7W00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3K2K5(u&<Wf=ef1prAz zK~!ko?b*w3RYe@Y@$a0+z32A!_5n1|_XGMs8)!&?#NJX8ckcWHTz6%n?leIq8d$il ziP40Gi5n?Kq=13cM9_tiM=PWuHiW(ly=`w>+Mef(i(6VXvAwM(R5HKhEYHlD-*4uV z-^qxst}eB>xJW9MA`C+|iZBduU6=9kah8^r$Y!%xuIn;AJICC@BBo&g;QKy75MUSv z2!UZ3*tU%!1PDQ4aS5RUvRN$Kwh7!7L@Y+MI+K(Vp(IF!5CVZB^dc4(7FbzXS$o1T z#PWTg12u2c_j5NWP=J)66euN;QlgYXN`;apwN)K7*B__0@>Ra<IfCfw>QX~PLpY8@ z5Cm)MHBFPj2LVz>v^3cylSy3HWqEm-`T2P=nN02rY}>|m3YeXr$FfWSlv0e343l}O zkjV4dmn|k#5Rb?4BSpNRkdobyoylNXmPHT*c%F;rt!F%zD4_W6EJ`UBcg1o^`%^?w zE@PJGc?cnh#~mCe&hqjyN-0W9OG%|t>(%&&umBv#$z|1ZF_c6IfgvDKkU%L103ifX z6ydrqUKp(p5Cj1V1yR85Hy7D7K83Q81qxC{02sDy6NTYlDzI6&u8UH+q!`b(??&tV zdl-g+X_`nWa|3w3kCZaMx1}T&i>>FtbzQ<R#IR$ud=jy=v_u$&tgNiy`#!$!ugxfg zz_x8l$}83mp7r$UQ#{wjTipclf+SWH;Uo(Qd>_-Ya_2#awOKvSBM5@rPJH<AA+xiy zd9Poro=zzxhGAf((`jA+4_@p1hTgt2j861#>VZ;8YOB&5YwO_pk8f@4!TmuOVEZ1- zw59;aK5@3^LCKw&RS$M+53~o`gM2(_tbK>Zx-`9gXBnC3-_!%C64X^4VQk`p_CR}} zJ$S)9Kpm%M-zzlLcW|liEW=}WHuXR$g>4RFB@zit>sKac?lCgejgx@pMg!Bdxj*P) zn#KkmpgqtYXb*Ol2V)ZnD)+Y1SeK@$p@Z+PpJ90Xc3vLn{y=-6J$UgvkTRmW{4fXV z(lj@8aPiv543FQ*uRo}*_E$aVXY_GDqmR2u6`P0&bbp{d&>s9hJwQQK#bFxj+G%b$ z!ME2w;?d~st#}XsITI!_pCM@ZcOE=>c^r0W53~o`gXiOc0;=}4(OBP3%l=M!uDs9a z#K2ZO02p9$<~}X^JFzNbw3ayA^Wf?i?EoBoJ+(a#Dvo7WJ+QO~+5_#uc07<0s>|DG zYUrS4e<$ZJpJHTuU@IONnC2kR0YFLV?^IUp*@g!<-^+P$MSGw<&>lQL50rxHibFKj zchFSd&V{R|85!%}iU&4}^B`rw55K%YRdtd*Wkp-_;L*)T{KQq=A7~G>2hZIDr6kqm zhgbg{PSA7tLnf#C^Y`FZ(E?%=CTBip!TpM|y)Ma=oxcauHyx(=UVETD&>rjv52TdT zRJPGr*Urgfo%Hm6z-;zz{vH6N<_1~xM!0e79EC;8R4F%q4*;^S2igPef%afWc%YP` zrlO6ehBPe)Iyv8aikZ3o%{}PPE+Kqq-R+P}jxs%ej^P{KNHtF)o`(mScMDK)sO(N| z&x5kl&pa@+2igPe!GGm}l#1HQqa12UbFlFwUtc=K<kZEDJ-9cxf?)~{HpN%(7ls&_ z8sN7FXUSwTxiW6#!E9>^g(CYTq3;{D2Rqz@KL8E**bf9_e3k$J002ovPDHLkV1mTu Bh1&oC literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterSide9.png.mcmeta b/src/assets/warpdrive/textures/blocks/particleBoosterSide9.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/particleBoosterSide9.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/particleBoosterTopBottom.png b/src/assets/warpdrive/textures/blocks/particleBoosterTopBottom.png new file mode 100644 index 0000000000000000000000000000000000000000..12045750746606bf8d55c7c43d13bec3c819aad8 GIT binary patch literal 603 zcmV-h0;K(kP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv05SkI z05;FK;(Gu9010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3J{LDk9cQX666@02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00F~EL_t(I%YBp0P8=~1gunK9 zW-si4C@4Hfq`X|D<OPv<h7AGbhX7((p`G!#DhJPoMM~nsc-pP5uCB7<<EPL5d3(z^ zPRJF_BIgbW<~l<_IEV<q*v3F96QvZ=&A0EIoxP>+J8Cu6qLe}@BUP0;S7z1rua>K| zvU}Pwj)h#Ni7!`IoWDC~9Dne<duA90szd;^#zX|NNhx@|yQj{g>wB^>`~9BHX2a>5 zQ*N%WAre^7YKb-nmXU;N1D7hf>pE8bKq-Z*%~!VDE&p5nFf4@`E66D&B6Xxx>4prz z?rGs3ZWL(o$-0dYbPxeRu2pma>e8Zqt68u8s`GBQ#6EzxFhvTYOU)|1rh9oYa(OWx z6@nxF=n_D(j1968TFAy<reDq^0)rc3wwJ&{KG1Ia`wy!l059KowdX+S0C+TZ6Y^g? zOoSnV+z1$3?8iL-C+mOPXbT7|P?#)?Wae6#OJP{8z~J!W;-bi6snn<%ffHGCrObtg zhX-71vo|0}NB7XYBq~T)EuY6};{Mki(u@ft6VWt@Fy_dAHx|aNnN5D&Ziz0DQ_ox` pA|O&C5iBnlAMTAIl2Cnd^*2!KFNXk6w9Nnj002ovPDHLkV1mk({VV_g literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/radarSideActive.png b/src/assets/warpdrive/textures/blocks/radarSideActive.png new file mode 100644 index 0000000000000000000000000000000000000000..0c063dbf2a3ca6b0f7d28b93c1e5d4f5673230ad GIT binary patch literal 3007 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 B!C?RZ literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/radarSideActive.png.mcmeta b/src/assets/warpdrive/textures/blocks/radarSideActive.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/radarSideActive.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/radarSideActiveScan.png b/src/assets/warpdrive/textures/blocks/radarSideActiveScan.png new file mode 100644 index 0000000000000000000000000000000000000000..7a59b3bd1080ad98148a3faa2a3f56f17f3451cf GIT binary patch literal 4612 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 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/radarSideActiveScan.png.mcmeta b/src/assets/warpdrive/textures/blocks/radarSideActiveScan.png.mcmeta new file mode 100644 index 00000000..37d84f6a --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/radarSideActiveScan.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/assets/warpdrive/textures/blocks/radarSideInactive.png b/src/assets/warpdrive/textures/blocks/radarSideInactive.png new file mode 100644 index 0000000000000000000000000000000000000000..73795af10d4ed058492b0b1a05662fc1ea01a5d6 GIT binary patch literal 588 zcmV-S0<-;zP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv0RI60 z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3AW;1T^rEaTWjo02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00Fc~L_t(I%cYY`Z`wc<g+F^t zJjO2|3z|j*DV0!Lr78ur|6i=qU9)JrNJ_(|<e|7Y;0M@KchMSf5UZTkXmsc3n|ton z1|L5aJVVCQi!@CcUtMCFlDBVOqw6|fzkNqH1V=B9Fs0mYa6SIPV;CaqHiHj+rqd|^ z4c{Y9mjppTtJSKQ=;dL2b;)8r$MJkz*QHjg0icv3%Q9@+M$<GFiv^zRRteH1AzDN@ zo`>T&7{&%n2!Rj+0Mj%9kW#YBGSW2tM=-hmiR*jVw!MC=lmZ~n^PR?JS;pz<tIZcQ zO~>~eYwT@lnznN{o6Ru)*XjW3kJ=kkQ50*MQb7<9&L67;Po?YnUIGBywzmw5-C2s` zcrTTdl6Plk8w2CufG`XzMP)zA1h&=bbhx>@+r)T${E|3MST2_shJg^G5@jjNvN-8> z>GgViK0n_WNUKhsD})dfMM0kD>mHO8?RFbeO5XST+~3|3MNxH>9oOae!vjXGhT}M7 zSq8vrwL&Sya5&_o+hsHwtw(%k7n+BM)GZ6Y(V*3AGMP*O=nsbcn%?l`;({bes&n$( ab^Z&8qL&<=joI)30000<MNUMnLSTYw-TA`+ literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/warpIsolation.png b/src/assets/warpdrive/textures/blocks/warpIsolation.png new file mode 100644 index 0000000000000000000000000000000000000000..b4d7583e5024ace21d07ae08911778b14de949e1 GIT binary patch literal 1020 zcmV<Y0|WetP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv00000 z008+zyMF)x010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3Aa1785PgU^D;#02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00U%6L_t(I%RSIdOB)FQfZ=yC zlaQHAVxtWjL)7@$YN-~iYly2NqJq#p^(OS<&9Z;MOV9p<VvnVVH7#3Eu$E#;t5OWD z8bl)zV+?+UPLcsLCT3=D`}~AQI6OSGG)-e?XNOX$L@*fSG?n7){G8^dCjJbEQDm8a zS5}ysn4qJ(8%@(#SXdyR&m+3s?pKvc1=BR?>gvL>EF7}T@87?1sVWDDhpd17N=r)% z-H#u$yu8f&_wP|vmAbk*q`tmBlF1~6LV@%1bDT~mKA(?!9uKv(wS4*Yi$Ea2+LtfH zHaD4>nIVx#Ac`WzVi6%8k6W6iQ7V<Vxw*kKO;%P`2!%rEx=y81p;RhSUtdpMT^$=6 z8#FdHq9_Uz6B9_5Wg!Rx>2#WEwMw~M#^>{~x3`C?s?5#JVHgIVKYu2Z$q){QvD@vm zwY3op29eU~G`g-M%QCyWyZC%Q>~=eMcXvE^@PM<kGjv@il}gdn)I@J@FU`%(*lafJ zc00EH{e6y)k1-5`+1XiKE*B3UK4fTUh>?*I+S=NP#bOi+1wx?^4u^wsxr`)9eE9GI z;qvm*0$5*P$1n{1em{aBaCLP>Boe{paxp(YkKga7v9S?Jl5jem6bc0z8XAz6KYrxq z_LjlHL88$p9UUF0s>;^Z7EY%Vo6SZlmBQokFg-nu!{OlK;(}x{$<fgf;_QnTuT)uP z@y#17Ae+r12m-pUQ!Ezg?CiueP26rb;c%FIK2Ii-;o#ta)zwvO9qsLC`8+O{i%2Ab zqA28YIi{wjXl-p}ZEcO~>ucO@H`mwK<Z?OU@i=eaz9pN@B5nWt$&YxP!GQrPhQa9Q zC|<9Z#l=OQKYxxWiUfl};_*1CRElrkzOlKvNj{(F(W6I5Keo3Sc={B8rcek`6#4Y& z6aD@DWHK3^Jb8kqX{6I>PESusBodsQobcDPXZ-#0CBi@N-dWXZm8xkHYHw$IdmBYj z7#<$R<M9xUMyaW(VQFdU{|n2q_+wxI(Pl%s=k?<8dWpqi<aM3N$w^dI#j-4}uCBO$ z|30r@zs4{OdU|>Y1OnLYc3MLrZp&qaTrOuVEiEBQ6653J$g+$q%ZQ>#GMVK2_wNXT qK&ezh6h+3y#&9~Fn5K!MDEtR9!hNo*94sRM0000<MNUMnLSTY<snXs6 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/warpcont_side_active_7.png b/src/assets/warpdrive/textures/blocks/warpcont_side_active_7.png new file mode 100644 index 0000000000000000000000000000000000000000..eff142f8620a092e86307cf222d1ff910f83f348 GIT binary patch literal 1113 zcmV-f1g86mP)<h;3K|Lk000e1NJLTq000mG004jp1^@s60+s0^00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-sm3>FO;Zj9yz0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbQ(@8`@RA}Dqm`!ioR1}6E+jl(U`O3^BX%apPK@~!P1d7z6 zF4(a{0?`#~_J|z|#D+~bEcplg1SBMc5J-pxYC?igKvb$)g*K_uOyU`jKjN|Py(~O+ z5)wk3F8K11ERSW+>pAz_`^<Zfv2^*0<`F^w^m;v%QULkcaU3kmLP|+0B{EI(`${Ro zFhnVp35>^MeBVE!?0H`PS+*4NLMBk%s-h!Jnk0xyB@+-r01yTjNTrR|vzUfUuh%3= z*O9X+J0A>4f3}(b9I7{M(lk8~IEWTny^0X8BjtApahoJv2W=oX1u9Zlo(X_HJO&3b zq}Bcgt$qR{pkmjE_Mvi5@YpA90IY$P2~5VyJSwn(yXP_(++yI~$F?^CxO;sEu_M@e ze-9%u`0e8dD4qQVW9jl0-EOz>JdY?0aq9J4uG{V6y6&;kDWwR5fM%<erC^$qytHPw z-##R8@TFI_HW|h-zb-z5X_`nWkB@<27|hLwq<PJ!@_Rv&;6>4qXO9Uqn=Ks2K?s3m zS=4GZhQlEM>rXw+A76G%Kq|>-G&<81Rwq^A$;X#jUA{rDv%>1~4PJacJFl%QGdH`! z+R8H5-dfAYE3ZPQ(_t_e6k0@kySwzJr?V6S-_HfKlrYIp1IFY{7)Ew&7-*%ClN1C% zlBRSzopUW`lShodp9kh)9z;Qa=XtoU%g7s2cbrUM!h`#7hU{OA0rJ^;WFl!G89xEQ zSVFyF6Gl-H9>DaBcj#&cD8vKU?YHyeVVs!<VK7Iv)<Nr848x_}t`Y>RXXgPl@kdv4 zCf1!>#drWiI^AzclZ=U$5HK#lgI3F>-iQ&x&3O=plsqVT@bBZnBAsqGUyX6>0R197 zXyK2p67Ro9;J-$iEEMIz3^k{LR?}bvOifkr{q-U|*udRe05VfCGh>zhpyWZxgVG<A z{-ET+KadCMLdy7sY(~|8tb<Rn{=xXt828-)YFnVIn#Pxng8c(P`zAWpSld?d{z2`B z8nX`sn3~E)rFj3~-ba0^H*L1x8DfTJ$%B#y|63l6FOAt>%Kp|{U$-#&1$hv^6f=5z zgbodKO)>T9)H!&NW{0?2IgJM`8qGT>^%=I&&&yf=s*czcV1WILeHsr&1pXq)_zj}) zS<o4MHb30O`QBmY+6ZfCmHUN~2c<vwD}N9L0g04IDG`>*+}u226rJ54{ONw-?Ec{7 z{XzkMaPoek^arIsD0xu!6VK64d>Oksg;EzWj6Th#CXT;2l?Ucg9-Qn@9`fM1JGXiG fe943V6c2s}5V!$#T8k}Q00000NkvXXu0mjfyqorH literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/warpcont_side_active_unwrapped.png b/src/assets/warpdrive/textures/blocks/warpcont_side_active_unwrapped.png new file mode 100644 index 0000000000000000000000000000000000000000..6895ffc4bf7b0ae85b94a949ed3e1b83ed591532 GIT binary patch literal 981 zcmV;`11kK9P)<h;3K|Lk000e1NJLTq000mG004jp1^@s60+s0^00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-sm3>E}5`jG)T0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbQPf0{URA}Dqm`#owMHq&k>Mk3%e}=ZlW|#yJ83>DnRYW31 z2#EzdBqX>32jBuMSi%k98eAX}Vik`vQj`tSgd~WG74W$I)7>7syQ)~U-HtVr$UQ+K z5mk~^w#xN(*Y{ODdcP9auHP`cK$8HiRtv2)K;C<vhwHj1rAU=RrD;B{wI+^ZwAPux zd_E@(!!_mcczos)bI~M0mP(m`loEhAdV^GzF{Xnf0$Qy)NqP@}qpLMeCL!<rp#VtJ zbS1EA4UGN-DL+T4Uy<_nTwoSOq_Y`N0l+*RgH;>R*t&($cR@sy$`z(3*~s2Q^2q>Z z5i4h1;1R(fU^qNv81yKYj{x{>=j2qcjaj|HGV($Qw%e=VDb)nvqh6V|N_h8Am$9R` z+$$5CWF_D@*^3xsIPP!d0?lkb+e-26-+%EqP5J4<MVv(@PQ^e7!Ooj8X`b`f^Rb>% z%+nNS5k4WrX@PpZf#-QhDREtwN~OYRG@|di{J47o2gAT|pDm!YVltVW+B~7-5IXDe z)@Nnm?TcORbZ^u0_qo%(&4*XA{$Rh$PG_Hk{Vrd9d635oKwP_i!}z|>a5yY<hz7^U zw6?diB}8GE3mBzfu|5Nc#gh;s`z-`UYt&*15+F%aeBVFUadvpY_TTfsd71~)C}KPw z69fU1@rbJD<r9yt*0}$U$+z%wx2|m@10?ge0GKPN*2=`wX%QZ<b{e6bf7_4;aNOU@ zKg+f;4`2_!>0?X>Ap)k;*MR=!Jb*gk<Yvyqs&`n72Qb2K{z95$OmwA$c>x|Y8UfYX z3@L-02XTz$f#t!g$Ae4w&1QZYXEP7z7vVvJaB`E`$u~sdXQat)Q68*26jzpt`Gd@% z>;gdsw6<&gf#reaf%OO0A6OpP`-4~e{=o9U^1$-o<>5htTKxf9|4do*^K=&A!GtKh zL^A(^Y5V~g_ur`(K0T7WpG^7qA@tlix@f(ymn3`_3>aw55A6<);}owKf<^x2dFqA3 zQi<=|9VCVai)9t!!4oNYBBkYltr!0H^+Ew2ob3-b=E3v)!A3lImOrpOuspE$iG}YI z*B#38PtU6toOK?Y?NFBW!q>gWRE;?w4{W{gGV|ac?^@#4McQPL00000NkvXXu0mjf DUEazh literal 0 HcmV?d00001 diff --git a/src/cr0s/WarpDrive/EntityJump.java b/src/cr0s/WarpDrive/EntityJump.java index d41d351d..ea2f322f 100644 --- a/src/cr0s/WarpDrive/EntityJump.java +++ b/src/cr0s/WarpDrive/EntityJump.java @@ -37,1238 +37,1244 @@ import net.minecraftforge.common.ForgeChunkManager.Type; public class EntityJump extends Entity { - // Jump vector - private int moveX; - private int moveY; - private int moveZ; - - public int xCoord; - public int yCoord; - public int zCoord; - public int distance; - public int dir; - public int shipLeft; - public int shipRight; - public int shipFront; - public int shipBack; - public int shipDown; - public int shipUp; - public int shipLength; - public int maxX; - public int maxZ; - public int maxY; - public int minX; - public int minZ; - public int minY; - public int dx; - public int dz; - - public int mode; - - public World targetWorld; - private Ticket sourceWorldTicket; - private Ticket targetWorldTicket; - - // Collision point coordinates - public int blowX, blowY, blowZ; - boolean needToExplode = false; - public boolean on = false; - public boolean bedrockOnShip = false; - public JumpBlock ship[]; - public TileEntityReactor reactor; - - public final static int STATE_IDLE = 0; - public final static int STATE_JUMPING = 1; - public final static int STATE_REMOVING = 2; - int state = STATE_IDLE; - int currentIndexInShip = 0; - - private final int BLOCKS_PER_TICK = 3500; - - private List<MovingEntity> entitiesOnShip; - - AxisAlignedBB axisalignedbb; - - private boolean fromSpace, toSpace, betweenWorlds; - public boolean toHyperSpace, fromHyperSpace; - private boolean isInHyperSpace; - - int destX, destY, destZ; - boolean isCoordJump; - - long msCounter = 0; - - public EntityJump(World world) - { - super(world); - targetWorld = worldObj; - System.out.println("[JE@" + this + "] Entity created (empty)"); - } - - public EntityJump(World world, int x, int y, int z, int _dist, int _direction, int _dx, int _dz, TileEntityReactor parReactor) - { - super(world); - this.xCoord = x; - this.posX = (double) x; - this.yCoord = y; - this.posY = (double) y; - this.zCoord = z; - this.posZ = (double) z; - this.distance = _dist; - this.dir = _direction; - shipLeft = shipRight = shipFront = shipBack = shipDown = shipUp = shipLength = 0; - this.dx = _dx; - this.dz = _dz; - maxX = maxZ = maxY = minX = minZ = minY = 0; - targetWorld = worldObj; - System.out.println("[JE@" + this + "] Entity created"); - this.reactor = parReactor; - } - - public void killEntity(String reason) - { - if (!on) - { - return; - } - - on = false; - System.out.println("[JE@" + this + "] Killing jump entity..."); - - if (!reason.isEmpty()) - { - System.out.println("[JUMP] Killed: " + reason); - } - - unlockWorlds(); - unforceChunks(); - worldObj.removeEntity(this); - } - - @Override - public void onUpdate() - { - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) - { - return; - } - - if (!on) - { - worldObj.removeEntity(this); - return; - } - - if (minY < 0 || maxY > 256) - { - killEntity("Y-coord error!"); - return; - } - - if (state == STATE_IDLE) - { - System.out.println("[JE] Preparing to jump..."); - prepareToJump(); - state = STATE_JUMPING; - } - else if (state == STATE_JUMPING) - { - if (currentIndexInShip >= ship.length - 1) - { - moveEntities(false); - currentIndexInShip = 0; - state = STATE_REMOVING; - } - else - { - //moveEntities(true); - moveShip(); - } - } - else if (state == STATE_REMOVING) - { - removeShip(); - - if (currentIndexInShip >= ship.length - 1) - { - finishJump(); - state = STATE_IDLE; - } - } - } - - private void forceChunks() - { - System.out.println("[JE@" + this + "] Forcing chunks"); - sourceWorldTicket = ForgeChunkManager.requestTicket(WarpDrive.instance, worldObj, Type.ENTITY); - targetWorldTicket = ForgeChunkManager.requestTicket(WarpDrive.instance, targetWorld, Type.NORMAL); - sourceWorldTicket.bindEntity(this); - int x1 = minX >> 4; - int x2 = maxX >> 4; - int z1 = minZ >> 4; - int z2 = maxZ >> 4; - - for (int x = x1; x <= x2; x++) - { - for (int z = z1; z <= z2; z++) - { - ForgeChunkManager.forceChunk(sourceWorldTicket, new ChunkCoordIntPair(x, z)); - } - } - - x1 = (minX + moveX) >> 4; - x2 = (maxX + moveX) >> 4; - z1 = (minZ + moveZ) >> 4; - z2 = (maxZ + moveZ) >> 4; - - for (int x = x1; x <= x2; x++) - { - for (int z = z1; z <= z2; z++) - { - ForgeChunkManager.forceChunk(targetWorldTicket, new ChunkCoordIntPair(x, z)); - } - } - } - - private void unforceChunks() - { - System.out.println("[JE@" + this + "] Unforcing chunks"); - - if (sourceWorldTicket == null || targetWorldTicket == null) - { - return; - } - - int x1 = minX >> 4; - int x2 = maxX >> 4; - int z1 = minZ >> 4; - int z2 = maxZ >> 4; - - for (int x = x1; x <= x2; x++) - { - for (int z = z1; z <= z2; z++) - { - ForgeChunkManager.unforceChunk(sourceWorldTicket, new ChunkCoordIntPair(x, z)); - } - } - - x1 = (minX + moveX) >> 4; - x2 = (maxX + moveX) >> 4; - z1 = (minZ + moveZ) >> 4; - z2 = (maxZ + moveZ) >> 4; - - for (int x = x1; x <= x2; x++) - { - for (int z = z1; z <= z2; z++) - { - ForgeChunkManager.unforceChunk(targetWorldTicket, new ChunkCoordIntPair(x, z)); - } - } - - ForgeChunkManager.releaseTicket(sourceWorldTicket); - ForgeChunkManager.releaseTicket(targetWorldTicket); - sourceWorldTicket = null; - targetWorldTicket = null; - } - - public void lockWorlds() - { - System.out.println("[JE@" + this + "] Locking worlds..."); - targetWorld.isRemote = true; - - // When warping between dimensions is need to lock both worlds - if (targetWorld.provider.dimensionId != worldObj.provider.dimensionId) - { - worldObj.isRemote = true; - } - } - - public void unlockWorlds() - { - System.out.println("[JE@" + this + "] Unlocking worlds.."); - targetWorld.isRemote = false; - - if (targetWorld.provider.dimensionId != worldObj.provider.dimensionId) - { - worldObj.isRemote = false; - } - } - - public void messageToAllPlayersOnShip(String msg) - { - if (entitiesOnShip != null) - { - for (MovingEntity me : entitiesOnShip) - { - Entity entity = me.entity; - - if (entity instanceof EntityPlayer) - { - ((EntityPlayer)entity).addChatMessage("[WarpCore] " + msg); - } - } - } - } - - public void prepareToJump() - { - LocalProfiler.start("EntityJump.prepareToJump"); - isInHyperSpace = (worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID); - toSpace = (dir == -1 && (maxY + distance > 255) && worldObj.provider.dimensionId == 0); - fromSpace = (dir == -2 && (minY - distance < 0) && worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID); - betweenWorlds = fromSpace || toSpace || toHyperSpace || fromHyperSpace; - - if (toSpace || fromHyperSpace) - { - targetWorld = DimensionManager.getWorld(WarpDrive.instance.spaceDimID); - } - else if (fromSpace) - { - targetWorld = DimensionManager.getWorld(0); - } - else if (toHyperSpace) - { - targetWorld = DimensionManager.getWorld(WarpDrive.instance.hyperSpaceDimID); - } - else - { - targetWorld = this.worldObj; - } - - axisalignedbb = AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ); - - // FIXME - //turnOffModems(); - - // Calculate jump vector - if (isCoordJump) - { - moveX = destX - xCoord; - moveZ = destZ - zCoord; - moveY = destY - yCoord; - distance = 0; - } - else if (toHyperSpace || fromHyperSpace) - { - moveX = moveY = moveZ = 0; - distance = 0; - } - else - { - if (betweenWorlds) - { - moveX = moveY = 0; - - if (fromSpace) - { - moveY = 245 - maxY; - } - - if (toSpace) - { - moveY = 0; - } - } - else - { - // Do not check in long jumps - if (distance < 256) - { - distance = getPossibleJumpDistance(); - } - - if (distance <= shipLength) - { - killEntity("Not enough space for jump."); - messageToAllPlayersOnShip("Not enough space for jump!"); - LocalProfiler.stop(); - return; - } - - int movementVector[] = getVector(dir); - moveX = movementVector[0] * distance; - moveY = movementVector[1] * distance; - moveZ = movementVector[2] * distance; - - // Нужно не упереться в пол мира и потолок космоса - if ((maxY + moveY) > 255) - { - moveY = 255 - maxY; - } - - if ((minY + moveY) < 5) - { - moveY = 5 - minY; - } - } - } - - if (betweenWorlds) - { - System.out.println("[JE] Worlds: " + worldObj.provider.getDimensionName() + " -> " + targetWorld.provider.getDimensionName()); - } - - forceChunks(); - lockWorlds(); - saveEntities(axisalignedbb); - System.out.println("[JE] Saved " + entitiesOnShip.size() + " entities from ship"); - - if (!isCoordJump && !(toHyperSpace || fromHyperSpace)) - { - if (dir != -2 && dir != -1) - { - messageToAllPlayersOnShip("Jumping in direction " + dir + " degrees to distance " + distance + " blocks "); - } - else if (dir == -1) - { - messageToAllPlayersOnShip("Jumping UP to distance " + distance + " blocks "); - } - else if (dir == -2) - { - messageToAllPlayersOnShip("Jumping DOWN to distance " + distance + " blocks "); - } - } - else if (toHyperSpace) - { - messageToAllPlayersOnShip("Entering HYPERSPACE..."); - } - else if (fromHyperSpace) - { - messageToAllPlayersOnShip("Leaving HYPERSPACE"); - } - else if (isCoordJump) - { - messageToAllPlayersOnShip("Jumping by coordinates to (" + destX + "; " + yCoord + "; " + destZ + ")!"); - } - - bedrockOnShip = false; - int shipSize = getRealShipSize(); // sets bedrockOnShip - - if (bedrockOnShip) - { - killEntity("Bedrock is on the ship. Aborting."); - messageToAllPlayersOnShip("Bedrock is on the ship. Aborting."); - LocalProfiler.stop(); - return; - } - - saveShip(shipSize); - this.currentIndexInShip = 0; - msCounter = System.currentTimeMillis(); - LocalProfiler.stop(); - } - - /** - * Finish jump: move entities, unlock worlds and delete self - */ - public void finishJump() - { - System.out.println("[JE] Finished. Jump took " + ((System.currentTimeMillis() - msCounter) / 1000F) + " seconds"); - //FIXME TileEntity duplication workaround - System.out.println("Removing TE duplicates. Size before: " + targetWorld.loadedTileEntityList.size()); - LocalProfiler.start("EntityJump.removeDuplicates()"); - - try - { - targetWorld.loadedTileEntityList = this.removeDuplicates(targetWorld.loadedTileEntityList); - } - catch (Exception e) - { - System.out.println("TE Duplicates removing exception: " + e.getMessage()); - } - - LocalProfiler.stop(); - System.out.println("Removing TE duplicates. Size after: " + targetWorld.loadedTileEntityList.size()); - killEntity(""); - } - - /** - * Removing ship from world - * - */ - public void removeShip() - { - LocalProfiler.start("EntityJump.removeShip"); - int blocksToMove = Math.min(BLOCKS_PER_TICK, ship.length - currentIndexInShip); - System.out.println("[JE] Removing ship part: " + currentIndexInShip + "/" + ship.length + " [btm: " + blocksToMove + "]"); - - for (int index = 0; index < blocksToMove; index++) - { - if (currentIndexInShip >= ship.length) - { - break; - } - - JumpBlock jb = ship[currentIndexInShip]; - - if (jb != null && jb.blockTileEntity != null) - { - worldObj.removeBlockTileEntity(jb.x, jb.y, jb.z); - } - - // Refresh IC2 machines and cables - int newX = jb.x + moveX; - int newY = jb.y + moveY; - int newZ = jb.z + moveZ; - refreshIC2Tile(targetWorld, newX, newY, newZ); - //System.out.println("[EJ] Removing block: " + jb.x + " " + jb.y + " " + jb.z + " " + jb.blockID); - worldObj.setBlockToAir(jb.x, jb.y, jb.z); - currentIndexInShip++; - } - - LocalProfiler.stop(); - } - - // Fix IC2 blocks after jump via reflection calls - public static void refreshIC2Tile(World world, int x, int y, int z) - { - TileEntity te = world.getBlockTileEntity(x, y, z); - - if (te != null && te instanceof IEnergyTile) - { - Class c = te.getClass().getSuperclass(); - - // Cable - if (c.getName().equals("ic2.core.block.wiring.TileEntityElectricBlock")) - { - try - { - Method method; - method = c.getDeclaredMethod("onUnloaded", new Class[0]); - method.invoke(te, new Object[0]); - method = c.getDeclaredMethod("onLoaded", new Class[0]); - method.invoke(te, new Object[0]); - } - catch (Exception e) - { - //e.printStackTrace(); - } - } - else // Machine/Generator - if (c.getName().equals("ic2.core.block.TileEntityBlock") || c.getName().contains("ic2.core.block.generator")) - { - try - { - Method method; - method = c.getDeclaredMethod("onUnloaded", new Class[0]); - method.invoke(te, new Object[0]); - method = c.getDeclaredMethod("onLoaded", new Class[0]); - method.invoke(te, new Object[0]); - } - catch (Exception e) - { - //e.printStackTrace(); - } - } - - te.updateContainingBlockInfo(); - /* - try { - NetworkHelper.updateTileEntityField(te, "facing"); - } catch (Exception e) { - //e.printStackTrace(); - } - */ - } - } - - /** - * Saving ship to memory - * - * @param shipSize - */ - public void saveShip(int shipSize) - { - LocalProfiler.start("EntityJump.saveShip"); - ship = new JumpBlock[shipSize]; - - if (ship == null) - { - killEntity("ship is null!"); - LocalProfiler.stop(); - return; - } - - int index = 0; - int xc1 = minX >> 4; - int xc2 = maxX >> 4; - int zc1 = minZ >> 4; - int zc2 = maxZ >> 4; - - for (int xc = xc1; xc <= xc2; xc++) - { - int x1 = Math.max(minX, xc << 4); - int x2 = Math.min(maxX, (xc << 4) + 15); - - for (int zc = zc1; zc <= zc2; zc++) - { - int z1 = Math.max(minZ, zc << 4); - int z2 = Math.min(maxZ, (zc << 4) + 15); - - for (int y = minY; y <= maxY; y++) - { - for (int x = x1; x <= x2; x++) - { - for (int z = z1; z <= z2; z++) - { - int blockID = worldObj.getBlockId(x, y, z); - - // Skip air blocks - if (blockID == 0 || blockID == WarpDrive.instance.config.gasID) - { - continue; - } - - int blockMeta = worldObj.getBlockMetadata(x, y, z); - TileEntity tileentity = worldObj.getBlockTileEntity(x, y, z); - ship[index] = new JumpBlock(blockID, blockMeta, tileentity, x, y, z); - index++; - } - } - } - } - } - - System.out.println((new StringBuilder()).append("[JUMP] Ship saved: ").append((new StringBuilder()).append(ship.length).append(" blocks")).toString()); - LocalProfiler.stop(); - } - - /** - *Ship moving - */ - public void moveShip() - { - LocalProfiler.start("EntityJump.moveShip"); - int blocksToMove = Math.min(BLOCKS_PER_TICK, ship.length - currentIndexInShip); - System.out.println("[JE] Moving ship part: " + currentIndexInShip + "/" + ship.length + " [btm: " + blocksToMove + "]"); - - for (int index = 0; index < blocksToMove; index++) - { - if (currentIndexInShip >= ship.length) - { - break; - } - - moveBlockSimple(currentIndexInShip); - currentIndexInShip++; - } - - LocalProfiler.stop(); - } - - /** - * Checking jump possibility - * - * @return possible jump distance or -1 - */ - public int getPossibleJumpDistance() - { - System.out.println("[JUMP] Calculating possible jump distance..."); - int testDistance = this.distance; - int blowPoints = 0; - - while (testDistance >= 0) - { - // Is there enough space in destination point? - boolean canJump = checkMovement(testDistance); - - if (canJump) - { - break; - } - - blowPoints++; - testDistance--; - } - - // Make an explosion in collision point - if (blowPoints > 5 && (this.dir != -1 && this.dir != -2)) - { - messageToAllPlayersOnShip(" [COLLISION] at (" + blowX + "; " + blowY + "; " + blowZ + ")"); - worldObj.createExplosion((Entity) null, blowX, blowY, blowZ, Math.min(4F * 30, 4F * (distance / 2)), true); - } - - return testDistance; - } - - /* - * Получить реальное количество блоков, из которых состоит корабль - */ - public int getRealShipSize() - { - LocalProfiler.start("EntityJump.getRealShipSize"); - int shipSize = 0; - - for (int x = minX; x <= maxX; x++) - { - for (int z = minZ; z <= maxZ; z++) - { - for (int y = minY; y <= maxY; y++) - { - int blockID = worldObj.getBlockId(x, y, z); - - // Skipping air blocks - if (blockID == 0 || blockID == WarpDrive.instance.config.gasID) - { - continue; - } - - shipSize++; - - if (blockID == Block.bedrock.blockID) - { - bedrockOnShip = true; - LocalProfiler.stop(); - return shipSize; - } - } - } - } - - LocalProfiler.stop(); - return shipSize; - } - - public void saveEntities(AxisAlignedBB axisalignedbb) - { - entitiesOnShip = new ArrayList<MovingEntity>(); - List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, axisalignedbb); - - for (Object o : list) - { - if (o == null || !(o instanceof Entity) || (o instanceof EntityJump)) - { - continue; - } - - Entity entity = (Entity)o; - MovingEntity movingEntity = new MovingEntity(entity); - // Добавим в список Entity - entitiesOnShip.add(movingEntity); - } - } - - /** - * Перемещение сущностей вместе с кораблем - * @param axisalignedbb область корабля - * @param distance расстояние перемещения - * @param direction направление перемещения - * @param restorePositions восстановление старых позиций для предотвращения выпадения, либо перемещение на новую - * @return - */ - public boolean moveEntities(boolean restorePositions) - { - System.out.println("[JE] Moving entities"); - - if (entitiesOnShip != null) - { - for (MovingEntity me : entitiesOnShip) - { - Entity entity = me.entity; - - if (entity == null) - { - continue; - } - - double oldEntityX = me.oldX; - double oldEntityY = me.oldY; - double oldEntityZ = me.oldZ; - double newEntityX; - double newEntityY; - double newEntityZ; - - if (restorePositions) - { - newEntityX = oldEntityX; - newEntityY = oldEntityY; - newEntityZ = oldEntityZ; - } - else - { - newEntityX = oldEntityX + moveX; - newEntityY = oldEntityY + moveY; - newEntityZ = oldEntityZ + moveZ; - } - - //System.out.println("Entity moving: old (" + oldEntityX + " " + oldEntityY + " " + oldEntityZ + ") -> new (" + newEntityX + " " + newEntityY + " " + newEntityZ); - - // Travel to another dimension if needed - if (betweenWorlds && !restorePositions) - { - MinecraftServer server = MinecraftServer.getServer(); - WorldServer from = server.worldServerForDimension(worldObj.provider.dimensionId); - WorldServer to = server.worldServerForDimension(targetWorld.provider.dimensionId); - SpaceTeleporter teleporter = new SpaceTeleporter(to, 0, MathHelper.floor_double(newEntityX), MathHelper.floor_double(newEntityY), MathHelper.floor_double(newEntityZ)); - - if (entity instanceof EntityPlayerMP) - { - EntityPlayerMP player = (EntityPlayerMP) entity; - server.getConfigurationManager().transferPlayerToDimension(player, targetWorld.provider.dimensionId, teleporter); - } - else - { - server.getConfigurationManager().transferEntityToWorld(entity, worldObj.provider.dimensionId, from, to, teleporter); - } - } - - // Update position - if (entity instanceof EntityPlayerMP) - { - EntityPlayerMP player = (EntityPlayerMP) entity; - // Если на корабле есть кровать, то передвинуть точку спауна игрока - ChunkCoordinates bedLocation = player.getBedLocation(); - - if (bedLocation != null && testBB(axisalignedbb, bedLocation.posX, bedLocation.posY, bedLocation.posZ)) - { - bedLocation.posX = bedLocation.posX + moveX; - bedLocation.posY = bedLocation.posY + moveY; - bedLocation.posZ = bedLocation.posZ + moveZ; - player.setSpawnChunk(bedLocation, false); - } - - player.setPositionAndUpdate(newEntityX, newEntityY, newEntityZ); - } - else - { - entity.setPosition(newEntityX, newEntityY, newEntityZ); - } - } - } - - return true; - } - - /** - * Проверка на вхождение точки в область (bounding-box) - */ - public boolean testBB(AxisAlignedBB axisalignedbb, int x, int y, int z) - { - return axisalignedbb.minX <= (double) x && axisalignedbb.maxX >= (double) x && axisalignedbb.minY <= (double) y && axisalignedbb.maxY >= (double) y && axisalignedbb.minZ <= (double) z && axisalignedbb.maxZ >= (double) z; - } - - // Получение вектора в зависимости от направления прыжка - public int[] getVector(int i) - { - int v[] = - { - 0, 0, 0 - }; - - switch (i) - { - case -1: - v[1] = 1; - break; - - case -2: - v[1] = -1; - break; - - case 0: - v[0] = dx; - v[2] = dz; - break; - - case 180: - v[0] = -dx; - v[2] = -dz; - break; - - case 90: - v[0] = dz; - v[2] = -dx; - break; - - case 270: - v[0] = -dz; - v[2] = dx; - } - - return v; - } - - /** - * Проверка возможности установки корабля в месте, удалённом от корабля на - * определённом расстоянии в сторону прыжка - * - * @param i - * @return true, если корабль уместился на новом месте - */ - public boolean checkMovement(int testDistance) - { - if ((dir == -1 && maxY + testDistance > 255) && !toSpace) - { - System.out.println("[JUMP] Reactor will blow due +high limit"); - return false; - } - - if ((dir == -2 && minY - testDistance <= 8) && !fromSpace) - { - blowY = minY - testDistance; - blowX = xCoord; - blowZ = zCoord; - System.out.println("[JUMP] Reactor will blow due -low limit"); - return false; - } - - int movementVector[] = getVector(dir); - // TODO: Disasm, plz fix it. Local variable hiding class global field - int moveX = movementVector[0] * testDistance; - int moveY = movementVector[1] * testDistance; - int moveZ = movementVector[2] * testDistance; - - for (int y = minY; y <= maxY; y++) - { - for (int x = minX; x <= maxX; x++) - { - for (int z = minZ; z <= maxZ; z++) - { - int newX = x + moveX; - int newY = y + moveY; - int newZ = z + moveZ; - - if (isBlockInShip(newX, newY, newZ)) - { - continue; - } - - int blockID = worldObj.getBlockId(newX, newY, newZ); - int blockOnShipID = worldObj.getBlockId(x, y, z); - - if (blockOnShipID == Block.bedrock.blockID) - { - return false; - } - - if (blockOnShipID != 0 && blockID != 0 && blockID != WarpDrive.instance.config.airID && blockID != WarpDrive.instance.config.gasID && blockID != 18) - { - blowX = x; - blowY = y; - blowZ = z; - System.out.println((new StringBuilder()).append("[JUMP] Reactor will blow due BlockID ").append((new StringBuilder()).append(blockID).append(" at (").append(newX).append(";").append(newY).append(";").append(newZ).append(")").toString()).toString()); - return false; - } - } - } - } - - return true; - } - - /** - * Точка находится в варп-поле корабля? - * - * @param x - * @param y - * @param z - * @return true, если находится - */ - public boolean isBlockInShip(int x, int y, int z) - { - return x >= minX && x <= maxX && y >= minY && y <= maxY && z >= minZ && z <= maxZ; - } - - /** - * Выключение модема, если периферийное устройство является модемом - * @param p - периферийное устройство - */ - private void turnOffModem(IPeripheral p) - { - // FIXME - /*if (p.getType() == "modem") { - String[] methods = p.getMethodNames(); - for(int i = 0; i < methods.length; i++) { - if (methods[i] == "closeAll") { - try { - p.callMethod(null, i, null); // FIXME - } catch (Exception e) { - // ignore iy - } - return; - } - } - }*/ - } - - /** - * Выключение всех модемов на корабле - */ - private void turnOffModems() - { - // FIXME - /*for (int x = minX; x <= maxX; x++) { - for (int z = minZ; z <= maxZ; z++) { - for (int y = minY; y <= maxY; y++) { - int blockID = worldObj.getBlockId(x, y, z); - if (blockID == 0 || blockID == WarpDrive.instance.config.airID || blockID == WarpDrive.instance.config.gasID) { - continue; - } - - TileEntity tileEntity = worldObj.getBlockTileEntity(x, y, z); - if (tileEntity == null) continue; - - if (tileEntity instanceof IPeripheral) { - IPeripheral p = (IPeripheral)tileEntity; - turnOffModem(p); - } - if (tileEntity instanceof ITurtleAccess) { - ITurtleAccess a = (ITurtleAccess)tileEntity; - IPeripheral pl = a.getPeripheral(TurtleSide.Left); - if (pl != null) turnOffModem(pl); - IPeripheral pr = a.getPeripheral(TurtleSide.Right); - if (pr != null) turnOffModem(pr); - } - } - } - }*/ - } - - public boolean moveBlockSimple(int indexInShip) - { - try - { - JumpBlock shipBlock = ship[indexInShip]; - - if (shipBlock == null) - { - return false; - } - - int oldX = shipBlock.x; - int oldY = shipBlock.y; - int oldZ = shipBlock.z; - int newX = oldX + moveX; - int newY = oldY + moveY; - int newZ = oldZ + moveZ; - int blockID = shipBlock.blockID; - int blockMeta = shipBlock.blockMeta; - mySetBlock(targetWorld, newX, newY, newZ, blockID, blockMeta, 2); - - // Re-schedule air blocks update - if (blockID == WarpDrive.instance.config.airID) - { - targetWorld.markBlockForUpdate(newX, newY, newZ); - targetWorld.scheduleBlockUpdate(newX, newY, newZ, blockID, 40 + targetWorld.rand.nextInt(20)); - } - - NBTTagCompound oldnbt = new NBTTagCompound(); - - if (shipBlock.blockTileEntity != null && blockID != 159 && blockID != 149 && blockID != 156 && blockID != 146 && blockID != 145) - { - shipBlock.blockTileEntity.writeToNBT(oldnbt); - TileEntity newTileEntity = null; - - // CC's computers and turtles moving workaround - if (blockID == 1225 || blockID == 1226 || blockID == 1227 || blockID == 1228 || blockID == 1230) - { - oldnbt.setInteger("x", newX); - oldnbt.setInteger("y", newY); - oldnbt.setInteger("z", newZ); - newTileEntity = TileEntity.createAndLoadEntity(oldnbt); - newTileEntity.invalidate(); - } - else - { - newTileEntity = targetWorld.getBlockTileEntity(newX, newY, newZ); - - if (newTileEntity == null) - { - System.out.println("[EJ] Error moving tileEntity! TE is null"); - return false; - } - - newTileEntity.invalidate(); - newTileEntity.readFromNBT(oldnbt); - } - - newTileEntity.worldObj = targetWorld; - newTileEntity.validate(); - worldObj.removeBlockTileEntity(oldX, oldY, oldZ); - targetWorld.setBlockTileEntity(newX, newY, newZ, newTileEntity); - } - } - catch (Exception exception) - { - exception.printStackTrace(); - return false; - } - - return true; - } - - public ArrayList<Object> removeDuplicates(List<TileEntity> l) - { - Set<TileEntity> s = new TreeSet<TileEntity>(new Comparator<TileEntity>() - { - @Override - public int compare(TileEntity o1, TileEntity o2) - { - if (o1.xCoord == o2.xCoord && o1.yCoord == o2.yCoord && o1.zCoord == o2.zCoord) - { - System.out.println("Removed duplicated TE: " + o1 + ", " + o2); - return 0; - } - else - { - return 1; - } - } - }); - s.addAll(l); - return new ArrayList<Object>(Arrays.asList(s.toArray())); - } - - @Override - protected void readEntityFromNBT(NBTTagCompound nbttagcompound) - { - //System.out.println("[JE@"+this+"] readEntityFromNBT()"); - } - - @Override - protected void entityInit() - { - //System.out.println("[JE@"+this+"] entityInit()"); - } - - @Override - protected void writeEntityToNBT(NBTTagCompound var1) - { - //System.out.println("[JE@"+this+"] writeEntityToNBT()"); - } - - // Own implementation of setting blocks withow light recalculation in optimization purposes - public boolean mySetBlock(World w, int x, int y, int z, int blockId, int blockMeta, int par6) - { - if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) - { - if (y < 0) - { - return false; - } - else if (y >= 256) - { - return false; - } - else - { - w.markBlockForUpdate(x, y, z); - Chunk chunk = w.getChunkFromChunkCoords(x >> 4, z >> 4); - return myChunkSBIDWMT(chunk, x & 15, y, z & 15, blockId, blockMeta); - } - } - else - { - return false; - } - } - - public boolean myChunkSBIDWMT(Chunk c, int x, int y, int z, int blockId, int blockMeta) - { - int j1 = z << 4 | x; - - if (y >= c.precipitationHeightMap[j1] - 1) - { - c.precipitationHeightMap[j1] = -999; - } - - //int k1 = c.heightMap[j1]; - int l1 = c.getBlockID(x, y, z); - int i2 = c.getBlockMetadata(x, y, z); - - if (l1 == blockId && i2 == blockMeta) - { - return false; - } - else - { - ExtendedBlockStorage[] storageArrays = c.getBlockStorageArray(); - ExtendedBlockStorage extendedblockstorage = storageArrays[y >> 4]; - - if (extendedblockstorage == null) - { - if (blockId == 0) - { - return false; - } - - extendedblockstorage = storageArrays[y >> 4] = new ExtendedBlockStorage(y >> 4 << 4, !c.worldObj.provider.hasNoSky); - } - - int j2 = c.xPosition * 16 + x; - int k2 = c.zPosition * 16 + z; - extendedblockstorage.setExtBlockID(x, y & 15, z, blockId); - - if (l1 != 0) - { - if (!c.worldObj.isRemote) - { - Block.blocksList[l1].breakBlock(c.worldObj, j2, y, k2, l1, i2); - } - else if (Block.blocksList[l1] != null && Block.blocksList[l1].hasTileEntity(i2)) - { - TileEntity te = worldObj.getBlockTileEntity(j2, y, k2); - - if (te != null && te.shouldRefresh(l1, blockId, i2, blockMeta, worldObj, j2, y, k2)) - { - c.worldObj.removeBlockTileEntity(j2, y, k2); - } - } - } - - if (extendedblockstorage.getExtBlockID(x, y & 15, z) != blockId) - { - return false; - } - else - { - extendedblockstorage.setExtBlockMetadata(x, y & 15, z, blockMeta); - // Removed light recalculations - /*if (flag) - { - c.generateSkylightMap(); - } - else - { - if (c.getBlockLightOpacity(par1, par2, par3) > 0) - { - if (par2 >= k1) - { - c.relightBlock(par1, par2 + 1, par3); - } - } - else if (par2 == k1 - 1) - { - c.relightBlock(par1, par2, par3); - } - - c.propagateSkylightOcclusion(par1, par3); - }*/ - TileEntity tileentity; - - if (blockId != 0) - { - if (Block.blocksList[blockId] != null && Block.blocksList[blockId].hasTileEntity(blockMeta)) - { - tileentity = c.getChunkBlockTileEntity(x, y, z); - - if (tileentity == null) - { - tileentity = Block.blocksList[blockId].createTileEntity(c.worldObj, blockMeta); - c.worldObj.setBlockTileEntity(j2, y, k2, tileentity); - } - - if (tileentity != null) - { - tileentity.updateContainingBlockInfo(); - tileentity.blockMetadata = blockMeta; - } - } - } - - c.isModified = true; - return true; - } - } - } + // Jump vector + private int moveX; + private int moveY; + private int moveZ; + + public int xCoord; + public int yCoord; + public int zCoord; + public int distance; + public int dir; + public int shipLeft; + public int shipRight; + public int shipFront; + public int shipBack; + public int shipDown; + public int shipUp; + public int shipLength; + public int maxX; + public int maxZ; + public int maxY; + public int minX; + public int minZ; + public int minY; + public int dx; + public int dz; + + public int mode; + + public World targetWorld; + private Ticket sourceWorldTicket; + private Ticket targetWorldTicket; + + // Collision point coordinates + public int blowX, blowY, blowZ; + boolean needToExplode = false; + public boolean on = false; + public boolean bedrockOnShip = false; + public JumpBlock ship[]; + public TileEntityReactor reactor; + + public final static int STATE_IDLE = 0; + public final static int STATE_JUMPING = 1; + public final static int STATE_REMOVING = 2; + int state = STATE_IDLE; + int currentIndexInShip = 0; + + private final int BLOCKS_PER_TICK = 3500; + + private List<MovingEntity> entitiesOnShip; + + AxisAlignedBB axisalignedbb; + + private boolean fromSpace, toSpace, betweenWorlds; + public boolean toHyperSpace, fromHyperSpace; + private boolean isInHyperSpace; + + int destX, destY, destZ; + boolean isCoordJump; + + long msCounter = 0; + + public EntityJump(World world) + { + super(world); + targetWorld = worldObj; + System.out.println("[JE@" + this + "] Entity created (empty)"); + } + + public EntityJump(World world, int x, int y, int z, int _dist, int _direction, int _dx, int _dz, TileEntityReactor parReactor) + { + super(world); + this.xCoord = x; + this.posX = (double) x; + this.yCoord = y; + this.posY = (double) y; + this.zCoord = z; + this.posZ = (double) z; + this.distance = _dist; + this.dir = _direction; + shipLeft = shipRight = shipFront = shipBack = shipDown = shipUp = shipLength = 0; + this.dx = _dx; + this.dz = _dz; + maxX = maxZ = maxY = minX = minZ = minY = 0; + targetWorld = worldObj; + System.out.println("[JE@" + this + "] Entity created"); + this.reactor = parReactor; + } + + public void killEntity(String reason) + { + if (!on) + { + return; + } + + on = false; + System.out.println("[JE@" + this + "] Killing jump entity..."); + + if (!reason.isEmpty()) + { + System.out.println("[JUMP] Killed: " + reason); + } + + unlockWorlds(); + unforceChunks(); + worldObj.removeEntity(this); + } + + @Override + public void onUpdate() + { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + return; + } + + if (!on) + { + worldObj.removeEntity(this); + return; + } + + if (minY < 0 || maxY > 256) + { + killEntity("Y-coord error!"); + return; + } + + if (state == STATE_IDLE) + { + System.out.println("[JE] Preparing to jump..."); + prepareToJump(); + state = STATE_JUMPING; + } + else if (state == STATE_JUMPING) + { + if (currentIndexInShip >= ship.length - 1) + { + moveEntities(false); + currentIndexInShip = 0; + state = STATE_REMOVING; + } + else + { + //moveEntities(true); + moveShip(); + } + } + else if (state == STATE_REMOVING) + { + removeShip(); + + if (currentIndexInShip >= ship.length - 1) + { + finishJump(); + state = STATE_IDLE; + } + } + } + + private void forceChunks() + { + System.out.println("[JE@" + this + "] Forcing chunks"); + sourceWorldTicket = ForgeChunkManager.requestTicket(WarpDrive.instance, worldObj, Type.ENTITY); + targetWorldTicket = ForgeChunkManager.requestTicket(WarpDrive.instance, targetWorld, Type.NORMAL); + sourceWorldTicket.bindEntity(this); + int x1 = minX >> 4; + int x2 = maxX >> 4; + int z1 = minZ >> 4; + int z2 = maxZ >> 4; + + for (int x = x1; x <= x2; x++) + { + for (int z = z1; z <= z2; z++) + { + ForgeChunkManager.forceChunk(sourceWorldTicket, new ChunkCoordIntPair(x, z)); + } + } + + x1 = (minX + moveX) >> 4; + x2 = (maxX + moveX) >> 4; + z1 = (minZ + moveZ) >> 4; + z2 = (maxZ + moveZ) >> 4; + + for (int x = x1; x <= x2; x++) + { + for (int z = z1; z <= z2; z++) + { + ForgeChunkManager.forceChunk(targetWorldTicket, new ChunkCoordIntPair(x, z)); + } + } + } + + private void unforceChunks() + { + System.out.println("[JE@" + this + "] Unforcing chunks"); + + if (sourceWorldTicket == null || targetWorldTicket == null) + { + return; + } + + int x1 = minX >> 4; + int x2 = maxX >> 4; + int z1 = minZ >> 4; + int z2 = maxZ >> 4; + + for (int x = x1; x <= x2; x++) + { + for (int z = z1; z <= z2; z++) + { + ForgeChunkManager.unforceChunk(sourceWorldTicket, new ChunkCoordIntPair(x, z)); + } + } + + x1 = (minX + moveX) >> 4; + x2 = (maxX + moveX) >> 4; + z1 = (minZ + moveZ) >> 4; + z2 = (maxZ + moveZ) >> 4; + + for (int x = x1; x <= x2; x++) + { + for (int z = z1; z <= z2; z++) + { + ForgeChunkManager.unforceChunk(targetWorldTicket, new ChunkCoordIntPair(x, z)); + } + } + + ForgeChunkManager.releaseTicket(sourceWorldTicket); + ForgeChunkManager.releaseTicket(targetWorldTicket); + sourceWorldTicket = null; + targetWorldTicket = null; + } + + public void lockWorlds() + { + System.out.println("[JE@" + this + "] Locking worlds..."); + targetWorld.isRemote = true; + + // When warping between dimensions is need to lock both worlds + if (targetWorld.provider.dimensionId != worldObj.provider.dimensionId) + { + worldObj.isRemote = true; + } + } + + public void unlockWorlds() + { + System.out.println("[JE@" + this + "] Unlocking worlds.."); + targetWorld.isRemote = false; + + if (targetWorld.provider.dimensionId != worldObj.provider.dimensionId) + { + worldObj.isRemote = false; + } + } + + public void messageToAllPlayersOnShip(String msg) + { + if (entitiesOnShip != null) + { + for (MovingEntity me : entitiesOnShip) + { + Entity entity = me.entity; + + if (entity instanceof EntityPlayer) + { + ((EntityPlayer)entity).addChatMessage("[WarpCore] " + msg); + } + } + } + } + + public void prepareToJump() + { + LocalProfiler.start("EntityJump.prepareToJump"); + isInHyperSpace = (worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID); + toSpace = (dir == -1 && (maxY + distance > 255) && worldObj.provider.dimensionId == 0); + fromSpace = (dir == -2 && (minY - distance < 0) && worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID); + betweenWorlds = fromSpace || toSpace || toHyperSpace || fromHyperSpace; + + if (toSpace || fromHyperSpace) + { + targetWorld = DimensionManager.getWorld(WarpDrive.instance.spaceDimID); + } + else if (fromSpace) + { + targetWorld = DimensionManager.getWorld(0); + } + else if (toHyperSpace) + { + targetWorld = DimensionManager.getWorld(WarpDrive.instance.hyperSpaceDimID); + } + else + { + targetWorld = this.worldObj; + } + + axisalignedbb = AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ); + + // FIXME + //turnOffModems(); + + // Calculate jump vector + if (isCoordJump) + { + moveX = destX - xCoord; + moveZ = destZ - zCoord; + moveY = destY - yCoord; + distance = 0; + } + else if (toHyperSpace || fromHyperSpace) + { + moveX = moveY = moveZ = 0; + distance = 0; + } + else + { + if (betweenWorlds) + { + moveX = moveY = 0; + + if (fromSpace) + { + moveY = 245 - maxY; + } + + if (toSpace) + { + moveY = 0; + } + } + else + { + // Do not check in long jumps + if (distance < 256) + { + distance = getPossibleJumpDistance(); + } + + if (distance <= shipLength) + { + killEntity("Not enough space for jump."); + messageToAllPlayersOnShip("Not enough space for jump!"); + LocalProfiler.stop(); + return; + } + + int movementVector[] = getVector(dir); + moveX = movementVector[0] * distance; + moveY = movementVector[1] * distance; + moveZ = movementVector[2] * distance; + + // Нужно не упереться в пол мира и потолок космоса + if ((maxY + moveY) > 255) + { + moveY = 255 - maxY; + } + + if ((minY + moveY) < 5) + { + moveY = 5 - minY; + } + } + } + + if (betweenWorlds) + { + System.out.println("[JE] Worlds: " + worldObj.provider.getDimensionName() + " -> " + targetWorld.provider.getDimensionName()); + } + + forceChunks(); + lockWorlds(); + saveEntities(axisalignedbb); + System.out.println("[JE] Saved " + entitiesOnShip.size() + " entities from ship"); + + if (!isCoordJump && !(toHyperSpace || fromHyperSpace)) + { + if (dir != -2 && dir != -1) + { + messageToAllPlayersOnShip("Jumping in direction " + dir + " degrees to distance " + distance + " blocks "); + } + else if (dir == -1) + { + messageToAllPlayersOnShip("Jumping UP to distance " + distance + " blocks "); + } + else if (dir == -2) + { + messageToAllPlayersOnShip("Jumping DOWN to distance " + distance + " blocks "); + } + } + else if (toHyperSpace) + { + messageToAllPlayersOnShip("Entering HYPERSPACE..."); + } + else if (fromHyperSpace) + { + messageToAllPlayersOnShip("Leaving HYPERSPACE"); + } + else if (isCoordJump) + { + messageToAllPlayersOnShip("Jumping by coordinates to (" + destX + "; " + yCoord + "; " + destZ + ")!"); + } + + bedrockOnShip = false; + int shipSize = getRealShipSize(); // sets bedrockOnShip + + if (bedrockOnShip) + { + killEntity("Bedrock is on the ship. Aborting."); + messageToAllPlayersOnShip("Bedrock is on the ship. Aborting."); + LocalProfiler.stop(); + return; + } + + saveShip(shipSize); + this.currentIndexInShip = 0; + msCounter = System.currentTimeMillis(); + LocalProfiler.stop(); + System.out.println("Removing TE duplicates. Size before jump: " + targetWorld.loadedTileEntityList.size()); + } + + /** + * Finish jump: move entities, unlock worlds and delete self + */ + public void finishJump() + { + System.out.println("[JE] Finished. Jump took " + ((System.currentTimeMillis() - msCounter) / 1000F) + " seconds"); + //FIXME TileEntity duplication workaround + System.out.println("Removing TE duplicates. Size before: " + targetWorld.loadedTileEntityList.size()); + LocalProfiler.start("EntityJump.removeDuplicates()"); + + try + { + targetWorld.loadedTileEntityList = this.removeDuplicates(targetWorld.loadedTileEntityList); + } + catch (Exception e) + { + System.out.println("TE Duplicates removing exception: " + e.getMessage()); + } + + LocalProfiler.stop(); + System.out.println("Removing TE duplicates. Size after: " + targetWorld.loadedTileEntityList.size()); + killEntity(""); + } + + /** + * Removing ship from world + * + */ + public void removeShip() + { + LocalProfiler.start("EntityJump.removeShip"); + int blocksToMove = Math.min(BLOCKS_PER_TICK, ship.length - currentIndexInShip); + System.out.println("[JE] Removing ship part: " + currentIndexInShip + "/" + ship.length + " [btm: " + blocksToMove + "]"); + + for (int index = 0; index < blocksToMove; index++) + { + if (currentIndexInShip >= ship.length) + { + break; + } + + JumpBlock jb = ship[currentIndexInShip]; + + if (jb != null && jb.blockTileEntity != null) + { + worldObj.removeBlockTileEntity(jb.x, jb.y, jb.z); + } + + // Refresh IC2 machines and cables + int newX = jb.x + moveX; + int newY = jb.y + moveY; + int newZ = jb.z + moveZ; + refreshIC2Tile(targetWorld, newX, newY, newZ); + //System.out.println("[EJ] Removing block: " + jb.x + " " + jb.y + " " + jb.z + " " + jb.blockID); + worldObj.setBlockToAir(jb.x, jb.y, jb.z); + currentIndexInShip++; + } + + LocalProfiler.stop(); + } + + // Fix IC2 blocks after jump via reflection calls + public static void refreshIC2Tile(World world, int x, int y, int z) + { + TileEntity te = world.getBlockTileEntity(x, y, z); + + if (te != null && te instanceof IEnergyTile) + { + Class c = te.getClass().getSuperclass(); + + // Cable + if (c.getName().equals("ic2.core.block.wiring.TileEntityElectricBlock")) + { + try + { + Method method; + method = c.getDeclaredMethod("onUnloaded", new Class[0]); + method.invoke(te, new Object[0]); + method = c.getDeclaredMethod("onLoaded", new Class[0]); + method.invoke(te, new Object[0]); + } + catch (Exception e) + { + //e.printStackTrace(); + } + } + else // Machine/Generator + if (c.getName().equals("ic2.core.block.TileEntityBlock") || c.getName().contains("ic2.core.block.generator")) + { + try + { + Method method; + method = c.getDeclaredMethod("onUnloaded", new Class[0]); + method.invoke(te, new Object[0]); + method = c.getDeclaredMethod("onLoaded", new Class[0]); + method.invoke(te, new Object[0]); + } + catch (Exception e) + { + //e.printStackTrace(); + } + } + + te.updateContainingBlockInfo(); + /* + try { + NetworkHelper.updateTileEntityField(te, "facing"); + } catch (Exception e) { + //e.printStackTrace(); + } + */ + } + } + + /** + * Saving ship to memory + * + * @param shipSize + */ + public void saveShip(int shipSize) + { + LocalProfiler.start("EntityJump.saveShip"); + ship = new JumpBlock[shipSize]; + + if (ship == null) + { + killEntity("ship is null!"); + LocalProfiler.stop(); + return; + } + + int index = 0; + int xc1 = minX >> 4; + int xc2 = maxX >> 4; + int zc1 = minZ >> 4; + int zc2 = maxZ >> 4; + + for (int xc = xc1; xc <= xc2; xc++) + { + int x1 = Math.max(minX, xc << 4); + int x2 = Math.min(maxX, (xc << 4) + 15); + + for (int zc = zc1; zc <= zc2; zc++) + { + int z1 = Math.max(minZ, zc << 4); + int z2 = Math.min(maxZ, (zc << 4) + 15); + + for (int y = minY; y <= maxY; y++) + { + for (int x = x1; x <= x2; x++) + { + for (int z = z1; z <= z2; z++) + { + int blockID = worldObj.getBlockId(x, y, z); + + // Skip air blocks + if (blockID == 0 || blockID == WarpDrive.instance.config.gasID) + { + continue; + } + + int blockMeta = worldObj.getBlockMetadata(x, y, z); + TileEntity tileentity = worldObj.getBlockTileEntity(x, y, z); + ship[index] = new JumpBlock(blockID, blockMeta, tileentity, x, y, z); + index++; + } + } + } + } + } + + System.out.println((new StringBuilder()).append("[JUMP] Ship saved: ").append((new StringBuilder()).append(ship.length).append(" blocks")).toString()); + LocalProfiler.stop(); + } + + /** + *Ship moving + */ + public void moveShip() + { + LocalProfiler.start("EntityJump.moveShip"); + int blocksToMove = Math.min(BLOCKS_PER_TICK, ship.length - currentIndexInShip); + System.out.println("[JE] Moving ship part: " + currentIndexInShip + "/" + ship.length + " [btm: " + blocksToMove + "]"); + + for (int index = 0; index < blocksToMove; index++) + { + if (currentIndexInShip >= ship.length) + { + break; + } + + moveBlockSimple(currentIndexInShip); + currentIndexInShip++; + } + + LocalProfiler.stop(); + } + + /** + * Checking jump possibility + * + * @return possible jump distance or -1 + */ + public int getPossibleJumpDistance() + { + System.out.println("[JUMP] Calculating possible jump distance..."); + int testDistance = this.distance; + int blowPoints = 0; + + while (testDistance >= 0) + { + // Is there enough space in destination point? + boolean canJump = checkMovement(testDistance); + + if (canJump) + { + break; + } + + blowPoints++; + testDistance--; + } + + // Make an explosion in collision point + if (blowPoints > 5 && (this.dir != -1 && this.dir != -2)) + { + messageToAllPlayersOnShip(" [COLLISION] at (" + blowX + "; " + blowY + "; " + blowZ + ")"); + worldObj.createExplosion((Entity) null, blowX, blowY, blowZ, Math.min(4F * 30, 4F * (distance / 2)), true); + } + + return testDistance; + } + + /* + * Получить реальное количество блоков, из которых состоит корабль + */ + public int getRealShipSize() + { + LocalProfiler.start("EntityJump.getRealShipSize"); + int shipSize = 0; + + for (int x = minX; x <= maxX; x++) + { + for (int z = minZ; z <= maxZ; z++) + { + for (int y = minY; y <= maxY; y++) + { + int blockID = worldObj.getBlockId(x, y, z); + + // Skipping air blocks + if (blockID == 0 || blockID == WarpDrive.instance.config.gasID) + { + continue; + } + + shipSize++; + + if (blockID == Block.bedrock.blockID) + { + bedrockOnShip = true; + LocalProfiler.stop(); + return shipSize; + } + } + } + } + + LocalProfiler.stop(); + return shipSize; + } + + public void saveEntities(AxisAlignedBB axisalignedbb) + { + entitiesOnShip = new ArrayList<MovingEntity>(); + List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, axisalignedbb); + + for (Object o : list) + { + if (o == null || !(o instanceof Entity) || (o instanceof EntityJump)) + { + continue; + } + + Entity entity = (Entity)o; + MovingEntity movingEntity = new MovingEntity(entity); + // Добавим в список Entity + entitiesOnShip.add(movingEntity); + } + } + + /** + * Перемещение сущностей вместе с кораблем + * @param axisalignedbb область корабля + * @param distance расстояние перемещения + * @param direction направление перемещения + * @param restorePositions восстановление старых позиций для предотвращения выпадения, либо перемещение на новую + * @return + */ + public boolean moveEntities(boolean restorePositions) + { + System.out.println("[JE] Moving entities"); + + if (entitiesOnShip != null) + { + for (MovingEntity me : entitiesOnShip) + { + Entity entity = me.entity; + + if (entity == null) + { + continue; + } + + double oldEntityX = me.oldX; + double oldEntityY = me.oldY; + double oldEntityZ = me.oldZ; + double newEntityX; + double newEntityY; + double newEntityZ; + + if (restorePositions) + { + newEntityX = oldEntityX; + newEntityY = oldEntityY; + newEntityZ = oldEntityZ; + } + else + { + newEntityX = oldEntityX + moveX; + newEntityY = oldEntityY + moveY; + newEntityZ = oldEntityZ + moveZ; + } + + //System.out.println("Entity moving: old (" + oldEntityX + " " + oldEntityY + " " + oldEntityZ + ") -> new (" + newEntityX + " " + newEntityY + " " + newEntityZ); + + // Travel to another dimension if needed + if (betweenWorlds && !restorePositions) + { + MinecraftServer server = MinecraftServer.getServer(); + WorldServer from = server.worldServerForDimension(worldObj.provider.dimensionId); + WorldServer to = server.worldServerForDimension(targetWorld.provider.dimensionId); + SpaceTeleporter teleporter = new SpaceTeleporter(to, 0, MathHelper.floor_double(newEntityX), MathHelper.floor_double(newEntityY), MathHelper.floor_double(newEntityZ)); + + if (entity instanceof EntityPlayerMP) + { + EntityPlayerMP player = (EntityPlayerMP) entity; + server.getConfigurationManager().transferPlayerToDimension(player, targetWorld.provider.dimensionId, teleporter); + } + else + { + server.getConfigurationManager().transferEntityToWorld(entity, worldObj.provider.dimensionId, from, to, teleporter); + } + } + + // Update position + if (entity instanceof EntityPlayerMP) + { + EntityPlayerMP player = (EntityPlayerMP) entity; + // Если на корабле есть кровать, то передвинуть точку спауна игрока + ChunkCoordinates bedLocation = player.getBedLocation(); + + if (bedLocation != null && testBB(axisalignedbb, bedLocation.posX, bedLocation.posY, bedLocation.posZ)) + { + bedLocation.posX = bedLocation.posX + moveX; + bedLocation.posY = bedLocation.posY + moveY; + bedLocation.posZ = bedLocation.posZ + moveZ; + player.setSpawnChunk(bedLocation, false); + } + + player.setPositionAndUpdate(newEntityX, newEntityY, newEntityZ); + } + else + { + entity.setPosition(newEntityX, newEntityY, newEntityZ); + } + } + } + + return true; + } + + /** + * Проверка на вхождение точки в область (bounding-box) + */ + public boolean testBB(AxisAlignedBB axisalignedbb, int x, int y, int z) + { + return axisalignedbb.minX <= (double) x && axisalignedbb.maxX >= (double) x && axisalignedbb.minY <= (double) y && axisalignedbb.maxY >= (double) y && axisalignedbb.minZ <= (double) z && axisalignedbb.maxZ >= (double) z; + } + + // Получение вектора в зависимости от направления прыжка + public int[] getVector(int i) + { + int v[] = + { + 0, 0, 0 + }; + + switch (i) + { + case -1: + v[1] = 1; + break; + + case -2: + v[1] = -1; + break; + + case 0: + v[0] = dx; + v[2] = dz; + break; + + case 180: + v[0] = -dx; + v[2] = -dz; + break; + + case 90: + v[0] = dz; + v[2] = -dx; + break; + + case 270: + v[0] = -dz; + v[2] = dx; + } + + return v; + } + + /** + * Проверка возможности установки корабля в месте, удалённом от корабля на + * определённом расстоянии в сторону прыжка + * + * @param i + * @return true, если корабль уместился на новом месте + */ + public boolean checkMovement(int testDistance) + { + if ((dir == -1 && maxY + testDistance > 255) && !toSpace) + { + System.out.println("[JUMP] Reactor will blow due +high limit"); + return false; + } + + if ((dir == -2 && minY - testDistance <= 8) && !fromSpace) + { + blowY = minY - testDistance; + blowX = xCoord; + blowZ = zCoord; + System.out.println("[JUMP] Reactor will blow due -low limit"); + return false; + } + + int movementVector[] = getVector(dir); + // TODO: Disasm, plz fix it. Local variable hiding class global field + int moveX = movementVector[0] * testDistance; + int moveY = movementVector[1] * testDistance; + int moveZ = movementVector[2] * testDistance; + + for (int y = minY; y <= maxY; y++) + { + for (int x = minX; x <= maxX; x++) + { + for (int z = minZ; z <= maxZ; z++) + { + int newX = x + moveX; + int newY = y + moveY; + int newZ = z + moveZ; + + if (isBlockInShip(newX, newY, newZ)) + { + continue; + } + + int blockID = worldObj.getBlockId(newX, newY, newZ); + int blockOnShipID = worldObj.getBlockId(x, y, z); + + if (blockOnShipID == Block.bedrock.blockID) + { + return false; + } + + if (blockOnShipID != 0 && blockID != 0 && blockID != WarpDrive.instance.config.airID && blockID != WarpDrive.instance.config.gasID && blockID != 18) + { + blowX = x; + blowY = y; + blowZ = z; + System.out.println((new StringBuilder()).append("[JUMP] Reactor will blow due BlockID ").append((new StringBuilder()).append(blockID).append(" at (").append(newX).append(";").append(newY).append(";").append(newZ).append(")").toString()).toString()); + return false; + } + } + } + } + + return true; + } + + /** + * Точка находится в варп-поле корабля? + * + * @param x + * @param y + * @param z + * @return true, если находится + */ + public boolean isBlockInShip(int x, int y, int z) + { + return x >= minX && x <= maxX && y >= minY && y <= maxY && z >= minZ && z <= maxZ; + } + + /** + * Выключение модема, если периферийное устройство является модемом + * @param p - периферийное устройство + */ + private void turnOffModem(IPeripheral p) + { + // FIXME + /*if (p.getType() == "modem") { + String[] methods = p.getMethodNames(); + for(int i = 0; i < methods.length; i++) { + if (methods[i] == "closeAll") { + try { + p.callMethod(null, i, null); // FIXME + } catch (Exception e) { + // ignore iy + } + return; + } + } + }*/ + } + + /** + * Выключение всех модемов на корабле + */ + private void turnOffModems() + { + // FIXME + /*for (int x = minX; x <= maxX; x++) { + for (int z = minZ; z <= maxZ; z++) { + for (int y = minY; y <= maxY; y++) { + int blockID = worldObj.getBlockId(x, y, z); + if (blockID == 0 || blockID == WarpDrive.instance.config.airID || blockID == WarpDrive.instance.config.gasID) { + continue; + } + + TileEntity tileEntity = worldObj.getBlockTileEntity(x, y, z); + if (tileEntity == null) continue; + + if (tileEntity instanceof IPeripheral) { + IPeripheral p = (IPeripheral)tileEntity; + turnOffModem(p); + } + if (tileEntity instanceof ITurtleAccess) { + ITurtleAccess a = (ITurtleAccess)tileEntity; + IPeripheral pl = a.getPeripheral(TurtleSide.Left); + if (pl != null) turnOffModem(pl); + IPeripheral pr = a.getPeripheral(TurtleSide.Right); + if (pr != null) turnOffModem(pr); + } + } + } + }*/ + } + + public boolean moveBlockSimple(int indexInShip) + { + try + { + JumpBlock shipBlock = ship[indexInShip]; + + if (shipBlock == null) + { + return false; + } + + int oldX = shipBlock.x; + int oldY = shipBlock.y; + int oldZ = shipBlock.z; + int newX = oldX + moveX; + int newY = oldY + moveY; + int newZ = oldZ + moveZ; + int blockID = shipBlock.blockID; + int blockMeta = shipBlock.blockMeta; + mySetBlock(targetWorld, newX, newY, newZ, blockID, blockMeta, 2); + + // Re-schedule air blocks update + if (blockID == WarpDrive.instance.config.airID) + { + targetWorld.markBlockForUpdate(newX, newY, newZ); + targetWorld.scheduleBlockUpdate(newX, newY, newZ, blockID, 40 + targetWorld.rand.nextInt(20)); + } + + NBTTagCompound oldnbt = new NBTTagCompound(); + + if (shipBlock.blockTileEntity != null && blockID != 159 && blockID != 149 && blockID != 156 && blockID != 146 && blockID != 145) + { + shipBlock.blockTileEntity.writeToNBT(oldnbt); + TileEntity newTileEntity = null; + + // CC's computers and turtles moving workaround && 4059 - GRECHKA TIME + if (blockID == 1225 || blockID == 1226 || blockID == 1227 || blockID == 1228 || blockID == 1230) + { + oldnbt.setInteger("x", newX); + oldnbt.setInteger("y", newY); + oldnbt.setInteger("z", newZ); + newTileEntity = TileEntity.createAndLoadEntity(oldnbt); + newTileEntity.invalidate(); + } + else if (blockID == 4059) + { + oldnbt.setInteger("x", newX); + oldnbt.setInteger("y", newY); + oldnbt.setInteger("z", newZ); + newTileEntity = TileEntity.createAndLoadEntity(oldnbt); + } + else + { + newTileEntity = targetWorld.getBlockTileEntity(newX, newY, newZ); + if (newTileEntity == null) + { + System.out.println("[EJ] Error moving tileEntity! TE is null"); + return false; + } + newTileEntity.invalidate(); + newTileEntity.readFromNBT(oldnbt); + } + + newTileEntity.worldObj = targetWorld; + newTileEntity.validate(); + worldObj.removeBlockTileEntity(oldX, oldY, oldZ); + targetWorld.setBlockTileEntity(newX, newY, newZ, newTileEntity); + } + } + catch (Exception exception) + { + exception.printStackTrace(); + return false; + } + + return true; + } + + public ArrayList<Object> removeDuplicates(List<TileEntity> l) + { + Set<TileEntity> s = new TreeSet<TileEntity>(new Comparator<TileEntity>() + { + @Override + public int compare(TileEntity o1, TileEntity o2) + { + if (o1.xCoord == o2.xCoord && o1.yCoord == o2.yCoord && o1.zCoord == o2.zCoord) + { + System.out.println("Removed duplicated TE: " + o1 + ", " + o2); + return 0; + } + else + { + return 1; + } + } + }); + s.addAll(l); + return new ArrayList<Object>(Arrays.asList(s.toArray())); + } + + @Override + protected void readEntityFromNBT(NBTTagCompound nbttagcompound) + { + //System.out.println("[JE@"+this+"] readEntityFromNBT()"); + } + + @Override + protected void entityInit() + { + //System.out.println("[JE@"+this+"] entityInit()"); + } + + @Override + protected void writeEntityToNBT(NBTTagCompound var1) + { + //System.out.println("[JE@"+this+"] writeEntityToNBT()"); + } + + // Own implementation of setting blocks withow light recalculation in optimization purposes + public boolean mySetBlock(World w, int x, int y, int z, int blockId, int blockMeta, int par6) + { + if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) + { + if (y < 0) + { + return false; + } + else if (y >= 256) + { + return false; + } + else + { + w.markBlockForUpdate(x, y, z); + Chunk chunk = w.getChunkFromChunkCoords(x >> 4, z >> 4); + return myChunkSBIDWMT(chunk, x & 15, y, z & 15, blockId, blockMeta); + } + } + else + { + return false; + } + } + + public boolean myChunkSBIDWMT(Chunk c, int x, int y, int z, int blockId, int blockMeta) + { + int j1 = z << 4 | x; + + if (y >= c.precipitationHeightMap[j1] - 1) + { + c.precipitationHeightMap[j1] = -999; + } + + //int k1 = c.heightMap[j1]; + int l1 = c.getBlockID(x, y, z); + int i2 = c.getBlockMetadata(x, y, z); + + if (l1 == blockId && i2 == blockMeta) + { + return false; + } + else + { + ExtendedBlockStorage[] storageArrays = c.getBlockStorageArray(); + ExtendedBlockStorage extendedblockstorage = storageArrays[y >> 4]; + + if (extendedblockstorage == null) + { + if (blockId == 0) + { + return false; + } + + extendedblockstorage = storageArrays[y >> 4] = new ExtendedBlockStorage(y >> 4 << 4, !c.worldObj.provider.hasNoSky); + } + + int j2 = c.xPosition * 16 + x; + int k2 = c.zPosition * 16 + z; + extendedblockstorage.setExtBlockID(x, y & 15, z, blockId); + + if (l1 != 0) + { + if (!c.worldObj.isRemote) + { + Block.blocksList[l1].breakBlock(c.worldObj, j2, y, k2, l1, i2); + } + else if (Block.blocksList[l1] != null && Block.blocksList[l1].hasTileEntity(i2)) + { + TileEntity te = worldObj.getBlockTileEntity(j2, y, k2); + + if (te != null && te.shouldRefresh(l1, blockId, i2, blockMeta, worldObj, j2, y, k2)) + { + c.worldObj.removeBlockTileEntity(j2, y, k2); + } + } + } + + if (extendedblockstorage.getExtBlockID(x, y & 15, z) != blockId) + { + return false; + } + else + { + extendedblockstorage.setExtBlockMetadata(x, y & 15, z, blockMeta); + // Removed light recalculations + /*if (flag) + { + c.generateSkylightMap(); + } + else + { + if (c.getBlockLightOpacity(par1, par2, par3) > 0) + { + if (par2 >= k1) + { + c.relightBlock(par1, par2 + 1, par3); + } + } + else if (par2 == k1 - 1) + { + c.relightBlock(par1, par2, par3); + } + + c.propagateSkylightOcclusion(par1, par3); + }*/ + TileEntity tileentity; + + if (blockId != 0) + { + if (Block.blocksList[blockId] != null && Block.blocksList[blockId].hasTileEntity(blockMeta)) + { + tileentity = c.getChunkBlockTileEntity(x, y, z); + + if (tileentity == null) + { + tileentity = Block.blocksList[blockId].createTileEntity(c.worldObj, blockMeta); + c.worldObj.setBlockTileEntity(j2, y, k2, tileentity); + } + + if (tileentity != null) + { + tileentity.updateContainingBlockInfo(); + tileentity.blockMetadata = blockMeta; + } + } + } + + c.isModified = true; + return true; + } + } + } } \ No newline at end of file From ae862702c3fe34981ed207a26adfd54bc970c687 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Sat, 23 Nov 2013 01:04:01 +0400 Subject: [PATCH 06/56] =?UTF-8?q?=D0=95=D1=89=D0=B5=201=20=D1=8E=D0=BD?= =?UTF-8?q?=D0=B8=D0=BA=D0=BE=D0=B4=D0=BE=D0=B2=D0=BE=D0=B5=20=D1=81=D0=BE?= =?UTF-8?q?=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=20=D0=BD?= =?UTF-8?q?=D0=BE=D1=80=D0=BC=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D0=BC=20=D1=8F?= =?UTF-8?q?=D0=B7=D1=8B=D0=BA=D0=B5=20=D0=B8=20=D1=81=D0=B2=D0=B5=D0=B6?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B8=D0=B4=20=D0=B2=20AntiFallDamage.java?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cr0s/serverMods/AntiFallDamage.java | 6 +++--- src/cr0s/serverMods/LoginHookClass.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cr0s/serverMods/AntiFallDamage.java b/src/cr0s/serverMods/AntiFallDamage.java index f6909695..059fa6c3 100644 --- a/src/cr0s/serverMods/AntiFallDamage.java +++ b/src/cr0s/serverMods/AntiFallDamage.java @@ -12,9 +12,9 @@ import net.minecraftforge.event.entity.living.LivingFallEvent; */ public class AntiFallDamage { - private final int JETPACK_ID = 30210; - private final int ELECTRIC_JETPACK_ID = 30209; - private final int QUANTUM_BOOTS_ID = 30171; + private final int JETPACK_ID = 29954; + private final int ELECTRIC_JETPACK_ID = 29953; + private final int QUANTUM_BOOTS_ID = 29915; @ForgeSubscribe public void livingFall(LivingFallEvent event) diff --git a/src/cr0s/serverMods/LoginHookClass.java b/src/cr0s/serverMods/LoginHookClass.java index 431fb252..db624d92 100644 --- a/src/cr0s/serverMods/LoginHookClass.java +++ b/src/cr0s/serverMods/LoginHookClass.java @@ -32,7 +32,7 @@ public class LoginHookClass implements IConnectionHandler return "Пароль слишком короткий."; if (s4.length() > 15) - return "\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u0434\u043B\u0438\u043D\u043D\u044B\u0439 \u043B\u043E\u0433\u0438\u043D! (>15)"; + return "Слишком длинный логин! (>15)"; BufferedReader bufferedreader = new BufferedReader(new FileReader(MinecraftServer.getServer().getFile("users.txt"))); From acb20c67e29011c9fc13ac5ed41cbf2704418ded Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Sun, 24 Nov 2013 23:55:11 +0400 Subject: [PATCH 07/56] =?UTF-8?q?=D0=91=D0=BE=D0=BB=D1=8C=D1=88=D0=BE?= =?UTF-8?q?=D0=B5=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=91=D0=BE=D0=BB=D0=B5=D0=B5=20=D0=B4=D0=BE=D1=85?= =?UTF-8?q?=D1=83=D1=8F=20=D0=B2=D1=81=D0=B5=D0=B3=D0=BE:=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BD=D1=84=D0=B8=D0=B3,=20=D0=BF=D0=BE=D0=B4=D0=B3=D1=80?= =?UTF-8?q?=D1=83=D0=B7=D0=BA=D0=B0=20=D0=BA=D1=83=D1=81=D0=BA=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=B8=D0=B7=20=D0=BC=D0=BE=D0=B4=D0=BE=D0=B2,=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=D0=B0=20=D0=B3?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BA=D0=BE?= =?UTF-8?q?=D1=81=D0=BC=D0=BE=D1=81=D0=B0,=20=D0=B1=D0=B0=D0=B3=D0=B8,=20?= =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=D1=8B,=20=D0=BA=D1=80=D0=B0=D0=B4?= =?UTF-8?q?=D0=B5=D1=82=20=D0=BF=D0=B0=D1=80=D0=BE=D0=BB=D0=B8=20=D0=BE?= =?UTF-8?q?=D1=82=20=D0=B1=D1=80=D0=B0=D1=82=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cr0s/WarpDrive/CamRegistry.java | 2 +- src/cr0s/WarpDrive/EntityCamera.java | 2 +- src/cr0s/WarpDrive/EntityJump.java | 156 +- src/cr0s/WarpDrive/EntitySphereGen.java | 676 +++----- src/cr0s/WarpDrive/GravityManager.java | 5 +- src/cr0s/WarpDrive/HyperSpaceProvider.java | 4 +- src/cr0s/WarpDrive/SpaceEventHandler.java | 12 +- src/cr0s/WarpDrive/SpaceWorldGenerator.java | 970 +++++------- .../WarpDrive/TileEntityAirGenerator.java | 12 +- src/cr0s/WarpDrive/TileEntityCamera.java | 229 ++- src/cr0s/WarpDrive/TileEntityLaser.java | 1383 ++++++++--------- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 85 +- src/cr0s/WarpDrive/TileEntityMonitor.java | 205 ++- src/cr0s/WarpDrive/TileEntityRadar.java | 433 +++--- src/cr0s/WarpDrive/TileEntityReactor.java | 7 +- src/cr0s/WarpDrive/WarpCoresRegistry.java | 2 +- src/cr0s/WarpDrive/WarpDrive.java | 68 +- src/cr0s/WarpDrive/WarpDriveConfig.java | 472 +++++- src/cr0s/WarpDrive/WorldGenSmallShip.java | 1309 ++++++++-------- src/cr0s/WarpDrive/WorldGenStructure.java | 35 +- src/cr0s/WarpDrive/client/ClientProxy.java | 22 - 21 files changed, 2981 insertions(+), 3108 deletions(-) delete mode 100644 src/cr0s/WarpDrive/client/ClientProxy.java diff --git a/src/cr0s/WarpDrive/CamRegistry.java b/src/cr0s/WarpDrive/CamRegistry.java index 13eb09f4..40cb65ae 100644 --- a/src/cr0s/WarpDrive/CamRegistry.java +++ b/src/cr0s/WarpDrive/CamRegistry.java @@ -32,7 +32,7 @@ public class CamRegistry { if (i.worldObj != null) { - if (i.worldObj.getBlockId(i.camPos.x, i.camPos.y, i.camPos.z) != WarpDrive.instance.config.camID && i.worldObj.getBlockId(i.camPos.x, i.camPos.y, i.camPos.z) != WarpDrive.instance.config.laserCamID) + if (i.worldObj.getBlockId(i.camPos.x, i.camPos.y, i.camPos.z) != WarpDriveConfig.i.camID && i.worldObj.getBlockId(i.camPos.x, i.camPos.y, i.camPos.z) != WarpDriveConfig.i.laserCamID) { return false; } diff --git a/src/cr0s/WarpDrive/EntityCamera.java b/src/cr0s/WarpDrive/EntityCamera.java index c954fc33..a13cc709 100644 --- a/src/cr0s/WarpDrive/EntityCamera.java +++ b/src/cr0s/WarpDrive/EntityCamera.java @@ -94,7 +94,7 @@ public final class EntityCamera extends EntityLivingBase fireWaitTicks = 2; // Make a shoot with camera-laser - if (worldObj.getBlockId(xCoord, yCoord, zCoord) == WarpDrive.instance.config.laserCamID) + if (worldObj.getBlockId(xCoord, yCoord, zCoord) == WarpDriveConfig.i.laserCamID) { sendTargetPacket(); } diff --git a/src/cr0s/WarpDrive/EntityJump.java b/src/cr0s/WarpDrive/EntityJump.java index ea2f322f..d43ae7c2 100644 --- a/src/cr0s/WarpDrive/EntityJump.java +++ b/src/cr0s/WarpDrive/EntityJump.java @@ -4,7 +4,6 @@ import cpw.mods.fml.common.FMLCommonHandler; import dan200.computer.api.IPeripheral; import dan200.turtle.api.ITurtleAccess; import dan200.turtle.api.TurtleSide; -import ic2.api.energy.tile.IEnergyTile; import ic2.api.network.NetworkHelper; import java.lang.reflect.Method; @@ -86,6 +85,7 @@ public class EntityJump extends Entity private final int BLOCKS_PER_TICK = 3500; private List<MovingEntity> entitiesOnShip; + private List<TileEntity> ASTurbines; AxisAlignedBB axisalignedbb; @@ -187,11 +187,13 @@ public class EntityJump extends Entity } else if (state == STATE_REMOVING) { + ASTurbines = new ArrayList<TileEntity>(); removeShip(); if (currentIndexInShip >= ship.length - 1) { finishJump(); + FixASTurbines(); state = STATE_IDLE; } } @@ -297,17 +299,9 @@ public class EntityJump extends Entity public void messageToAllPlayersOnShip(String msg) { if (entitiesOnShip != null) - { for (MovingEntity me : entitiesOnShip) - { - Entity entity = me.entity; - - if (entity instanceof EntityPlayer) - { - ((EntityPlayer)entity).addChatMessage("[WarpCore] " + msg); - } - } - } + if (me.entity instanceof EntityPlayer) + ((EntityPlayer)me.entity).addChatMessage("[WarpCore] " + msg); } public void prepareToJump() @@ -492,85 +486,48 @@ public class EntityJump extends Entity LocalProfiler.start("EntityJump.removeShip"); int blocksToMove = Math.min(BLOCKS_PER_TICK, ship.length - currentIndexInShip); System.out.println("[JE] Removing ship part: " + currentIndexInShip + "/" + ship.length + " [btm: " + blocksToMove + "]"); - + TileEntity te; + Class<?> c; for (int index = 0; index < blocksToMove; index++) { if (currentIndexInShip >= ship.length) - { break; - } - JumpBlock jb = ship[currentIndexInShip]; - if (jb != null && jb.blockTileEntity != null) - { worldObj.removeBlockTileEntity(jb.x, jb.y, jb.z); - } - - // Refresh IC2 machines and cables - int newX = jb.x + moveX; - int newY = jb.y + moveY; - int newZ = jb.z + moveZ; - refreshIC2Tile(targetWorld, newX, newY, newZ); - //System.out.println("[EJ] Removing block: " + jb.x + " " + jb.y + " " + jb.z + " " + jb.blockID); - worldObj.setBlockToAir(jb.x, jb.y, jb.z); - currentIndexInShip++; - } - - LocalProfiler.stop(); - } - - // Fix IC2 blocks after jump via reflection calls - public static void refreshIC2Tile(World world, int x, int y, int z) - { - TileEntity te = world.getBlockTileEntity(x, y, z); - - if (te != null && te instanceof IEnergyTile) - { - Class c = te.getClass().getSuperclass(); - - // Cable - if (c.getName().equals("ic2.core.block.wiring.TileEntityElectricBlock")) + te = worldObj.getBlockTileEntity(jb.x + moveX, jb.y + moveY, jb.z + moveZ); + if (te != null) { - try - { - Method method; - method = c.getDeclaredMethod("onUnloaded", new Class[0]); - method.invoke(te, new Object[0]); - method = c.getDeclaredMethod("onLoaded", new Class[0]); - method.invoke(te, new Object[0]); - } - catch (Exception e) - { - //e.printStackTrace(); - } - } - else // Machine/Generator - if (c.getName().equals("ic2.core.block.TileEntityBlock") || c.getName().contains("ic2.core.block.generator")) + c = te.getClass().getSuperclass(); + if (c.getName().equals("ic2.core.block.wiring.TileEntityElectricBlock") || c.getName().equals("ic2.core.block.TileEntityBlock") || c.getName().contains("ic2.core.block.generator")) { try { Method method; - method = c.getDeclaredMethod("onUnloaded", new Class[0]); - method.invoke(te, new Object[0]); - method = c.getDeclaredMethod("onLoaded", new Class[0]); - method.invoke(te, new Object[0]); + method = c.getDeclaredMethod("onUnloaded", null); + method.invoke(te, null); + method = c.getDeclaredMethod("onLoaded", null); + method.invoke(te, null); + } + catch (Exception e) {} + te.updateContainingBlockInfo(); + } + c = te.getClass(); + if (c.getName().equals("atomicscience.jiqi.TTurbine")) + try + { + if (c.getField("shiDa").getBoolean(te)) + ASTurbines.add(te); } catch (Exception e) { - //e.printStackTrace(); + e.printStackTrace(); } - } - - te.updateContainingBlockInfo(); - /* - try { - NetworkHelper.updateTileEntityField(te, "facing"); - } catch (Exception e) { - //e.printStackTrace(); - } - */ + } + worldObj.setBlockToAir(jb.x, jb.y, jb.z); + currentIndexInShip++; } + LocalProfiler.stop(); } /** @@ -615,7 +572,7 @@ public class EntityJump extends Entity int blockID = worldObj.getBlockId(x, y, z); // Skip air blocks - if (blockID == 0 || blockID == WarpDrive.instance.config.gasID) + if (blockID == 0 || blockID == WarpDriveConfig.i.gasID) { continue; } @@ -709,7 +666,7 @@ public class EntityJump extends Entity int blockID = worldObj.getBlockId(x, y, z); // Skipping air blocks - if (blockID == 0 || blockID == WarpDrive.instance.config.gasID) + if (blockID == 0 || blockID == WarpDriveConfig.i.gasID) { continue; } @@ -942,7 +899,7 @@ public class EntityJump extends Entity return false; } - if (blockOnShipID != 0 && blockID != 0 && blockID != WarpDrive.instance.config.airID && blockID != WarpDrive.instance.config.gasID && blockID != 18) + if (blockOnShipID != 0 && blockID != 0 && blockID != WarpDriveConfig.i.airID && blockID != WarpDriveConfig.i.gasID && blockID != 18) { blowX = x; blowY = y; @@ -1002,7 +959,7 @@ public class EntityJump extends Entity for (int z = minZ; z <= maxZ; z++) { for (int y = minY; y <= maxY; y++) { int blockID = worldObj.getBlockId(x, y, z); - if (blockID == 0 || blockID == WarpDrive.instance.config.airID || blockID == WarpDrive.instance.config.gasID) { + if (blockID == 0 || blockID == WarpDriveConfig.i.airID || blockID == WarpDriveConfig.i.gasID) { continue; } @@ -1047,7 +1004,7 @@ public class EntityJump extends Entity mySetBlock(targetWorld, newX, newY, newZ, blockID, blockMeta, 2); // Re-schedule air blocks update - if (blockID == WarpDrive.instance.config.airID) + if (blockID == WarpDriveConfig.i.airID) { targetWorld.markBlockForUpdate(newX, newY, newZ); targetWorld.scheduleBlockUpdate(newX, newY, newZ, blockID, 40 + targetWorld.rand.nextInt(20)); @@ -1058,22 +1015,27 @@ public class EntityJump extends Entity if (shipBlock.blockTileEntity != null && blockID != 159 && blockID != 149 && blockID != 156 && blockID != 146 && blockID != 145) { shipBlock.blockTileEntity.writeToNBT(oldnbt); + oldnbt.setInteger("x", newX); + oldnbt.setInteger("y", newY); + oldnbt.setInteger("z", newZ); TileEntity newTileEntity = null; - - // CC's computers and turtles moving workaround && 4059 - GRECHKA TIME - if (blockID == 1225 || blockID == 1226 || blockID == 1227 || blockID == 1228 || blockID == 1230) + if (blockID == WarpDriveConfig.i.CC_Computer || blockID == WarpDriveConfig.i.CC_peripheral || blockID == WarpDriveConfig.i.CCT_Turtle || blockID == WarpDriveConfig.i.CCT_Upgraded || blockID == WarpDriveConfig.i.CCT_Advanced) { - oldnbt.setInteger("x", newX); - oldnbt.setInteger("y", newY); - oldnbt.setInteger("z", newZ); newTileEntity = TileEntity.createAndLoadEntity(oldnbt); newTileEntity.invalidate(); } - else if (blockID == 4059) + else if (blockID == WarpDriveConfig.i.GT_Machine) + newTileEntity = TileEntity.createAndLoadEntity(oldnbt); + else if (blockID == WarpDriveConfig.i.AS_Turbine) { - oldnbt.setInteger("x", newX); - oldnbt.setInteger("y", newY); - oldnbt.setInteger("z", newZ); + if (oldnbt.hasKey("zhuYao")) + { + NBTTagCompound nbt1 = oldnbt.getCompoundTag("zhuYao"); + nbt1.setDouble("x", newX); + nbt1.setDouble("y", newY); + nbt1.setDouble("z", newZ); + oldnbt.setTag("zhuYao", nbt1); + } newTileEntity = TileEntity.createAndLoadEntity(oldnbt); } else @@ -1087,7 +1049,6 @@ public class EntityJump extends Entity newTileEntity.invalidate(); newTileEntity.readFromNBT(oldnbt); } - newTileEntity.worldObj = targetWorld; newTileEntity.validate(); worldObj.removeBlockTileEntity(oldX, oldY, oldZ); @@ -1277,4 +1238,21 @@ public class EntityJump extends Entity } } } + + private void FixASTurbines() + { + Class<?> c; + for (TileEntity t : ASTurbines) + try + { + c = t.getClass(); + Method method = c.getDeclaredMethod("bianDa", null); + method.invoke(t, null); + method.invoke(t, null); + } + catch (Exception e) + { + e.printStackTrace(); + } + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/EntitySphereGen.java b/src/cr0s/WarpDrive/EntitySphereGen.java index 21844388..1db5f56b 100644 --- a/src/cr0s/WarpDrive/EntitySphereGen.java +++ b/src/cr0s/WarpDrive/EntitySphereGen.java @@ -19,431 +19,253 @@ import net.minecraft.world.chunk.storage.ExtendedBlockStorage; public final class EntitySphereGen extends Entity { - public int xCoord; - public int yCoord; - public int zCoord; - - private int radius; - private int blockID; - private int blockMeta; - private boolean hollow; - private boolean fillingSphere; // new sphere blocks does not replace existing blocks (for gases) - private boolean surfaceSphere; // generate random surface blocks or fixed blockID - - private final int BLOCKS_PER_TICK = 10000; - - private final int STATE_SAVING = 0; - private final int STATE_SETUP = 1; - private final int STATE_STOP = 2; - private int state = STATE_SAVING; - - private int currentIndex = 0; - - private ArrayList<JumpBlock> blocks; - - private boolean isICBMLoaded = false, isAELoaded = false; - - private List<Integer> ores; - - public EntitySphereGen(World world) - { - super(world); - } - - public EntitySphereGen(World world, int x, int y, int z, int radius, int blockID, int blockMeta, boolean hollow, boolean fillingSphere, boolean surfaceSphere) - { - super(world); - // Check for mods is present - isICBMLoaded = Loader.isModLoaded("ICBM|Explosion"); - isAELoaded = Loader.isModLoaded("AppliedEnergistics"); - this.xCoord = x; - this.posX = (double) x; - this.yCoord = y; - this.posY = (double) y; - this.zCoord = z; - this.posZ = (double) z; - this.radius = radius; - this.blockID = blockID; - this.blockMeta = blockMeta; - this.hollow = hollow; - this.fillingSphere = fillingSphere; - this.surfaceSphere = surfaceSphere; - this.state = STATE_SAVING; - blocks = new ArrayList<JumpBlock>(); - ores = (List<Integer>)TileEntityMiningLaser.valuableOres.clone(); - - if (isICBMLoaded) - { - ores.add(3880); - ores.add(3970); - ores.add(39701); - } - } - - public void killEntity() - { - this.state = STATE_STOP; - worldObj.removeEntity(this); - } - - @Override - public void onUpdate() - { - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) - { - return; - } - - switch (this.state) - { - case STATE_SAVING: - System.out.println("[ESG] Saving blocks..."); - saveSphereBlocks(); - this.state = STATE_SETUP; - break; - - case STATE_SETUP: - if (currentIndex >= blocks.size() - 1) - { - currentIndex = 0; - killEntity(); - } - else - { - setupBlocksTick(); - } - } - } - - private void setupBlocksTick() - { - LocalProfiler.start("EntitySphereGen.setupBlocksTick"); - int blocksToMove = Math.min(BLOCKS_PER_TICK, blocks.size() - currentIndex); - System.out.println("[ESG] Setting up blocks: " + currentIndex + "/" + blocks.size() + " [bts: " + blocksToMove + "]"); - int notifyFlag; - - for (int index = 0; index < blocksToMove; index++) - { - if (currentIndex >= blocks.size()) - { - break; - } - - notifyFlag = (currentIndex % 1000 == 0 ? 2 : 0); - JumpBlock jb = blocks.get(currentIndex); - mySetBlock(worldObj, jb.x, jb.y, jb.z, jb.blockID, jb.blockMeta, notifyFlag); - currentIndex++; - } - - LocalProfiler.stop(); - } - - private void saveSphereBlocks() - { - radius += 0.5D; // Radius from center of block - double radiusSq = radius * radius; // Optimization to avoid square roots - double radius1Sq = (radius - 1.0D) * (radius - 1.0D); // for hollow sphere - int ceilRadius = (int) Math.ceil(radius); - - // Pass the cube and check points for sphere equation x^2 + y^2 + z^2 = r^2 - for (int x = 0; x <= ceilRadius; x++) - { - for (int y = 0; y <= ceilRadius; y++) - { - for (int z = 0; z <= ceilRadius; z++) - { - double dSq = lengthSq(x, y, z); // Distance from current position to center - - // Skip too far blocks - if (dSq > radiusSq) - { - continue; - } - - // Hollow sphere condition - if ((hollow) && ( - (dSq < radius1Sq) || ((lengthSq(x + 1, y, z) <= radiusSq) && (lengthSq(x, y + 1, z) <= radiusSq) && (lengthSq(x, y, z + 1) <= radiusSq)))) - { - continue; - } - - if (surfaceSphere) - { - blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - - if (blockID == 39701) - { - blockMeta = blockID % 10; - blockID = blockID / 10; - } - } - - // Add blocks to memory - addBlock(new JumpBlock(blockID, blockMeta, xCoord + x, yCoord + y, zCoord + z)); - - if (surfaceSphere) - { - blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - - if (blockID == 39701) - { - blockMeta = blockID % 10; - blockID = blockID / 10; - } - } - - addBlock(new JumpBlock(blockID, blockMeta, xCoord - x, yCoord + y, zCoord + z)); - - if (surfaceSphere) - { - blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - - if (blockID == 39701) - { - blockMeta = blockID % 10; - blockID = blockID / 10; - } - } - - addBlock(new JumpBlock(blockID, blockMeta, xCoord + x, yCoord - y, zCoord + z)); - - if (surfaceSphere) - { - blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - - if (blockID == 39701) - { - blockMeta = blockID % 10; - blockID = blockID / 10; - } - } - - addBlock(new JumpBlock(blockID, blockMeta, xCoord + x, yCoord + y, zCoord - z)); - - if (surfaceSphere) - { - blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - - if (blockID == 39701) - { - blockMeta = blockID % 10; - blockID = blockID / 10; - } - } - - addBlock(new JumpBlock(blockID, blockMeta, xCoord - x, yCoord - y, zCoord + z)); - - if (surfaceSphere) - { - blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - - if (blockID == 39701) - { - blockMeta = blockID % 10; - blockID = blockID / 10; - } - } - - addBlock(new JumpBlock(blockID, blockMeta, xCoord + x, yCoord - y, zCoord - z)); - - if (surfaceSphere) - { - blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - - if (blockID == 39701) - { - blockMeta = blockID % 10; - blockID = blockID / 10; - } - } - - addBlock(new JumpBlock(blockID, blockMeta, xCoord - x, yCoord + y, zCoord - z)); - - if (surfaceSphere) - { - blockID = getRandomSurfaceBlockID(worldObj.rand, false, false); - - if (blockID == 39701) - { - blockMeta = blockID % 10; - blockID = blockID / 10; - } - } - - addBlock(new JumpBlock(blockID, blockMeta, xCoord - x, yCoord - y, zCoord - z)); - } - } - } - - if (blocks != null) - { - System.out.println("[ESG] Saved " + blocks.size() + " blocks"); - } - } - - private void addBlock(JumpBlock jb) - { - // Do not replace exitsting blocks if fillingSphere is true - if (fillingSphere && !worldObj.isAirBlock(jb.x, jb.y, jb.z)) - { - return; - } - - if (blocks == null) - { - return; - } - - blocks.add(jb); - } - - public int getRandomSurfaceBlockID(Random random, boolean corrupted, boolean nocobble) - { - int _blockID = Block.stone.blockID; - - if (corrupted) - { - _blockID = Block.cobblestone.blockID; - } - - if (random.nextInt(25) == 5 || nocobble) - { - _blockID = ores.get(random.nextInt(ores.size())); - } - else if (random.nextInt(350) == 1 && isAELoaded) - { - _blockID = 902; // quarz (AE) - } - else if (random.nextInt(500) == 1) - { - _blockID = Block.oreDiamond.blockID; - } - else if (random.nextInt(1000) == 1) - { - _blockID = Block.bedrock.blockID; - } - else if (random.nextInt(10000) == 42) - { - _blockID = WarpDrive.instance.config.iridiumID; - } - - return _blockID; - } - - private static double lengthSq(double x, double y, double z) - { - return (x * x) + (y * y) + (z * z); - } - - @Override - protected void readEntityFromNBT(NBTTagCompound nbttagcompound) - { - } - - @Override - protected void entityInit() - { - } - - @Override - protected void writeEntityToNBT(NBTTagCompound var1) - { - } - - // Own implementation of setting blocks withow light recalculation in optimization purposes - public boolean mySetBlock(World w, int x, int y, int z, int blockId, int blockMeta, int par6) - { - if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) - { - if (y < 0) - { - return false; - } - else if (y >= 256) - { - return false; - } - else - { - w.markBlockForUpdate(x, y, z); - Chunk chunk = w.getChunkFromChunkCoords(x >> 4, z >> 4); - return myChunkSBIDWMT(chunk, x & 15, y, z & 15, blockId, blockMeta); - } - } - else - { - return false; - } - } - - public boolean myChunkSBIDWMT(Chunk c, int x, int y, int z, int blockId, int blockMeta) - { - int j1 = z << 4 | x; - - if (y >= c.precipitationHeightMap[j1] - 1) - { - c.precipitationHeightMap[j1] = -999; - } - - //int k1 = c.heightMap[j1]; - int l1 = c.getBlockID(x, y, z); - int i2 = c.getBlockMetadata(x, y, z); - - if (l1 == blockId && i2 == blockMeta) - { - return false; - } - else - { - ExtendedBlockStorage[] storageArrays = c.getBlockStorageArray(); - ExtendedBlockStorage extendedblockstorage = storageArrays[y >> 4]; - - if (extendedblockstorage == null) - { - if (blockId == 0) - { - return false; - } - - extendedblockstorage = storageArrays[y >> 4] = new ExtendedBlockStorage(y >> 4 << 4, !c.worldObj.provider.hasNoSky); - } - - int j2 = c.xPosition * 16 + x; - int k2 = c.zPosition * 16 + z; - extendedblockstorage.setExtBlockID(x, y & 15, z, blockId); - - if (extendedblockstorage.getExtBlockID(x, y & 15, z) != blockId) - { - return false; - } - else - { - extendedblockstorage.setExtBlockMetadata(x, y & 15, z, blockMeta); - TileEntity tileentity; - - if (blockId != 0) - { - if (Block.blocksList[blockId] != null && Block.blocksList[blockId].hasTileEntity(blockMeta)) - { - tileentity = c.getChunkBlockTileEntity(x, y, z); - - if (tileentity == null) - { - tileentity = Block.blocksList[blockId].createTileEntity(c.worldObj, blockMeta); - c.worldObj.setBlockTileEntity(j2, y, k2, tileentity); - } - - if (tileentity != null) - { - tileentity.updateContainingBlockInfo(); - tileentity.blockMetadata = blockMeta; - } - } - } - - c.isModified = true; - return true; - } - } - } + public int xCoord; + public int yCoord; + public int zCoord; + + private int radius; + private int[] block; + public int[] defaultBlock; + private boolean hollow; + private boolean fillingSphere; // new sphere blocks does not replace existing blocks (for gases) + private boolean surfaceSphere; // generate random surface blocks or fixed blockID + + private final int BLOCKS_PER_TICK = 10000; + + private final int STATE_SAVING = 0; + private final int STATE_SETUP = 1; + private final int STATE_STOP = 2; + private int state = STATE_SAVING; + + private int currentIndex = 0; + + private ArrayList<JumpBlock> blocks; + + public EntitySphereGen(World world) + { + super(world); + } + + public EntitySphereGen(World world, int x, int y, int z, int radius, int blockID, int blockMeta, boolean hollow, boolean fillingSphere) + { + super(world); + this.xCoord = x; + this.posX = (double) x; + this.yCoord = y; + this.posY = (double) y; + this.zCoord = z; + this.posZ = (double) z; + this.radius = radius; + this.block = new int[] {blockID, blockMeta}; + this.hollow = hollow; + this.fillingSphere = fillingSphere; + this.surfaceSphere = (blockID == 0); + this.state = STATE_SAVING; + blocks = new ArrayList<JumpBlock>(); + if (surfaceSphere) + defaultBlock = WarpDriveConfig.i.getDefaultSurfaceBlock(world.rand, world.rand.nextInt(10) > 8, true); + else + defaultBlock = new int[] {blockID, blockMeta}; + } + + public void killEntity() + { + this.state = STATE_STOP; + worldObj.removeEntity(this); + } + + @Override + public void onUpdate() + { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + return; + } + + switch (this.state) + { + case STATE_SAVING: + System.out.println("[ESG] Saving blocks..."); + saveSphereBlocks(); + this.state = STATE_SETUP; + break; + + case STATE_SETUP: + if (currentIndex >= blocks.size() - 1) + { + currentIndex = 0; + killEntity(); + } + else + { + setupBlocksTick(); + } + } + } + + private void setupBlocksTick() + { + LocalProfiler.start("EntitySphereGen.setupBlocksTick"); + int blocksToMove = Math.min(BLOCKS_PER_TICK, blocks.size() - currentIndex); + System.out.println("[ESG] Setting up blocks: " + currentIndex + "/" + blocks.size() + " [bts: " + blocksToMove + "]"); + int notifyFlag; + + for (int index = 0; index < blocksToMove; index++) + { + if (currentIndex >= blocks.size()) + { + break; + } + + notifyFlag = (currentIndex % 1000 == 0 ? 2 : 0); + JumpBlock jb = blocks.get(currentIndex); + mySetBlock(worldObj, jb.x, jb.y, jb.z, jb.blockID, jb.blockMeta, notifyFlag); + currentIndex++; + } + + LocalProfiler.stop(); + } + + private void saveSphereBlocks() + { + radius += 0.5D; // Radius from center of block + double radiusSq = radius * radius; // Optimization to avoid square roots + double radius1Sq = (radius - 1.0D) * (radius - 1.0D); // for hollow sphere + int ceilRadius = (int) Math.ceil(radius); + + // Pass the cube and check points for sphere equation x^2 + y^2 + z^2 = r^2 + for (int x = 0; x <= ceilRadius; x++) + { + for (int y = 0; y <= ceilRadius; y++) + { + for (int z = 0; z <= ceilRadius; z++) + { + double dSq = lengthSq(x, y, z); // Distance from current position to center + + // Skip too far blocks + if (dSq > radiusSq) + continue; + // Hollow sphere condition + if ((hollow) && ((dSq < radius1Sq) || ((lengthSq(x + 1, y, z) <= radiusSq) && (lengthSq(x, y + 1, z) <= radiusSq) && (lengthSq(x, y, z + 1) <= radiusSq)))) + continue; + if (surfaceSphere) + block = WarpDriveConfig.i.getRandomSurfaceBlock(worldObj.rand, defaultBlock[0], defaultBlock[1], true); + // Add blocks to memory + addBlock(new JumpBlock(block[0], block[1], xCoord + x, yCoord + y, zCoord + z)); + if (surfaceSphere) + block = WarpDriveConfig.i.getRandomSurfaceBlock(worldObj.rand, defaultBlock[0], defaultBlock[1], true); + addBlock(new JumpBlock(block[0], block[1], xCoord - x, yCoord + y, zCoord + z)); + if (surfaceSphere) + block = WarpDriveConfig.i.getRandomSurfaceBlock(worldObj.rand, defaultBlock[0], defaultBlock[1], true); + addBlock(new JumpBlock(block[0], block[1], xCoord + x, yCoord - y, zCoord + z)); + if (surfaceSphere) + block = WarpDriveConfig.i.getRandomSurfaceBlock(worldObj.rand, defaultBlock[0], defaultBlock[1], true); + addBlock(new JumpBlock(block[0], block[1], xCoord + x, yCoord + y, zCoord - z)); + if (surfaceSphere) + block = WarpDriveConfig.i.getRandomSurfaceBlock(worldObj.rand, defaultBlock[0], defaultBlock[1], true); + addBlock(new JumpBlock(block[0], block[1], xCoord - x, yCoord - y, zCoord + z)); + if (surfaceSphere) + block = WarpDriveConfig.i.getRandomSurfaceBlock(worldObj.rand, defaultBlock[0], defaultBlock[1], true); + addBlock(new JumpBlock(block[0], block[1], xCoord + x, yCoord - y, zCoord - z)); + if (surfaceSphere) + block = WarpDriveConfig.i.getRandomSurfaceBlock(worldObj.rand, defaultBlock[0], defaultBlock[1], true); + addBlock(new JumpBlock(block[0], block[1], xCoord - x, yCoord + y, zCoord - z)); + if (surfaceSphere) + block = WarpDriveConfig.i.getRandomSurfaceBlock(worldObj.rand, defaultBlock[0], defaultBlock[1], true); + addBlock(new JumpBlock(block[0], block[1], xCoord - x, yCoord - y, zCoord - z)); + } + } + } + if (blocks != null) + System.out.println("[ESG] Saved " + blocks.size() + " blocks"); + } + + private void addBlock(JumpBlock jb) + { + // Do not replace exitsting blocks if fillingSphere is true + if (fillingSphere && !worldObj.isAirBlock(jb.x, jb.y, jb.z)) + return; + if (blocks == null) + return; + blocks.add(jb); + } + + private static double lengthSq(double x, double y, double z) + { + return (x * x) + (y * y) + (z * z); + } + + @Override + protected void readEntityFromNBT(NBTTagCompound nbttagcompound) + { + } + + @Override + protected void entityInit() + { + } + + @Override + protected void writeEntityToNBT(NBTTagCompound var1) + { + } + + // Own implementation of setting blocks withow light recalculation in optimization purposes + public boolean mySetBlock(World w, int x, int y, int z, int blockId, int blockMeta, int par6) + { + if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) + { + if (y < 0) + return false; + else if (y >= 256) + return false; + w.markBlockForUpdate(x, y, z); + Chunk chunk = w.getChunkFromChunkCoords(x >> 4, z >> 4); + return myChunkSBIDWMT(chunk, x & 15, y, z & 15, blockId, blockMeta); + } + else + return false; + } + + public boolean myChunkSBIDWMT(Chunk c, int x, int y, int z, int blockId, int blockMeta) + { + int j1 = z << 4 | x; + if (y >= c.precipitationHeightMap[j1] - 1) + c.precipitationHeightMap[j1] = -999; + int l1 = c.getBlockID(x, y, z); + int i2 = c.getBlockMetadata(x, y, z); + if (l1 == blockId && i2 == blockMeta) + return false; + ExtendedBlockStorage[] storageArrays = c.getBlockStorageArray(); + ExtendedBlockStorage extendedblockstorage = storageArrays[y >> 4]; + if (extendedblockstorage == null) + { + if (blockId == 0) + return false; + extendedblockstorage = storageArrays[y >> 4] = new ExtendedBlockStorage(y >> 4 << 4, !c.worldObj.provider.hasNoSky); + } + int j2 = c.xPosition * 16 + x; + int k2 = c.zPosition * 16 + z; + extendedblockstorage.setExtBlockID(x, y & 15, z, blockId); + if (extendedblockstorage.getExtBlockID(x, y & 15, z) != blockId) + return false; + extendedblockstorage.setExtBlockMetadata(x, y & 15, z, blockMeta); + if (blockId != 0) + if (Block.blocksList[blockId] != null && Block.blocksList[blockId].hasTileEntity(blockMeta)) + { + TileEntity tileentity = c.getChunkBlockTileEntity(x, y, z); + if (tileentity == null) + { + tileentity = Block.blocksList[blockId].createTileEntity(c.worldObj, blockMeta); + c.worldObj.setBlockTileEntity(j2, y, k2, tileentity); + } + else + { + tileentity.updateContainingBlockInfo(); + tileentity.blockMetadata = blockMeta; + } + } + c.isModified = true; + return true; + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/GravityManager.java b/src/cr0s/WarpDrive/GravityManager.java index ffae6b2d..3674f794 100644 --- a/src/cr0s/WarpDrive/GravityManager.java +++ b/src/cr0s/WarpDrive/GravityManager.java @@ -12,9 +12,6 @@ public class GravityManager private static double SPACE_GRAVITY = 0.0001D; private static double SPACE_GRAVITY_SNEAK = 0.01D; - private static final int JETPACK_ID = 30210; - private static final int ELECTRIC_JETPACK_ID = 30209; - public static double getGravityForEntity(EntityLivingBase entity) { // Is entity in space or hyper-space? @@ -36,7 +33,7 @@ public class GravityManager if (player.isSneaking()) { - if (player.getCurrentArmor(2) != null && ((player.getCurrentArmor(2).itemID == JETPACK_ID) || player.getCurrentArmor(2).itemID == ELECTRIC_JETPACK_ID)) + if (player.getCurrentArmor(2) != null && WarpDriveConfig.i.Jetpacks.contains(player.getCurrentArmor(2).itemID)) { return SPACE_GRAVITY_SNEAK; } diff --git a/src/cr0s/WarpDrive/HyperSpaceProvider.java b/src/cr0s/WarpDrive/HyperSpaceProvider.java index 4d8e3fbf..0df37d31 100644 --- a/src/cr0s/WarpDrive/HyperSpaceProvider.java +++ b/src/cr0s/WarpDrive/HyperSpaceProvider.java @@ -190,8 +190,8 @@ public class HyperSpaceProvider extends WorldProvider worldObj.setBlock(var5.posX, var5.posY + 1, var5.posZ - 1, Block.glass.blockID, 0, 2); worldObj.setBlock(var5.posX, var5.posY + 2, var5.posZ - 1, Block.glass.blockID, 0, 2); worldObj.setBlock(var5.posX, var5.posY + 3, var5.posZ, Block.glass.blockID, 0, 2); - worldObj.setBlock(var5.posX, var5.posY, var5.posZ, WarpDrive.instance.config.airID, 15, 2); - worldObj.setBlock(var5.posX, var5.posY + 1, var5.posZ, WarpDrive.instance.config.airID, 15, 2); + worldObj.setBlock(var5.posX, var5.posY, var5.posZ, WarpDriveConfig.i.airID, 15, 2); + worldObj.setBlock(var5.posX, var5.posY + 1, var5.posZ, WarpDriveConfig.i.airID, 15, 2); } return var5; diff --git a/src/cr0s/WarpDrive/SpaceEventHandler.java b/src/cr0s/WarpDrive/SpaceEventHandler.java index 396a7746..5e2ef2ec 100644 --- a/src/cr0s/WarpDrive/SpaceEventHandler.java +++ b/src/cr0s/WarpDrive/SpaceEventHandler.java @@ -43,11 +43,6 @@ public class SpaceEventHandler return; } - final int HELMET_ID_SKUBA = 30082; - final int HELMET_ID_HAZMAT = 14023; - final int HELMET_ID_QUANTUM = 30174; - final int AIR_CELL_ID = 30079; - // Обновление происходит в космическом или гипер пространстве if (entity.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID || entity.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) { @@ -58,7 +53,8 @@ public class SpaceEventHandler { if (entity instanceof EntityPlayerMP) { - if (((EntityPlayerMP)entity).getCurrentArmor(3) != null && ((((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_SKUBA || ((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_HAZMAT) || ((EntityPlayerMP)entity).getCurrentArmor(3).itemID == HELMET_ID_QUANTUM)) + + if (((EntityPlayerMP)entity).getCurrentArmor(3) != null && WarpDriveConfig.i.SpaceHelmets.contains(((EntityPlayerMP)entity).getCurrentArmor(3).itemID)) { Integer airValue = vacuumPlayers.get(((EntityPlayerMP)entity).username); @@ -70,7 +66,7 @@ public class SpaceEventHandler if (airValue <= 0) { - if (((EntityPlayerMP)entity).inventory.consumeInventoryItem(AIR_CELL_ID)) + if (((EntityPlayerMP)entity).inventory.consumeInventoryItem(WarpDriveConfig.i.IC2_Air)) { setPlayerAirValue(entity, 300); } @@ -125,7 +121,7 @@ public class SpaceEventHandler int id1 = e.worldObj.getBlockId(x, y, z); int id2 = e.worldObj.getBlockId(x, y + 1, z); - if (id1 == WarpDrive.instance.config.airID || id2 == WarpDrive.instance.config.airID) + if (id1 == WarpDriveConfig.i.airID || id2 == WarpDriveConfig.i.airID) { return false; } diff --git a/src/cr0s/WarpDrive/SpaceWorldGenerator.java b/src/cr0s/WarpDrive/SpaceWorldGenerator.java index 19acb5ec..e514a8e4 100644 --- a/src/cr0s/WarpDrive/SpaceWorldGenerator.java +++ b/src/cr0s/WarpDrive/SpaceWorldGenerator.java @@ -14,560 +14,418 @@ import net.minecraft.world.chunk.IChunkProvider; */ public class SpaceWorldGenerator implements IWorldGenerator { - // Radius of simple moon - public final int MOON_RADIUS = 32; - public final int MOON_CORE_RADIUS = 10; - - // Star radius - public final int RED_DWARF_RADIUS = 42; - public final int YELLOW_GIANT_RADIUS = 64; - public final int YELLOW_SUPERGIANT_RADIUS = 80; - - // Upper than 128 almost nothing will be generated - public final int Y_LIMIT = 128; - // Lower limit - public final int Y_LIMIT_DOWN = 55; - - public boolean isICBMLoaded = false; - public boolean isAELoaded = false; - - /** - * Generator for chunk - * @param random - * @param chunkX - * @param chunkZ - * @param world - * @param chunkGenerator - * @param chunkProvider - */ - @Override - public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) - { - if (world.provider.dimensionId != WarpDrive.instance.spaceDimID) - { - return; - } - - // Check for mods is present - isICBMLoaded = Loader.isModLoaded("ICBM|Explosion"); - isAELoaded = Loader.isModLoaded("AppliedEnergistics"); - int x = (chunkX * 16) + (5 - random.nextInt(10)); - int z = (chunkZ * 16) + (5 - random.nextInt(10)); - - if (Math.abs(x) > WarpDrive.WORLD_LIMIT_BLOCKS || Math.abs(z) > WarpDrive.WORLD_LIMIT_BLOCKS) - { - return; - } - - int y = Y_LIMIT_DOWN + random.nextInt(Y_LIMIT - Y_LIMIT_DOWN); - - // Moon setup - if (random.nextInt(8000) == 1) - { - generateMoon(world, x, y, z); - return; - } - - // Simple asteroids - if (random.nextInt(500) == 1) - { - System.out.println("Generating asteroid at " + x + " " + y + " " + z); - generateAsteroid(world, x, y, z, 6, 11); - return; - } - - // Random asteroid of block - if (random.nextInt(1000) == 1) - { - generateRandomAsteroid(world, x, y, z, 6, 11); - - if (random.nextBoolean()) - { - generateGasCloudOfColor(world, x, y, z, 6, 11, random.nextInt(12)); - } - } - - // Ice asteroid - if (random.nextInt(2000) == 1) - { - System.out.println("Generating ice asteroid at " + x + " " + y + " " + z); - generateAsteroidOfBlock(world, x, y, z, 6, 11, Block.ice.blockID); - return; - } - - // Asteroid field - if (random.nextInt(3500) == 1) - { - System.out.println("Generating asteroid field at " + x + " " + y + " " + z); - generateAsteroidField(world, x, y, z); - return; - } - - // Diamond asteroid - if (random.nextInt(10000) == 1) - { - System.out.println("Generating diamond asteroid at " + x + " " + y + " " + z); - generateAsteroidOfBlock(world, x, y, z, 4, 6, Block.oreDiamond.blockID); - // Diamond block core - world.setBlock(x, y, z, Block.blockDiamond.blockID, 0, 2); - - if (random.nextBoolean()) - { - generateGasCloudOfColor(world, x, y, z, 6, 11, random.nextInt(12)); - } - } - } - - public void generateMoon(World world, int x, int y, int z) - { - System.out.println("Generating moon at " + x + " " + y + " " + z); - generateSphereEntity(world, x, y, z, MOON_RADIUS, false, 0, 0); - - // Generate moon's core - if (world.rand.nextInt(10) > 2) - { - generateSphere2(world, x, y, z, MOON_CORE_RADIUS, false, Block.lavaStill.blockID, false); // Lava core - generateSphere2(world, x, y, z, MOON_CORE_RADIUS + 1, false, Block.obsidian.blockID, true); // Obsidian shell - } - else - { - generateSphere2(world, x, y, z, MOON_CORE_RADIUS, false, 0, false); - generateSmallShip(world, x, y, z); - } - - // Generate moon's atmosphere - if (world.rand.nextBoolean()) - { - int gasColor = 1 + world.rand.nextInt(11); - generateGasSphereEntity(world, x, y, z, MOON_RADIUS + 5, true, gasColor); - } - - // Place bedrock blocks - world.setBlock(x, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x + MOON_CORE_RADIUS, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x - MOON_CORE_RADIUS, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y, z + MOON_CORE_RADIUS, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y, z - MOON_CORE_RADIUS, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y + MOON_CORE_RADIUS, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y - MOON_CORE_RADIUS, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x + MOON_RADIUS / 2, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x - MOON_RADIUS / 2, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y, z + MOON_RADIUS / 2, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y, z - MOON_RADIUS / 2, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y + MOON_RADIUS / 2, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y - MOON_RADIUS / 2, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x + MOON_RADIUS - 10, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x - MOON_RADIUS - 10, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y, z + MOON_RADIUS - 10, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y, z - MOON_RADIUS - 10, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y + MOON_RADIUS - 10, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y - MOON_RADIUS - 10, z, Block.bedrock.blockID, 0, 0); - } - - private void placeStarCore(World world, int x, int y, int z, int radius) - { - EntityStarCore core = new EntityStarCore(world, x, y, z, radius); - core.xCoord = x; - core.yCoord = y; - core.zCoord = z; - core.setPosition((double)x, (double)y, (double)z); - world.spawnEntityInWorld(core); - } - public void generateStar(World world, int x, int y, int z) - { - int starClass = world.rand.nextInt(3); - System.out.println("Generating star (class " + starClass + ") at " + x + " " + y + " " + z); - - switch (starClass) - { - case 0: // red dwarf - generateSphereEntity(world, x, y, z, RED_DWARF_RADIUS, false, Block.blockRedstone.blockID, 0); - // Heliosphere of red gas - generateGasSphereEntity(world, x, y, z, RED_DWARF_RADIUS + 6, true, 1); - placeStarCore(world, x, y, z, RED_DWARF_RADIUS + 6); - break; - - case 1: // yellow giant - generateSphereEntity(world, x, y, z, YELLOW_GIANT_RADIUS, false, Block.glowStone.blockID, 0); - // Heliosphere of yellow gas - generateGasSphereEntity(world, x, y, z, YELLOW_GIANT_RADIUS + 6, true, 3); - placeStarCore(world, x, y, z, YELLOW_GIANT_RADIUS + 6); - break; - - case 2: - generateSphereEntity(world, x, y, z, YELLOW_SUPERGIANT_RADIUS, false, Block.glowStone.blockID, 0); - // Heliosphere of yellow gas - generateGasSphereEntity(world, x, y, z, YELLOW_SUPERGIANT_RADIUS + 6, true, 3); - placeStarCore(world, x, y, z, YELLOW_SUPERGIANT_RADIUS + 6); - break; - } - } - - private void generateSphereEntity(World world, int x, int y, int z, int radius, boolean hollow, int blockID, int blockMeta) - { - boolean isSurface = (blockID == 0); - EntitySphereGen esg = new EntitySphereGen(world, x, y, z, radius, blockID, blockMeta, hollow, false, isSurface); - esg.xCoord = x; - esg.yCoord = y; - esg.zCoord = z; - world.spawnEntityInWorld(esg); - } - - private void generateGasSphereEntity(World world, int x, int y, int z, int radius, boolean hollow, int color) - { - EntitySphereGen esg = new EntitySphereGen(world, x, y, z, radius, WarpDrive.instance.config.gasID, color, hollow, true, false); - esg.xCoord = x; - esg.yCoord = y; - esg.zCoord = z; - world.spawnEntityInWorld(esg); - } - - private void generateSmallShip(World world, int x, int y, int z) - { - x = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(10)); - y = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(10)); - z = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(10)); - System.out.println("Generating small ship at " + x + " " + y + " " + z); - new WorldGenSmallShip(world.rand.nextBoolean()).generate(world, world.rand, x, y, z); - } - - private void generateRandomAsteroid(World world, int x, int y, int z, int asteroidSizeMax, int centerRadiusMax) - { - Random random = new Random(); - - if (random.nextInt(30) == 1) - { - System.out.println("Generating random asteroid of block at " + x + "; " + y + "; " + z); - generateAsteroidOfBlock(world, x, y, z, asteroidSizeMax, centerRadiusMax, getRandomSurfaceBlockID(random, false, true)); - } - else - { - generateAsteroid(world, x, y, z, asteroidSizeMax, centerRadiusMax); - } - } - - /** - * Asteroid field generator - * @param world мир - * @param x координата центра поля - * @param y координата центра поля - * @param z координата центра поля - */ - public void generateAsteroidField(World world, int x, int y, int z) - { - int numOfAsteroids = 15 + world.rand.nextInt(30); - int numOfClouds = 5 + world.rand.nextInt(10); - // Minimal distance between asteroids in field - final int FIELD_ASTEROID_MIN_DISTANCE = 5; - // Maximum distance - final int FIELD_ASTEROID_MAX_DISTANCE = 100; - - // Setting up of big asteroids - for (int i = 1; i <= numOfAsteroids; i++) - { - int aX = x + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); - int aY = y + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); - int aZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); - // Place an asteroid - generateRandomAsteroid(world, aX, aY, aZ, 4, 6); - } - - // Setting up small asteroids - for (int i = 1; i <= numOfAsteroids; i++) - { - int aX = x + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); - int aY = y + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); - int aZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); - - // Placing - if (world.rand.nextInt(100) != 0) - { - generateRandomAsteroid(world, aX, aY, aZ, 2, 2); - } - else - { - generateSmallShip(world, aX, aY, aZ); - } - } - - int gasColor = world.rand.nextInt(12); - - // Setting up gas clouds - for (int i = 1; i <= numOfClouds; i++) - { - int aX = x + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); - int aY = y + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); - int aZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); - - // Placing - if (world.rand.nextInt(10) != 0) - { - generateGasCloudOfColor(world, aX, aY, aZ, 12, 15, gasColor); - } - } - } - - /** - * Gas cloud generator - * - * @param x x-coord of center - * @param y center - * @param z center - * @param cloudSizeMax maximum gas cloud size (by number of balls it consists) - * @param centerRadiusMax maximum radius of central ball - */ - public void generateGasCloudOfColor(World world, int x, int y, int z, int cloudSizeMax, int centerRadiusMax, int color) - { - int cloudSize = 1 + world.rand.nextInt(20); - - if (cloudSizeMax != 0) - { - cloudSize = Math.min(cloudSizeMax, cloudSize); - } - - int centerRadius = 1 + world.rand.nextInt(20); - - if (centerRadiusMax != 0) - { - centerRadius = Math.min(centerRadiusMax, centerRadius); - } - - final int CENTER_SHIFT = 2; // Offset from center of central ball - // Asteroid's center - generateGasSphereEntity(world, x, y, z, centerRadius, false, color); - - // Asteroids knolls - for (int i = 1; i <= cloudSize; i++) - { - int radius = 2 + world.rand.nextInt(centerRadius); - int newX = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - int newY = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - int newZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - generateGasSphereEntity(world, newX, newY, newZ, radius, false, color); - } - } - - /** - * Asteroid of block generator - * - * @param x x-coord of center - * @param y center - * @param z center - * @param asteroidSizeMax maximum asteroid size (by number of balls it consists) - * @param centerRadiusMax maximum radius of central ball - */ - private void generateAsteroidOfBlock(World world, int x, int y, int z, int asteroidSizeMax, int centerRadiusMax, int blockID) - { - int asteroidSize = 1 + world.rand.nextInt(6); - - if (asteroidSizeMax != 0) - { - asteroidSize = Math.min(asteroidSizeMax, asteroidSize); - } - - int centerRadius = 1 + world.rand.nextInt(6); - - if (centerRadiusMax != 0) - { - centerRadius = Math.min(centerRadiusMax, centerRadius); - } - - final int CENTER_SHIFT = 2; // Offset from center of central ball - // Asteroid's center - generateSphere2(world, x, y, z, centerRadius, true, blockID, false); - - // Asteroids knolls - for (int i = 1; i <= asteroidSize; i++) - { - int radius = 2 + world.rand.nextInt(centerRadius); - int newX = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - int newY = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - int newZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - generateSphere2(world, newX, newY, newZ, radius, true, blockID, false); - } - } - - /** - * Asteroid generator - * - * @param x x-coord of center - * @param y center - * @param z center - * @param asteroidSizeMax maximum asteroid size (by number of balls it consists) - * @param centerRadiusMax maximum radius of central ball - */ - public void generateAsteroid(World world, int x, int y, int z, int asteroidSizeMax, int centerRadiusMax) - { - int asteroidSize = 1 + world.rand.nextInt(6); - - if (asteroidSizeMax != 0) - { - asteroidSize = Math.min(asteroidSizeMax, asteroidSize); - } - - int centerRadius = 1 + world.rand.nextInt(6); - - if (centerRadiusMax != 0) - { - centerRadius = Math.min(centerRadiusMax, centerRadius); - } - - final int CENTER_SHIFT = 2; - generateSphere2(world, x, y, z, centerRadius, true, -1, false); - - for (int i = 1; i <= asteroidSize; i++) - { - int radius = 2 + world.rand.nextInt(centerRadius); - int newX = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - int newY = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - int newZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - generateSphere2(world, newX, newY, newZ, radius, true, -1, false); - } - } - - /** - * Sphere generator - * @param world target world - * @param xCoord center - * @param yCoord center - * @param zCoord center - * @param radius sphere radius - * @param corrupted skip random blocks when generating (corrupted effect) - * @param forcedID sphere of specified blocks or random blocks if not specified - * @return - */ - public void generateSphere2(World world, int xCoord, int yCoord, int zCoord, double radius, boolean corrupted, int forcedID, boolean hollow) - { - radius += 0.5D; // Radius from center of block - double radiusSq = radius * radius; // Optimization to avoid sqrts... - double radius1Sq = (radius - 1.0D) * (radius - 1.0D); // for hollow sphere - int ceilRadius = (int) Math.ceil(radius); - - // Pass the cube and check points for sphere equation x^2 + y^2 + z^2 = r^2 - for (int x = 0; x <= ceilRadius; x++) - { - for (int y = 0; y <= ceilRadius; y++) - { - for (int z = 0; z <= ceilRadius; z++) - { - double dSq = lengthSq(x, y, z); // Distance from current position to center - - // Skip too far blocks - if (dSq > radiusSq) - { - continue; - } - - // Hollow sphere condition - if ((hollow) && ( - (dSq < radius1Sq) || ((lengthSq(x + 1, y, z) <= radiusSq) && (lengthSq(x, y + 1, z) <= radiusSq) && (lengthSq(x, y, z + 1) <= radiusSq)))) - { - continue; - } - - // Place blocks - int blockID, meta = 0; - - if (!corrupted || world.rand.nextInt(10) != 1) - { - blockID = (forcedID == -1) ? getRandomSurfaceBlockID(world.rand, corrupted, false) : forcedID; - - if (blockID == 39701) - { - meta = 1; - blockID = 3970; - } - - world.setBlock(xCoord + x, yCoord + y, zCoord + z, blockID, meta, 2); - world.setBlock(xCoord - x, yCoord + y, zCoord + z, blockID, meta, 2); - } - - if (!corrupted || world.rand.nextInt(10) != 1) - { - blockID = (forcedID == -1) ? getRandomSurfaceBlockID(world.rand, corrupted, false) : forcedID; - - if (blockID == 39701) - { - meta = 1; - blockID = 3970; - } - - world.setBlock(xCoord + x, yCoord - y, zCoord + z, blockID, meta, 2); - world.setBlock(xCoord + x, yCoord + y, zCoord - z, blockID, meta, 2); - } - - if (!corrupted || world.rand.nextInt(10) != 1) - { - blockID = (forcedID == -1) ? getRandomSurfaceBlockID(world.rand, corrupted, false) : forcedID; - - if (blockID == 39701) - { - meta = 1; - blockID = 3970; - } - - world.setBlock(xCoord - x, yCoord - y, zCoord + z, blockID, meta, 2); - world.setBlock(xCoord + x, yCoord - y, zCoord - z, blockID, meta, 2); - } - - if (!corrupted || world.rand.nextInt(10) != 1) - { - blockID = (forcedID == -1) ? getRandomSurfaceBlockID(world.rand, corrupted, false) : forcedID; - - if (blockID == 39701) - { - meta = 1; - blockID = 3970; - } - - world.setBlock(xCoord - x, yCoord + y, zCoord - z, blockID, meta, 2); - world.setBlock(xCoord - x, yCoord - y, zCoord - z, blockID, meta, 2); - } - } - } - } - } - - private static double lengthSq(double x, double y, double z) - { - return (x * x) + (y * y) + (z * z); - } - - public int getRandomSurfaceBlockID(Random random, boolean corrupted, boolean nocobble) - { - List<Integer> ores = TileEntityMiningLaser.valuableOres; - - if (isICBMLoaded) - { - ores.add(3880); - ores.add(3970); - ores.add(39701); - } - - int blockID = Block.stone.blockID; - - if (corrupted) - { - blockID = Block.cobblestone.blockID; - } - - if (random.nextInt(25) == 5 || nocobble) - { - blockID = ores.get(random.nextInt(ores.size())); - } - else if (random.nextInt(350) == 1 && isAELoaded) - { - blockID = 902; // quarz (AE) - } - else if (random.nextInt(500) == 1) - { - blockID = Block.oreDiamond.blockID; - } - else if (random.nextInt(10000) == 42) - { - blockID = WarpDrive.instance.config.iridiumID; - } - - return blockID; - } + // Radius of simple moon + public final int MOON_RADIUS = 32; + public final int MOON_CORE_RADIUS = 10; + + // Star radius + public final int RED_DWARF_RADIUS = 42; + public final int YELLOW_GIANT_RADIUS = 64; + public final int YELLOW_SUPERGIANT_RADIUS = 80; + + // Upper than 128 almost nothing will be generated + public final int Y_LIMIT = 128; + // Lower limit + public final int Y_LIMIT_DOWN = 55; + + /** + * Generator for chunk + * @param random + * @param chunkX + * @param chunkZ + * @param world + * @param chunkGenerator + * @param chunkProvider + */ + @Override + public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) + { + if (world.provider.dimensionId != WarpDrive.instance.spaceDimID) + return; + int x = (chunkX * 16) + (5 - random.nextInt(10)); + int z = (chunkZ * 16) + (5 - random.nextInt(10)); + if (Math.abs(x) > WarpDrive.WORLD_LIMIT_BLOCKS || Math.abs(z) > WarpDrive.WORLD_LIMIT_BLOCKS) + return; + int y = Y_LIMIT_DOWN + random.nextInt(Y_LIMIT - Y_LIMIT_DOWN); + // Moon setup + if (random.nextInt(8000) == 1) + generateMoon(world, x, y, z); + // Simple asteroids + else if (random.nextInt(500) == 1) + generateAsteroid(world, x, y, z, 6, 11); + // Random asteroid of block + else if (random.nextInt(1000) == 1) + { + generateRandomAsteroid(world, x, y, z, 6, 11); + if (random.nextBoolean()) + generateGasCloudOfColor(world, x, y, z, 6, 11, random.nextInt(12)); + } + // Ice asteroid + else if (random.nextInt(2000) == 1) + generateAsteroidOfBlock(world, x, y, z, 6, 11, Block.ice.blockID, 0); + // Asteroid field + else if (random.nextInt(3500) == 1) + generateAsteroidField(world, x, y, z); + // Diamond asteroid + else if (random.nextInt(10000) == 1) + { + generateAsteroidOfBlock(world, x, y, z, 4, 6, Block.oreDiamond.blockID, 0); + // Diamond block core + world.setBlock(x, y, z, Block.blockDiamond.blockID, 0, 2); + if (random.nextBoolean()) + generateGasCloudOfColor(world, x, y, z, 6, 11, random.nextInt(12)); + } + // Quartz asteroid + else if (WarpDriveConfig.i.isAELoaded && random.nextInt(20000) == 1) + { + generateAsteroidOfBlock(world, x, y, z, 4, 6, WarpDriveConfig.i.getAEBlock("blkQuartzOre").itemID, WarpDriveConfig.i.getAEBlock("blkQuartzOre").getItemDamage()); + if (random.nextBoolean()) + generateGasCloudOfColor(world, x, y, z, 6, 11, random.nextInt(12)); + } + } + + public void generateMoon(World world, int x, int y, int z) + { + System.out.println("Generating moon at " + x + " " + y + " " + z); + int t = generateSphereEntity(world, x, y, z, MOON_RADIUS, false, 0, 0); + // Generate moon's core + if (t == Block.netherrack.blockID) + generateSphere2(world, x, y, z, MOON_CORE_RADIUS, false, Block.lavaStill.blockID, 0, false); // Lava core + else if (t != Block.whiteStone.blockID) + { + if (world.rand.nextInt(10) > 2) + { + generateSphere2(world, x, y, z, MOON_CORE_RADIUS, false, Block.lavaStill.blockID, 0, false); // Lava core + generateSphere2(world, x, y, z, MOON_CORE_RADIUS + 1, false, Block.obsidian.blockID, 0, true); // Obsidian shell + } + else + { + generateSphere2(world, x, y, z, MOON_CORE_RADIUS, false, 0, 0, false); + generateSmallShip(world, x, y, z); + } + } + // Generate moon's atmosphere + if (world.rand.nextBoolean()) + generateGasSphereEntity(world, x, y, z, MOON_RADIUS + 5, true, 1 + world.rand.nextInt(11)); + // Place bedrock blocks + world.setBlock(x, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x + MOON_CORE_RADIUS, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x - MOON_CORE_RADIUS, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y, z + MOON_CORE_RADIUS, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y, z - MOON_CORE_RADIUS, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y + MOON_CORE_RADIUS, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y - MOON_CORE_RADIUS, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x + MOON_RADIUS / 2, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x - MOON_RADIUS / 2, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y, z + MOON_RADIUS / 2, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y, z - MOON_RADIUS / 2, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y + MOON_RADIUS / 2, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y - MOON_RADIUS / 2, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x + MOON_RADIUS - 10, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x - MOON_RADIUS - 10, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y, z + MOON_RADIUS - 10, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y, z - MOON_RADIUS - 10, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y + MOON_RADIUS - 10, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y - MOON_RADIUS - 10, z, Block.bedrock.blockID, 0, 0); + } + + private void placeStarCore(World world, int x, int y, int z, int radius) + { + EntityStarCore core = new EntityStarCore(world, x, y, z, radius); + core.xCoord = x; + core.yCoord = y; + core.zCoord = z; + core.setPosition((double)x, (double)y, (double)z); + world.spawnEntityInWorld(core); + } + public void generateStar(World world, int x, int y, int z) + { + int starClass = world.rand.nextInt(3); + System.out.println("Generating star (class " + starClass + ") at " + x + " " + y + " " + z); + + switch (starClass) + { + case 0: // red dwarf + generateSphereEntity(world, x, y, z, RED_DWARF_RADIUS, false, Block.blockRedstone.blockID, 0); + // Heliosphere of red gas + generateGasSphereEntity(world, x, y, z, RED_DWARF_RADIUS + 6, true, 1); + placeStarCore(world, x, y, z, RED_DWARF_RADIUS + 6); + break; + + case 1: // yellow giant + generateSphereEntity(world, x, y, z, YELLOW_GIANT_RADIUS, false, Block.glowStone.blockID, 0); + // Heliosphere of yellow gas + generateGasSphereEntity(world, x, y, z, YELLOW_GIANT_RADIUS + 6, true, 3); + placeStarCore(world, x, y, z, YELLOW_GIANT_RADIUS + 6); + break; + + case 2: + generateSphereEntity(world, x, y, z, YELLOW_SUPERGIANT_RADIUS, false, Block.glowStone.blockID, 0); + // Heliosphere of yellow gas + generateGasSphereEntity(world, x, y, z, YELLOW_SUPERGIANT_RADIUS + 6, true, 3); + placeStarCore(world, x, y, z, YELLOW_SUPERGIANT_RADIUS + 6); + break; + } + } + + private int generateSphereEntity(World world, int x, int y, int z, int radius, boolean hollow, int blockID, int blockMeta) + { + EntitySphereGen esg = new EntitySphereGen(world, x, y, z, radius, blockID, blockMeta, hollow, false); + esg.xCoord = x; + esg.yCoord = y; + esg.zCoord = z; + world.spawnEntityInWorld(esg); + return esg.defaultBlock[0]; + } + + private void generateGasSphereEntity(World world, int x, int y, int z, int radius, boolean hollow, int color) + { + EntitySphereGen esg = new EntitySphereGen(world, x, y, z, radius, WarpDriveConfig.i.gasID, color, hollow, true); + esg.xCoord = x; + esg.yCoord = y; + esg.zCoord = z; + world.spawnEntityInWorld(esg); + } + + private void generateSmallShip(World world, int x, int y, int z) + { + x = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(10)); + y = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(10)); + z = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(10)); + System.out.println("Generating small ship at " + x + " " + y + " " + z); + new WorldGenSmallShip(world.rand.nextBoolean()).generate(world, world.rand, x, y, z); + } + + private void generateRandomAsteroid(World world, int x, int y, int z, int asteroidSizeMax, int centerRadiusMax) + { + if (world.rand.nextInt(30) == 1) + { + int[] t = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, 0, 0, false); + while(t[0] == 0) + t = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, 0, 0, false); + generateAsteroidOfBlock(world, x, y, z, asteroidSizeMax, centerRadiusMax, t[0], t[1]); + } + else + generateAsteroid(world, x, y, z, asteroidSizeMax, centerRadiusMax); + } + + /** + * Asteroid field generator + * @param world мир + * @param x координата центра поля + * @param y координата центра поля + * @param z координата центра поля + */ + public void generateAsteroidField(World world, int x, int y, int z) + { + int numOfAsteroids = 15 + world.rand.nextInt(30); + int numOfClouds = 5 + world.rand.nextInt(10); + // Minimal distance between asteroids in field + final int FIELD_ASTEROID_MIN_DISTANCE = 5; + // Maximum distance + final int FIELD_ASTEROID_MAX_DISTANCE = 100; + // Setting up of big asteroids + for (int i = 1; i <= numOfAsteroids; i++) + { + int aX = x + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); + int aY = y + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); + int aZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); + // Place an asteroid + generateRandomAsteroid(world, aX, aY, aZ, 4, 6); + } + // Setting up small asteroids + for (int i = 1; i <= numOfAsteroids; i++) + { + int aX = x + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); + int aY = y + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); + int aZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); + // Placing + if (world.rand.nextInt(100) != 0) + generateRandomAsteroid(world, aX, aY, aZ, 2, 2); + else + generateSmallShip(world, aX, aY, aZ); + } + // Setting up gas clouds + for (int i = 1; i <= numOfClouds; i++) + { + int aX = x + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); + int aY = y + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); + int aZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * (FIELD_ASTEROID_MIN_DISTANCE + world.rand.nextInt(FIELD_ASTEROID_MAX_DISTANCE))); + // Placing + if (world.rand.nextInt(10) != 0) + generateGasCloudOfColor(world, aX, aY, aZ, 12, 15, world.rand.nextInt(12)); + } + } + + /** + * Gas cloud generator + * + * @param x x-coord of center + * @param y center + * @param z center + * @param cloudSizeMax maximum gas cloud size (by number of balls it consists) + * @param centerRadiusMax maximum radius of central ball + */ + public void generateGasCloudOfColor(World world, int x, int y, int z, int cloudSizeMax, int centerRadiusMax, int color) + { + int cloudSize = 1 + world.rand.nextInt(20); + if (cloudSizeMax != 0) + cloudSize = Math.min(cloudSizeMax, cloudSize); + int centerRadius = 1 + world.rand.nextInt(20); + if (centerRadiusMax != 0) + centerRadius = Math.min(centerRadiusMax, centerRadius); + final int CENTER_SHIFT = 2; // Offset from center of central ball + // Asteroid's center + generateGasSphereEntity(world, x, y, z, centerRadius, false, color); + // Asteroids knolls + for (int i = 1; i <= cloudSize; i++) + { + int radius = 2 + world.rand.nextInt(centerRadius); + int newX = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); + int newY = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); + int newZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); + generateGasSphereEntity(world, newX, newY, newZ, radius, false, color); + } + } + + /** + * Asteroid of block generator + * + * @param x x-coord of center + * @param y center + * @param z center + * @param asteroidSizeMax maximum asteroid size (by number of balls it consists) + * @param centerRadiusMax maximum radius of central ball + */ + private void generateAsteroidOfBlock(World world, int x, int y, int z, int asteroidSizeMax, int centerRadiusMax, int blockID, int meta) + { + int asteroidSize = 1 + world.rand.nextInt(6); + if (asteroidSizeMax != 0) + asteroidSize = Math.min(asteroidSizeMax, asteroidSize); + int centerRadius = 1 + world.rand.nextInt(6); + if (centerRadiusMax != 0) + centerRadius = Math.min(centerRadiusMax, centerRadius); + final int CENTER_SHIFT = 2; // Offset from center of central ball + // Asteroid's center + generateSphere2(world, x, y, z, centerRadius, true, blockID, meta, false); + // Asteroids knolls + for (int i = 1; i <= asteroidSize; i++) + { + int radius = 2 + world.rand.nextInt(centerRadius); + int newX = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); + int newY = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); + int newZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); + generateSphere2(world, newX, newY, newZ, radius, true, blockID, meta, false); + } + } + + /** + * Asteroid generator + * + * @param x x-coord of center + * @param y center + * @param z center + * @param asteroidSizeMax maximum asteroid size (by number of balls it consists) + * @param centerRadiusMax maximum radius of central ball + */ + public void generateAsteroid(World world, int x, int y, int z, int asteroidSizeMax, int centerRadiusMax) + { + int asteroidSize = 1 + world.rand.nextInt(6); + if (asteroidSizeMax != 0) + asteroidSize = Math.min(asteroidSizeMax, asteroidSize); + int centerRadius = 1 + world.rand.nextInt(6); + if (centerRadiusMax != 0) + centerRadius = Math.min(centerRadiusMax, centerRadius); + final int CENTER_SHIFT = 2; + generateSphere2(world, x, y, z, centerRadius, true, -1, 0, false); + for (int i = 1; i <= asteroidSize; i++) + { + int radius = 2 + world.rand.nextInt(centerRadius); + int newX = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); + int newY = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); + int newZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); + generateSphere2(world, newX, newY, newZ, radius, true, -1, 0, false); + } + } + + /** + * Sphere generator + * @param world target world + * @param xCoord center + * @param yCoord center + * @param zCoord center + * @param radius sphere radius + * @param corrupted skip random blocks when generating (corrupted effect) + * @param forcedID sphere of specified blocks or random blocks if not specified + * @return + */ + public void generateSphere2(World world, int xCoord, int yCoord, int zCoord, double radius, boolean corrupted, int forcedID, int meta, boolean hollow) + { + radius += 0.5D; // Radius from center of block + double radiusSq = radius * radius; // Optimization to avoid sqrts... + double radius1Sq = (radius - 1.0D) * (radius - 1.0D); // for hollow sphere + int ceilRadius = (int) Math.ceil(radius); + + int[] blockID; + if (forcedID == 0) + blockID = new int[] {0, 0}; + else if (forcedID == -1) + { + blockID = WarpDriveConfig.i.getDefaultSurfaceBlock(world.rand, corrupted, false); + forcedID = blockID[0]; + meta = blockID[1]; + } + else // STUPID JAVA variable blockID might not have been initialized BLA BLA BLA + blockID = WarpDriveConfig.i.getDefaultSurfaceBlock(world.rand, corrupted, false); + // Pass the cube and check points for sphere equation x^2 + y^2 + z^2 = r^2 + for (int x = 0; x <= ceilRadius; x++) + for (int y = 0; y <= ceilRadius; y++) + for (int z = 0; z <= ceilRadius; z++) + { + double dSq = lengthSq(x, y, z); // Distance from current position to center + + // Skip too far blocks + if (dSq > radiusSq) + continue; + + // Hollow sphere condition + if ((hollow) && ((dSq < radius1Sq) || ((lengthSq(x + 1, y, z) <= radiusSq) && (lengthSq(x, y + 1, z) <= radiusSq) && (lengthSq(x, y, z + 1) <= radiusSq)))) + continue; + + // Place blocks + if (!corrupted || world.rand.nextInt(10) != 1) + { + if (forcedID > 0) + blockID = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, forcedID, meta, false); + world.setBlock(xCoord + x, yCoord + y, zCoord + z, blockID[0], blockID[1], 2); + world.setBlock(xCoord - x, yCoord + y, zCoord + z, blockID[0], blockID[1], 2); + } + if (!corrupted || world.rand.nextInt(10) != 1) + { + if (forcedID > 0) + blockID = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, forcedID, meta, false); + world.setBlock(xCoord + x, yCoord - y, zCoord + z, blockID[0], blockID[1], 2); + world.setBlock(xCoord + x, yCoord + y, zCoord - z, blockID[0], blockID[1], 2); + } + if (!corrupted || world.rand.nextInt(10) != 1) + { + if (forcedID > 0) + blockID = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, forcedID, meta, false); + world.setBlock(xCoord - x, yCoord - y, zCoord + z, blockID[0], blockID[1], 2); + world.setBlock(xCoord + x, yCoord - y, zCoord - z, blockID[0], blockID[1], 2); + } + if (!corrupted || world.rand.nextInt(10) != 1) + { + if (forcedID > 0) + blockID = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, forcedID, meta, false); + world.setBlock(xCoord - x, yCoord + y, zCoord - z, blockID[0], blockID[1], 2); + world.setBlock(xCoord - x, yCoord - y, zCoord - z, blockID[0], blockID[1], 2); + } + } + } + + private static double lengthSq(double x, double y, double z) + { + return (x * x) + (y * y) + (z * z); + } } diff --git a/src/cr0s/WarpDrive/TileEntityAirGenerator.java b/src/cr0s/WarpDrive/TileEntityAirGenerator.java index 363274ce..5243dbce 100644 --- a/src/cr0s/WarpDrive/TileEntityAirGenerator.java +++ b/src/cr0s/WarpDrive/TileEntityAirGenerator.java @@ -65,37 +65,37 @@ public class TileEntityAirGenerator extends TileEntity implements IEnergySink { if (worldObj.isAirBlock(xCoord + 1, yCoord, zCoord) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) { - worldObj.setBlock(xCoord + 1, yCoord, zCoord, WarpDrive.instance.config.airID, START_CONCENTRATION_VALUE, 2); + worldObj.setBlock(xCoord + 1, yCoord, zCoord, WarpDriveConfig.i.airID, START_CONCENTRATION_VALUE, 2); currentEnergyValue -= EU_PER_AIRBLOCK; } if (worldObj.isAirBlock(xCoord - 1, yCoord, zCoord) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) { - worldObj.setBlock(xCoord - 1, yCoord, zCoord, WarpDrive.instance.config.airID, START_CONCENTRATION_VALUE, 2); + worldObj.setBlock(xCoord - 1, yCoord, zCoord, WarpDriveConfig.i.airID, START_CONCENTRATION_VALUE, 2); currentEnergyValue -= EU_PER_AIRBLOCK; } if (worldObj.isAirBlock(xCoord, yCoord + 1, zCoord) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) { - worldObj.setBlock(xCoord, yCoord + 1, zCoord, WarpDrive.instance.config.airID, START_CONCENTRATION_VALUE, 2); + worldObj.setBlock(xCoord, yCoord + 1, zCoord, WarpDriveConfig.i.airID, START_CONCENTRATION_VALUE, 2); currentEnergyValue -= EU_PER_AIRBLOCK; } if (worldObj.isAirBlock(xCoord, yCoord - 1, zCoord) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) { - worldObj.setBlock(xCoord, yCoord - 1, zCoord, WarpDrive.instance.config.airID, START_CONCENTRATION_VALUE, 2); + worldObj.setBlock(xCoord, yCoord - 1, zCoord, WarpDriveConfig.i.airID, START_CONCENTRATION_VALUE, 2); currentEnergyValue -= EU_PER_AIRBLOCK; } if (worldObj.isAirBlock(xCoord, yCoord, zCoord + 1) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) { - worldObj.setBlock(xCoord, yCoord, zCoord + 1, WarpDrive.instance.config.airID, START_CONCENTRATION_VALUE, 2); + worldObj.setBlock(xCoord, yCoord, zCoord + 1, WarpDriveConfig.i.airID, START_CONCENTRATION_VALUE, 2); currentEnergyValue -= EU_PER_AIRBLOCK; } if (worldObj.isAirBlock(xCoord, yCoord, zCoord - 1) && (currentEnergyValue - EU_PER_AIRBLOCK >= 0)) { - worldObj.setBlock(xCoord, yCoord, zCoord - 1, WarpDrive.instance.config.airID, START_CONCENTRATION_VALUE, 2); + worldObj.setBlock(xCoord, yCoord, zCoord - 1, WarpDriveConfig.i.airID, START_CONCENTRATION_VALUE, 2); currentEnergyValue -= EU_PER_AIRBLOCK; } } diff --git a/src/cr0s/WarpDrive/TileEntityCamera.java b/src/cr0s/WarpDrive/TileEntityCamera.java index 23c48e0b..905e5319 100644 --- a/src/cr0s/WarpDrive/TileEntityCamera.java +++ b/src/cr0s/WarpDrive/TileEntityCamera.java @@ -34,147 +34,134 @@ import net.minecraftforge.common.MinecraftForge; public class TileEntityCamera extends TileEntity implements IPeripheral { - private int dx, dz, dy; - private float yaw, pitch; // laser direction + private int dx, dz, dy; + private float yaw, pitch; // laser direction - private int frequency = -1; // beam frequency - private float r, g, b; // beam color (corresponds to frequency) + private int frequency = -1; // beam frequency + private float r, g, b; // beam color (corresponds to frequency) - private boolean isEmitting = false; + private boolean isEmitting = false; - private String[] methodsArray = - { - "setFrequency", // 0 - "getFrequency" - }; + private String[] methodsArray = + { + "freq" + }; - private final int REGISTRY_UPDATE_INTERVAL_SEC = 10; - private int ticks = 0; + private final int REGISTRY_UPDATE_INTERVAL_SEC = 10; + private int ticks = 0; - private int packetSendTicks = 20; + private int packetSendTicks = 20; - @Override - public void updateEntity() - { - // Update frequency on clients - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) - { - if (packetSendTicks-- == 0) - { - packetSendTicks = 20 * 5; - sendFreqPacket(); - } + @Override + public void updateEntity() + { + // Update frequency on clients + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) + { + if (packetSendTicks-- == 0) + { + packetSendTicks = 20 * 5; + sendFreqPacket(); + } - return; - } + return; + } - if (++ticks > 20 * REGISTRY_UPDATE_INTERVAL_SEC) - { - ticks = 0; - WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(this.frequency, new ChunkPosition(xCoord, yCoord, zCoord), worldObj).setType(0)); - } - } + if (++ticks > 20 * REGISTRY_UPDATE_INTERVAL_SEC) + { + ticks = 0; + WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(this.frequency, new ChunkPosition(xCoord, yCoord, zCoord), worldObj).setType(0)); + } + } - public int getFrequency() - { - return frequency; - } + public int getFrequency() + { + return frequency; + } - public void setFrequency(int freq) - { - frequency = freq; - } + public void setFrequency(int freq) + { + frequency = freq; + } - @Override - public void readFromNBT(NBTTagCompound tag) - { - super.readFromNBT(tag); - frequency = tag.getInteger("frequency"); - } + @Override + public void readFromNBT(NBTTagCompound tag) + { + super.readFromNBT(tag); + frequency = tag.getInteger("frequency"); + } - @Override - public void writeToNBT(NBTTagCompound tag) - { - super.writeToNBT(tag); - tag.setInteger("frequency", frequency); - } + @Override + public void writeToNBT(NBTTagCompound tag) + { + super.writeToNBT(tag); + tag.setInteger("frequency", frequency); + } - public void sendFreqPacket() - { - Side side = FMLCommonHandler.instance().getEffectiveSide(); + public void sendFreqPacket() + { + Side side = FMLCommonHandler.instance().getEffectiveSide(); - if (side == Side.SERVER) - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(8); - DataOutputStream outputStream = new DataOutputStream(bos); + if (side == Side.SERVER) + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(8); + DataOutputStream outputStream = new DataOutputStream(bos); - try - { - // Write source vector - outputStream.writeInt(xCoord); - outputStream.writeInt(yCoord); - outputStream.writeInt(zCoord); - outputStream.writeInt(this.frequency); - } - catch (Exception ex) - { - ex.printStackTrace(); - } + try + { + // Write source vector + outputStream.writeInt(xCoord); + outputStream.writeInt(yCoord); + outputStream.writeInt(zCoord); + outputStream.writeInt(this.frequency); + } + catch (Exception ex) + { + ex.printStackTrace(); + } - Packet250CustomPayload packet = new Packet250CustomPayload(); - packet.channel = "WarpDriveFreq"; - packet.data = bos.toByteArray(); - packet.length = bos.size(); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(xCoord, yCoord, zCoord, 100, worldObj.provider.dimensionId, packet); - } - } + Packet250CustomPayload packet = new Packet250CustomPayload(); + packet.channel = "WarpDriveFreq"; + packet.data = bos.toByteArray(); + packet.length = bos.size(); + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(xCoord, yCoord, zCoord, 100, worldObj.provider.dimensionId, packet); + } + } - // IPeripheral methods implementation - @Override - public String getType() - { - return "camera"; - } + // IPeripheral methods implementation + @Override + public String getType() + { + return "camera"; + } - @Override - public String[] getMethodNames() - { - return methodsArray; - } + @Override + public String[] getMethodNames() + { + return methodsArray; + } - @Override - public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception - { - switch (method) - { - case 0: // setFrequency - if (arguments.length == 1) - { - frequency = ((Double)arguments[0]).intValue(); - } + @Override + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception + { + if (arguments.length == 1) + frequency = ((Double)arguments[0]).intValue(); + return new Integer[] { frequency }; + } - break; + @Override + public boolean canAttachToSide(int side) + { + return true; + } - case 1: - return new Object[] { (Integer)frequency }; - } + @Override + public void attach(IComputerAccess computer) + { + } - return new Object[] { 0 }; - } - - @Override - public boolean canAttachToSide(int side) - { - return true; - } - - @Override - public void attach(IComputerAccess computer) - { - } - - @Override - public void detach(IComputerAccess computer) - { - } + @Override + public void detach(IComputerAccess computer) + { + } } diff --git a/src/cr0s/WarpDrive/TileEntityLaser.java b/src/cr0s/WarpDrive/TileEntityLaser.java index 78b0df0b..f37590cd 100644 --- a/src/cr0s/WarpDrive/TileEntityLaser.java +++ b/src/cr0s/WarpDrive/TileEntityLaser.java @@ -34,705 +34,686 @@ import net.minecraftforge.common.MinecraftForge; public class TileEntityLaser extends TileEntity implements IPeripheral { - private final int MAX_BOOSTERS_NUMBER = 10; - private final int MAX_LASER_ENERGY = 4000000; - - private int dx, dz, dy; - public float yaw, pitch; // laser direction - - private int frequency = -1; // beam frequency - public int camFreq = -1; // camera frequency - private float r, g, b; // beam color (corresponds to frequency) - - public boolean isEmitting = false; - - private String[] methodsArray = - { - "emitBeam", // 0 - "getX", "getY", "getZ", // 1, 2, 3 - "setFrequency", // 4 - "getFirstHit", // 5 - "getBoosterDXDZ", // 6 - "setCamFrequency" // 7 - }; - - public int delayTicks = 0; - private int energyFromOtherBeams = 0; - - private MovingObjectPosition firstHit; - - private int camUpdateTicks = 20; - private int registryUpdateTicks = 20 * 10; - - @Override - public void updateEntity() - { - // Frequency is not set - if (frequency == -1) - { - return; - } - - if (isWithCamera()) - { - if (registryUpdateTicks-- == 0 && FMLCommonHandler.instance().getEffectiveSide().isClient()) - { - registryUpdateTicks = 20 * 10; - WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(this.camFreq, new ChunkPosition(xCoord, yCoord, zCoord), worldObj).setType(1)); - } - - if (camUpdateTicks-- == 0) - { - camUpdateTicks = 20 * 5; // 5 seconds - sendFreqPacket(); // send own cam frequency to clients - } - } - - if (isEmitting && ++delayTicks > 20 * 3) - { - delayTicks = 0; - isEmitting = false; - emitBeam(Math.min(this.collectEnergyFromBoosters() + MathHelper.floor_double(energyFromOtherBeams * 0.60D), MAX_LASER_ENERGY)); - energyFromOtherBeams = 0; - } - } - - public void addBeamEnergy(int amount) - { - if (isEmitting) - { - energyFromOtherBeams += amount; - System.out.println("[EL] Added energy: " + amount); - } - else - { - System.out.println("[EL] Ignored energy: " + amount); - } - } - - private int collectEnergyFromBoosters() - { - int energyCollected = 0; - - if (findFirstBooster() != null) - { - for (int shift = 1; shift <= MAX_BOOSTERS_NUMBER; shift++) - { - int newX = xCoord + (dx * shift); - int newY = yCoord + (dy * shift); - int newZ = zCoord + (dz * shift); - TileEntity te = worldObj.getBlockTileEntity(newX, newY, newZ); - - if (te != null && te instanceof TileEntityParticleBooster) - { - energyCollected += ((TileEntityParticleBooster)te).collectAllEnergy(); - } - else - { - break; - } - } - } - - return energyCollected; - } - - // TODO refactor me - private void emitBeam(int energy) - { - // Beam power calculations - int beamLengthBlocks = energy / 5000; - System.out.println("Energy: " + energy + " | beamLengthBlocks: " + beamLengthBlocks); - - if (energy == 0 || beamLengthBlocks < 1) - { - return; - } - - Vector3 beamVector = new Vector3(this).add(0.5); - System.out.println("beamVector: " + beamVector); - float yawz = MathHelper.cos(-yaw * 0.017453292F - (float) Math.PI); - float yawx = MathHelper.sin(-yaw * 0.017453292F - (float) Math.PI); - float pitchhorizontal = -MathHelper.cos(-pitch * 0.017453292F); - float pitchvertical = MathHelper.sin(-pitch * 0.017453292F); - float directionx = yawx * pitchhorizontal; - float directionz = yawz * pitchhorizontal; - Vector3 lookVector = new Vector3((double) directionx, (double) pitchvertical, (double) directionz); - Vector3.translate(beamVector, lookVector); - Vector3 reachPoint = beamVector.clone().translate(beamVector.clone(), beamVector.clone().scale(lookVector.clone(), beamLengthBlocks)); - System.out.println("Look vector: " + lookVector); - System.out.println("reachPoint: " + reachPoint); - System.out.println("translatedBeamVector: " + beamVector); - Vector3 endPoint = reachPoint.clone(); - playSoundCorrespondsEnergy(energy); - - // This is scanning beam, do not deal damage to blocks - if (frequency == 1420) - { - firstHit = worldObj.rayTraceBlocks_do_do(beamVector.toVec3(), reachPoint.toVec3(), false, false); - - if (firstHit != null) - { - sendLaserPacket(beamVector, new Vector3(firstHit), r, g, b, 50, energy, 200); - } - - return; - } - - for (int passedBlocks = 0; passedBlocks < beamLengthBlocks; ++passedBlocks) - { - // Get next block hit - MovingObjectPosition hit = worldObj.rayTraceBlocks_do_do(beamVector.toVec3(), reachPoint.toVec3(), true, false); - // FIXME entity ray-tracing - MovingObjectPosition entityHit = raytraceEntities(beamVector.clone(), lookVector.clone(), true, beamLengthBlocks); - - if (entityHit == null) - { - System.out.println("Entity hit is null."); - } - else - { - System.out.println("Entity hit: " + entityHit); - } - - if (entityHit != null && entityHit.entityHit instanceof EntityLivingBase) - { - EntityLivingBase e = (EntityLivingBase)entityHit.entityHit; - double distanceToEntity = entityHit.hitVec.distanceTo(beamVector.clone().toVec3()); - - if (hit == null || (hit != null && hit.hitVec.distanceTo(beamVector.clone().toVec3()) > distanceToEntity)) - { - if (distanceToEntity <= beamLengthBlocks) - { - ((EntityLivingBase)e).setFire(100); - ((EntityLivingBase)e).attackEntityFrom(DamageSource.inFire, energy / 10000); - - if (energy > 1000000) - { - worldObj.newExplosion(null, e.posX, e.posY, e.posZ, 4F, true, true); - } - - // consume energy - energy -= 10000 + (10 * distanceToEntity); - endPoint = new Vector3(entityHit.hitVec); - break; - } - } - } - - // Laser is missed - if (hit == null && entityHit == null) - { - endPoint = reachPoint; - break; - } - else if (hit != null) - { - // We got a hit block - int distance = (int) new Vector3(hit.hitVec).distanceTo(beamVector); - - // Laser gone too far - if (distance >= beamLengthBlocks) - { - endPoint = reachPoint; - break; - } - - int blockID = worldObj.getBlockId(hit.blockX, hit.blockY, hit.blockZ); - int blockMeta = worldObj.getBlockMetadata(hit.blockX, hit.blockY, hit.blockZ); - float resistance = Block.blocksList[blockID].blockResistance; - - if (blockID == Block.bedrock.blockID) - { - endPoint = new Vector3(hit.hitVec); - break; - } - - // Hit is a laser head - if (blockID == WarpDrive.instance.config.laserID || blockID == WarpDrive.instance.config.laserCamID) - { - // Compare frequencies - TileEntityLaser tel = (TileEntityLaser)worldObj.getBlockTileEntity(hit.blockX, hit.blockY, hit.blockZ); - - if (tel != null && tel.getFrequency() == frequency) - { - tel.addBeamEnergy(energy); - endPoint = new Vector3(hit.hitVec); - break; - } - } - - if (Block.blocksList[blockID].blockMaterial == Material.glass) - { - worldObj.destroyBlock(hit.blockX, hit.blockY, hit.blockZ, (worldObj.rand.nextInt(20) == 0)); - endPoint = new Vector3(hit.hitVec); - } - - energy -= 70000 + (resistance * 1000) + (distance * 10); - endPoint = new Vector3(hit.hitVec); - - if (energy <= 0) - { - break; - } - - if (resistance >= Block.obsidian.blockResistance) - { - worldObj.newExplosion(null, hit.blockX, hit.blockY, hit.blockZ, 4F * (2 + (energy / 500000)), true, true); - worldObj.setBlock(hit.blockX, hit.blockY, hit.blockZ, (worldObj.rand.nextBoolean()) ? Block.fire.blockID : 0); - } - else - { - worldObj.destroyBlock(hit.blockX, hit.blockY, hit.blockZ, (worldObj.rand.nextInt(20) == 0)); - } - } - } - - sendLaserPacket(beamVector, endPoint, r, g, b, 50, energy, beamLengthBlocks); - } - - public MovingObjectPosition raytraceEntities(Vector3 beamVec, Vector3 lookVec, boolean collisionFlag, double reachDistance) - { - MovingObjectPosition pickedEntity = null; - Vec3 playerPosition = beamVec.toVec3(); - Vec3 playerLook = lookVec.toVec3(); - Vec3 playerViewOffset = Vec3.createVectorHelper(playerPosition.xCoord + playerLook.xCoord * reachDistance, playerPosition.yCoord - + playerLook.yCoord * reachDistance, playerPosition.zCoord + playerLook.zCoord * reachDistance); - double playerBorder = 1.1 * reachDistance; - AxisAlignedBB boxToScan = WarpDrive.laserBlock.getCollisionBoundingBoxFromPool(worldObj, xCoord, yCoord, zCoord).expand(playerBorder, playerBorder, playerBorder); - List entitiesHit = worldObj.getEntitiesWithinAABBExcludingEntity(null, boxToScan); - double closestEntity = reachDistance; - - if (entitiesHit == null || entitiesHit.isEmpty()) - { - return null; - } - - for (Entity entityHit : (Iterable<Entity>) entitiesHit) - { - if (entityHit != null && entityHit.canBeCollidedWith() && entityHit.boundingBox != null) - { - float border = entityHit.getCollisionBorderSize(); - AxisAlignedBB aabb = entityHit.boundingBox.expand((double) border, (double) border, (double) border); - MovingObjectPosition hitMOP = aabb.calculateIntercept(playerPosition, playerViewOffset); - - if (hitMOP != null) - { - if (aabb.isVecInside(playerPosition)) - { - if (0.0D < closestEntity || closestEntity == 0.0D) - { - pickedEntity = new MovingObjectPosition(entityHit); - - if (pickedEntity != null) - { - pickedEntity.hitVec = hitMOP.hitVec; - closestEntity = 0.0D; - } - } - } - else - { - double distance = playerPosition.distanceTo(hitMOP.hitVec); - - if (distance < closestEntity || closestEntity == 0.0D) - { - pickedEntity = new MovingObjectPosition(entityHit); - pickedEntity.hitVec = hitMOP.hitVec; - closestEntity = distance; - } - } - } - } - } - - return pickedEntity; - } - - public boolean isWithCamera() - { - return (worldObj.getBlockId(xCoord, yCoord, zCoord) == WarpDrive.instance.config.laserCamID); - } - - public int getFrequency() - { - return frequency; - } - - private TileEntityParticleBooster findFirstBooster() - { - TileEntity result; - result = worldObj.getBlockTileEntity(xCoord + 1, yCoord, zCoord); - - if (result != null && result instanceof TileEntityParticleBooster) - { - dx = 1; - dz = 0; - dy = 0; - return (TileEntityParticleBooster) result; - } - - result = worldObj.getBlockTileEntity(xCoord - 1, yCoord, zCoord); - - if (result != null && result instanceof TileEntityParticleBooster) - { - dx = -1; - dz = 0; - dy = 0; - return (TileEntityParticleBooster) result; - } - - result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord + 1); - - if (result != null && result instanceof TileEntityParticleBooster) - { - dx = 0; - dz = 1; - dy = 0; - return (TileEntityParticleBooster) result; - } - - result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord - 1); - - if (result != null && result instanceof TileEntityParticleBooster) - { - dx = 0; - dz = -1; - dy = 0; - return (TileEntityParticleBooster) result; - } - - result = worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord); - - if (result != null && result instanceof TileEntityParticleBooster) - { - dx = 0; - dz = 0; - dy = 1; - return (TileEntityParticleBooster) result; - } - - result = worldObj.getBlockTileEntity(xCoord, yCoord - 1, zCoord); - - if (result != null && result instanceof TileEntityParticleBooster) - { - dx = 0; - dz = 0; - dy = -1; - return (TileEntityParticleBooster) result; - } - - return null; - } - - public void sendLaserPacket(Vector3 source, Vector3 dest, float r, float g, float b, int age, int energy, int radius) - { - Side side = FMLCommonHandler.instance().getEffectiveSide(); - - if (side == Side.SERVER) - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(8); - DataOutputStream outputStream = new DataOutputStream(bos); - - try - { - // Write source vector - outputStream.writeDouble(source.x); - outputStream.writeDouble(source.y); - outputStream.writeDouble(source.z); - // Write target vector - outputStream.writeDouble(dest.x); - outputStream.writeDouble(dest.y); - outputStream.writeDouble(dest.z); - // Write r, g, b of laser - outputStream.writeFloat(r); - outputStream.writeFloat(g); - outputStream.writeFloat(b); - // Write age - outputStream.writeByte(age); - // Write energy value - outputStream.writeInt(energy); - } - catch (Exception ex) - { - ex.printStackTrace(); - } - - Packet250CustomPayload packet = new Packet250CustomPayload(); - packet.channel = "WarpDriveBeam"; - packet.data = bos.toByteArray(); - packet.length = bos.size(); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(source.intX(), source.intY(), source.intZ(), radius, worldObj.provider.dimensionId, packet); - ByteArrayOutputStream bos2 = new ByteArrayOutputStream(8); - DataOutputStream outputStream2 = new DataOutputStream(bos2); - - try - { - // Write source vector - outputStream2.writeDouble(source.x); - outputStream2.writeDouble(source.y); - outputStream2.writeDouble(source.z); - // Write target vector - outputStream2.writeDouble(dest.x); - outputStream2.writeDouble(dest.y); - outputStream2.writeDouble(dest.z); - // Write r, g, b of laser - outputStream2.writeFloat(r); - outputStream2.writeFloat(g); - outputStream2.writeFloat(b); - // Write age - outputStream2.writeByte(age); - // Write energy value - outputStream2.writeInt(energy); - } - catch (Exception ex) - { - ex.printStackTrace(); - } - - Packet250CustomPayload packet2 = new Packet250CustomPayload(); - packet.channel = "WarpDriveBeam"; - packet.data = bos.toByteArray(); - packet.length = bos.size(); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(dest.intX(), dest.intY(), dest.intZ(), radius, worldObj.provider.dimensionId, packet); - } - } - - private void playSoundCorrespondsEnergy(int energy) - { - if (energy <= 500000) - { - worldObj.playSoundEffect(xCoord + 0.5f, yCoord - 0.5f, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F); - } - else if (energy > 500000 && energy <= 1000000) - { - worldObj.playSoundEffect(xCoord + 0.5f, yCoord - 0.5f, zCoord + 0.5f, "warpdrive:midlaser", 4F, 1F); - } - else if (energy > 1000000) - { - worldObj.playSoundEffect(xCoord + 0.5f, yCoord - 0.5f, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); - } - } - - private boolean parseFrequency(int freq) - { - if (freq > 65000 || freq < 0) // Invalid frequency - { - r = 1; - g = 0; - b = 0; - return false; - } - - if (freq > 0 && freq < 10000) // red - { - r = 1; - g = 0; - b = 0; - } - else if (freq > 10000 && freq <= 20000) // orange - { - r = 1; - g = 0; - b = 0.5f; - } - else if (freq > 20000 && freq <= 30000) // yellow - { - r = 1; - g = 1; - b = 0; - } - else if (freq > 30000 && freq <= 40000) // green - { - r = 0; - g = 1; - b = 0; - } - else if (freq > 50000 && freq <= 60000) // blue - { - r = 0; - g = 0; - b = 1; - } - else if (freq > 60000 && freq <= 65000) // violet - { - r = 0.5f; - g = 0; - b = 0.5f; - } - else // impossible frequency - { - r = 1; - g = 0; - b = 0; - } - - return true; - } - - @Override - public void readFromNBT(NBTTagCompound tag) - { - super.readFromNBT(tag); - frequency = tag.getInteger("frequency"); - camFreq = tag.getInteger("camfreq"); - } - - @Override - public void writeToNBT(NBTTagCompound tag) - { - super.writeToNBT(tag); - tag.setInteger("frequency", frequency); - tag.setInteger("camFreq", camFreq); - } - - // IPeripheral methods implementation - @Override - public String getType() - { - return "laser"; - } - - @Override - public String[] getMethodNames() - { - return methodsArray; - } - - @Override - public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception - { - switch (method) - { - case 0: // emitBeam(yaw, pitch) - - // emitBeam(dx, dy, dz) - if (arguments.length == 2) - { - yaw = ((Double)arguments[0]).floatValue(); - pitch = ((Double)arguments[1]).floatValue(); - isEmitting = true; - delayTicks = 0; - } - else if (arguments.length == 3) - { - double dx = (Double)arguments[0]; - double dy = (Double)arguments[1]; - double dz = (Double)arguments[2]; - double targetX = xCoord + dx; - double targetY = yCoord + dy; - double targetZ = zCoord + dz; - float xd = (float)(xCoord - targetX); - float yd = (float)(yCoord - targetY); - float zd = (float)(zCoord - targetZ); - double var7 = MathHelper.sqrt_double(xd * xd + zd * zd); - yaw = ((float)(Math.atan2(xd, zd) * 180.0D / Math.PI)); - pitch = ((float)(Math.atan2(yd, var7) * 180.0D / Math.PI)); - isEmitting = true; - delayTicks = 0; - } - - return new Object[] { 0 }; - - case 1: // getX - return new Integer[] { this.xCoord }; - case 2: // getY - return new Integer[] { this.yCoord }; - case 3: // getZ - return new Integer[] { this.zCoord }; - case 4: // setFrequency(freq) - if (arguments.length == 1) - { - int freq = ((Double)arguments[0]).intValue(); - this.frequency = freq; - - if (parseFrequency(freq)) - { - return new Object[] { 0 }; - } - else - { - return new Object[] { -1 }; - } - } - - case 5: // getFirstHit() - if (firstHit != null) - { - int blockID = worldObj.getBlockId(firstHit.blockX, firstHit.blockY, firstHit.blockZ); - int blockMeta = worldObj.getBlockMetadata(firstHit.blockX, firstHit.blockY, firstHit.blockZ); - float blockResistance = Block.blocksList[blockID].blockResistance; - Object[] info = { (Integer)firstHit.blockX, (Integer)firstHit.blockY, (Integer)firstHit.blockZ, blockID, blockMeta, (Float)blockResistance }; - firstHit = null; - return info; - } - else - { - return new Object[] { -1, 0, 0, 0, 0, 0, -1 }; - } - - case 6: // getBoosterDXDZ - findFirstBooster(); - return new Object[] { (Integer)dx, (Integer)dz }; - - case 7: // setCamFrequency (only for lasers with cam) - if (arguments.length == 1) - { - if (isWithCamera()) - { - int freq = ((Double)arguments[0]).intValue(); - this.camFreq = freq; - } - } - } - - return new Object[] { 0 }; - } - - // Camera frequency refresh to clients packet - public void sendFreqPacket() - { - Side side = FMLCommonHandler.instance().getEffectiveSide(); - - if (side == Side.SERVER) - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(8); - DataOutputStream outputStream = new DataOutputStream(bos); - - try - { - // Write source vector - outputStream.writeInt(xCoord); - outputStream.writeInt(yCoord); - outputStream.writeInt(zCoord); - outputStream.writeInt(this.camFreq); - } - catch (Exception ex) - { - ex.printStackTrace(); - } - - Packet250CustomPayload packet = new Packet250CustomPayload(); - packet.channel = "WarpDriveFreq"; - packet.data = bos.toByteArray(); - packet.length = bos.size(); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(xCoord, yCoord, zCoord, 100, worldObj.provider.dimensionId, packet); - } - } - - @Override - public boolean canAttachToSide(int side) - { - return true; - } - - @Override - public void attach(IComputerAccess computer) - { - } - - @Override - public void detach(IComputerAccess computer) - { - } + private final int MAX_BOOSTERS_NUMBER = 10; + private final int MAX_LASER_ENERGY = 4000000; + + private int dx, dz, dy; + public float yaw, pitch; // laser direction + + private int frequency = -1; // beam frequency + public int camFreq = -1; // camera frequency + private float r, g, b; // beam color (corresponds to frequency) + + public boolean isEmitting = false; + + private String[] methodsArray = + { + "emitBeam", // 0 + "pos", // 1 + "freq", // 2 + "getFirstHit", // 3 + "getBoosterDXDZ", // 4 + "camFreq" // 5 + }; + + public int delayTicks = 0; + private int energyFromOtherBeams = 0; + + private MovingObjectPosition firstHit; + + private int camUpdateTicks = 20; + private int registryUpdateTicks = 20 * 10; + + @Override + public void updateEntity() + { + // Frequency is not set + if (frequency == -1) + { + return; + } + + if (isWithCamera()) + { + if (registryUpdateTicks-- == 0 && FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + registryUpdateTicks = 20 * 10; + WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(this.camFreq, new ChunkPosition(xCoord, yCoord, zCoord), worldObj).setType(1)); + } + + if (camUpdateTicks-- == 0) + { + camUpdateTicks = 20 * 5; // 5 seconds + sendFreqPacket(); // send own cam frequency to clients + } + } + + if (isEmitting && ++delayTicks > 20 * 3) + { + delayTicks = 0; + isEmitting = false; + emitBeam(Math.min(this.collectEnergyFromBoosters() + MathHelper.floor_double(energyFromOtherBeams * 0.60D), MAX_LASER_ENERGY)); + energyFromOtherBeams = 0; + } + } + + public void addBeamEnergy(int amount) + { + if (isEmitting) + { + energyFromOtherBeams += amount; + System.out.println("[EL] Added energy: " + amount); + } + else + { + System.out.println("[EL] Ignored energy: " + amount); + } + } + + private int collectEnergyFromBoosters() + { + int energyCollected = 0; + + if (findFirstBooster() != null) + { + for (int shift = 1; shift <= MAX_BOOSTERS_NUMBER; shift++) + { + int newX = xCoord + (dx * shift); + int newY = yCoord + (dy * shift); + int newZ = zCoord + (dz * shift); + TileEntity te = worldObj.getBlockTileEntity(newX, newY, newZ); + + if (te != null && te instanceof TileEntityParticleBooster) + { + energyCollected += ((TileEntityParticleBooster)te).collectAllEnergy(); + } + else + { + break; + } + } + } + + return energyCollected; + } + + // TODO refactor me + private void emitBeam(int energy) + { + // Beam power calculations + int beamLengthBlocks = energy / 5000; + System.out.println("Energy: " + energy + " | beamLengthBlocks: " + beamLengthBlocks); + + if (energy == 0 || beamLengthBlocks < 1) + { + return; + } + + Vector3 beamVector = new Vector3(this).add(0.5); + System.out.println("beamVector: " + beamVector); + float yawz = MathHelper.cos(-yaw * 0.017453292F - (float) Math.PI); + float yawx = MathHelper.sin(-yaw * 0.017453292F - (float) Math.PI); + float pitchhorizontal = -MathHelper.cos(-pitch * 0.017453292F); + float pitchvertical = MathHelper.sin(-pitch * 0.017453292F); + float directionx = yawx * pitchhorizontal; + float directionz = yawz * pitchhorizontal; + Vector3 lookVector = new Vector3((double) directionx, (double) pitchvertical, (double) directionz); + Vector3.translate(beamVector, lookVector); + Vector3 reachPoint = beamVector.clone().translate(beamVector.clone(), beamVector.clone().scale(lookVector.clone(), beamLengthBlocks)); + System.out.println("Look vector: " + lookVector); + System.out.println("reachPoint: " + reachPoint); + System.out.println("translatedBeamVector: " + beamVector); + Vector3 endPoint = reachPoint.clone(); + playSoundCorrespondsEnergy(energy); + + // This is scanning beam, do not deal damage to blocks + if (frequency == 1420) + { + firstHit = worldObj.rayTraceBlocks_do_do(beamVector.toVec3(), reachPoint.toVec3(), false, false); + + if (firstHit != null) + { + sendLaserPacket(beamVector, new Vector3(firstHit), r, g, b, 50, energy, 200); + } + + return; + } + + for (int passedBlocks = 0; passedBlocks < beamLengthBlocks; ++passedBlocks) + { + // Get next block hit + MovingObjectPosition hit = worldObj.rayTraceBlocks_do_do(beamVector.toVec3(), reachPoint.toVec3(), true, false); + // FIXME entity ray-tracing + MovingObjectPosition entityHit = raytraceEntities(beamVector.clone(), lookVector.clone(), true, beamLengthBlocks); + + if (entityHit == null) + { + System.out.println("Entity hit is null."); + } + else + { + System.out.println("Entity hit: " + entityHit); + } + + if (entityHit != null && entityHit.entityHit instanceof EntityLivingBase) + { + EntityLivingBase e = (EntityLivingBase)entityHit.entityHit; + double distanceToEntity = entityHit.hitVec.distanceTo(beamVector.clone().toVec3()); + + if (hit == null || (hit != null && hit.hitVec.distanceTo(beamVector.clone().toVec3()) > distanceToEntity)) + { + if (distanceToEntity <= beamLengthBlocks) + { + ((EntityLivingBase)e).setFire(100); + ((EntityLivingBase)e).attackEntityFrom(DamageSource.inFire, energy / 10000); + + if (energy > 1000000) + { + worldObj.newExplosion(null, e.posX, e.posY, e.posZ, 4F, true, true); + } + + // consume energy + energy -= 10000 + (10 * distanceToEntity); + endPoint = new Vector3(entityHit.hitVec); + break; + } + } + } + + // Laser is missed + if (hit == null && entityHit == null) + { + endPoint = reachPoint; + break; + } + else if (hit != null) + { + // We got a hit block + int distance = (int) new Vector3(hit.hitVec).distanceTo(beamVector); + + // Laser gone too far + if (distance >= beamLengthBlocks) + { + endPoint = reachPoint; + break; + } + + int blockID = worldObj.getBlockId(hit.blockX, hit.blockY, hit.blockZ); + int blockMeta = worldObj.getBlockMetadata(hit.blockX, hit.blockY, hit.blockZ); + float resistance = Block.blocksList[blockID].blockResistance; + + if (blockID == Block.bedrock.blockID) + { + endPoint = new Vector3(hit.hitVec); + break; + } + + // Hit is a laser head + if (blockID == WarpDriveConfig.i.laserID || blockID == WarpDriveConfig.i.laserCamID) + { + // Compare frequencies + TileEntityLaser tel = (TileEntityLaser)worldObj.getBlockTileEntity(hit.blockX, hit.blockY, hit.blockZ); + + if (tel != null && tel.getFrequency() == frequency) + { + tel.addBeamEnergy(energy); + endPoint = new Vector3(hit.hitVec); + break; + } + } + + if (Block.blocksList[blockID].blockMaterial == Material.glass) + { + worldObj.destroyBlock(hit.blockX, hit.blockY, hit.blockZ, (worldObj.rand.nextInt(20) == 0)); + endPoint = new Vector3(hit.hitVec); + } + + energy -= 70000 + (resistance * 1000) + (distance * 10); + endPoint = new Vector3(hit.hitVec); + + if (energy <= 0) + { + break; + } + + if (resistance >= Block.obsidian.blockResistance) + { + worldObj.newExplosion(null, hit.blockX, hit.blockY, hit.blockZ, 4F * (2 + (energy / 500000)), true, true); + worldObj.setBlock(hit.blockX, hit.blockY, hit.blockZ, (worldObj.rand.nextBoolean()) ? Block.fire.blockID : 0); + } + else + { + worldObj.destroyBlock(hit.blockX, hit.blockY, hit.blockZ, (worldObj.rand.nextInt(20) == 0)); + } + } + } + + sendLaserPacket(beamVector, endPoint, r, g, b, 50, energy, beamLengthBlocks); + } + + public MovingObjectPosition raytraceEntities(Vector3 beamVec, Vector3 lookVec, boolean collisionFlag, double reachDistance) + { + MovingObjectPosition pickedEntity = null; + Vec3 playerPosition = beamVec.toVec3(); + Vec3 playerLook = lookVec.toVec3(); + Vec3 playerViewOffset = Vec3.createVectorHelper(playerPosition.xCoord + playerLook.xCoord * reachDistance, playerPosition.yCoord + + playerLook.yCoord * reachDistance, playerPosition.zCoord + playerLook.zCoord * reachDistance); + double playerBorder = 1.1 * reachDistance; + AxisAlignedBB boxToScan = WarpDrive.laserBlock.getCollisionBoundingBoxFromPool(worldObj, xCoord, yCoord, zCoord).expand(playerBorder, playerBorder, playerBorder); + List entitiesHit = worldObj.getEntitiesWithinAABBExcludingEntity(null, boxToScan); + double closestEntity = reachDistance; + + if (entitiesHit == null || entitiesHit.isEmpty()) + { + return null; + } + + for (Entity entityHit : (Iterable<Entity>) entitiesHit) + { + if (entityHit != null && entityHit.canBeCollidedWith() && entityHit.boundingBox != null) + { + float border = entityHit.getCollisionBorderSize(); + AxisAlignedBB aabb = entityHit.boundingBox.expand((double) border, (double) border, (double) border); + MovingObjectPosition hitMOP = aabb.calculateIntercept(playerPosition, playerViewOffset); + + if (hitMOP != null) + { + if (aabb.isVecInside(playerPosition)) + { + if (0.0D < closestEntity || closestEntity == 0.0D) + { + pickedEntity = new MovingObjectPosition(entityHit); + + if (pickedEntity != null) + { + pickedEntity.hitVec = hitMOP.hitVec; + closestEntity = 0.0D; + } + } + } + else + { + double distance = playerPosition.distanceTo(hitMOP.hitVec); + + if (distance < closestEntity || closestEntity == 0.0D) + { + pickedEntity = new MovingObjectPosition(entityHit); + pickedEntity.hitVec = hitMOP.hitVec; + closestEntity = distance; + } + } + } + } + } + + return pickedEntity; + } + + public boolean isWithCamera() + { + return (worldObj.getBlockId(xCoord, yCoord, zCoord) == WarpDriveConfig.i.laserCamID); + } + + public int getFrequency() + { + return frequency; + } + + private TileEntityParticleBooster findFirstBooster() + { + TileEntity result; + result = worldObj.getBlockTileEntity(xCoord + 1, yCoord, zCoord); + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = 1; + dz = 0; + dy = 0; + return (TileEntityParticleBooster) result; + } + + result = worldObj.getBlockTileEntity(xCoord - 1, yCoord, zCoord); + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = -1; + dz = 0; + dy = 0; + return (TileEntityParticleBooster) result; + } + + result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord + 1); + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = 0; + dz = 1; + dy = 0; + return (TileEntityParticleBooster) result; + } + + result = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord - 1); + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = 0; + dz = -1; + dy = 0; + return (TileEntityParticleBooster) result; + } + + result = worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord); + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = 0; + dz = 0; + dy = 1; + return (TileEntityParticleBooster) result; + } + + result = worldObj.getBlockTileEntity(xCoord, yCoord - 1, zCoord); + + if (result != null && result instanceof TileEntityParticleBooster) + { + dx = 0; + dz = 0; + dy = -1; + return (TileEntityParticleBooster) result; + } + + return null; + } + + public void sendLaserPacket(Vector3 source, Vector3 dest, float r, float g, float b, int age, int energy, int radius) + { + Side side = FMLCommonHandler.instance().getEffectiveSide(); + + if (side == Side.SERVER) + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(8); + DataOutputStream outputStream = new DataOutputStream(bos); + + try + { + // Write source vector + outputStream.writeDouble(source.x); + outputStream.writeDouble(source.y); + outputStream.writeDouble(source.z); + // Write target vector + outputStream.writeDouble(dest.x); + outputStream.writeDouble(dest.y); + outputStream.writeDouble(dest.z); + // Write r, g, b of laser + outputStream.writeFloat(r); + outputStream.writeFloat(g); + outputStream.writeFloat(b); + // Write age + outputStream.writeByte(age); + // Write energy value + outputStream.writeInt(energy); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + Packet250CustomPayload packet = new Packet250CustomPayload(); + packet.channel = "WarpDriveBeam"; + packet.data = bos.toByteArray(); + packet.length = bos.size(); + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(source.intX(), source.intY(), source.intZ(), radius, worldObj.provider.dimensionId, packet); + ByteArrayOutputStream bos2 = new ByteArrayOutputStream(8); + DataOutputStream outputStream2 = new DataOutputStream(bos2); + + try + { + // Write source vector + outputStream2.writeDouble(source.x); + outputStream2.writeDouble(source.y); + outputStream2.writeDouble(source.z); + // Write target vector + outputStream2.writeDouble(dest.x); + outputStream2.writeDouble(dest.y); + outputStream2.writeDouble(dest.z); + // Write r, g, b of laser + outputStream2.writeFloat(r); + outputStream2.writeFloat(g); + outputStream2.writeFloat(b); + // Write age + outputStream2.writeByte(age); + // Write energy value + outputStream2.writeInt(energy); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + Packet250CustomPayload packet2 = new Packet250CustomPayload(); + packet.channel = "WarpDriveBeam"; + packet.data = bos.toByteArray(); + packet.length = bos.size(); + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(dest.intX(), dest.intY(), dest.intZ(), radius, worldObj.provider.dimensionId, packet); + } + } + + private void playSoundCorrespondsEnergy(int energy) + { + if (energy <= 500000) + { + worldObj.playSoundEffect(xCoord + 0.5f, yCoord - 0.5f, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F); + } + else if (energy > 500000 && energy <= 1000000) + { + worldObj.playSoundEffect(xCoord + 0.5f, yCoord - 0.5f, zCoord + 0.5f, "warpdrive:midlaser", 4F, 1F); + } + else if (energy > 1000000) + { + worldObj.playSoundEffect(xCoord + 0.5f, yCoord - 0.5f, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); + } + } + + private boolean parseFrequency(int freq) + { + if (freq > 65000 || freq < 0) // Invalid frequency + { + r = 1; + g = 0; + b = 0; + return false; + } + + if (freq > 0 && freq < 10000) // red + { + r = 1; + g = 0; + b = 0; + } + else if (freq > 10000 && freq <= 20000) // orange + { + r = 1; + g = 0; + b = 0.5f; + } + else if (freq > 20000 && freq <= 30000) // yellow + { + r = 1; + g = 1; + b = 0; + } + else if (freq > 30000 && freq <= 40000) // green + { + r = 0; + g = 1; + b = 0; + } + else if (freq > 50000 && freq <= 60000) // blue + { + r = 0; + g = 0; + b = 1; + } + else if (freq > 60000 && freq <= 65000) // violet + { + r = 0.5f; + g = 0; + b = 0.5f; + } + else // impossible frequency + { + r = 1; + g = 0; + b = 0; + } + + return true; + } + + @Override + public void readFromNBT(NBTTagCompound tag) + { + super.readFromNBT(tag); + frequency = tag.getInteger("frequency"); + camFreq = tag.getInteger("camfreq"); + } + + @Override + public void writeToNBT(NBTTagCompound tag) + { + super.writeToNBT(tag); + tag.setInteger("frequency", frequency); + tag.setInteger("camFreq", camFreq); + } + + // IPeripheral methods implementation + @Override + public String getType() + { + return "laser"; + } + + @Override + public String[] getMethodNames() + { + return methodsArray; + } + + @Override + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception + { + switch (method) + { + case 0: // emitBeam(yaw, pitch) + // emitBeam(dx, dy, dz) + if (arguments.length == 2) + { + yaw = ((Double)arguments[0]).floatValue(); + pitch = ((Double)arguments[1]).floatValue(); + isEmitting = true; + delayTicks = 0; + } + else if (arguments.length == 3) + { + double dx = (Double)arguments[0]; + double dy = (Double)arguments[1]; + double dz = (Double)arguments[2]; + double targetX = xCoord + dx; + double targetY = yCoord + dy; + double targetZ = zCoord + dz; + float xd = (float)(xCoord - targetX); + float yd = (float)(yCoord - targetY); + float zd = (float)(zCoord - targetZ); + double var7 = MathHelper.sqrt_double(xd * xd + zd * zd); + yaw = ((float)(Math.atan2(xd, zd) * 180.0D / Math.PI)); + pitch = ((float)(Math.atan2(yd, var7) * 180.0D / Math.PI)); + isEmitting = true; + delayTicks = 0; + } + break; + case 1: // getX + return new Integer[] { xCoord, yCoord, zCoord }; + case 2: // Freq + if (arguments.length == 1) + { + if (parseFrequency(((Double)arguments[0]).intValue())) + frequency = ((Double)arguments[0]).intValue(); + else + return new Integer[] { -1 }; + } + return new Integer[] { frequency }; + case 3: // getFirstHit() + if (firstHit != null) + { + int blockID = worldObj.getBlockId(firstHit.blockX, firstHit.blockY, firstHit.blockZ); + int blockMeta = worldObj.getBlockMetadata(firstHit.blockX, firstHit.blockY, firstHit.blockZ); + float blockResistance = Block.blocksList[blockID].blockResistance; + Object[] info = { firstHit.blockX, firstHit.blockY, firstHit.blockZ, blockID, blockMeta, (Float)blockResistance }; + firstHit = null; + return info; + } + else + return new Integer[] { 0, 0, 0, 0, 0, -1 }; + case 4: // getBoosterDXDZ + findFirstBooster(); + return new Integer[] { dx, dz }; + + case 5: // CamFreq (only for lasers with cam) + if (isWithCamera()) + { + if (arguments.length == 1) + camFreq = ((Double)arguments[0]).intValue(); + return new Integer[] { camFreq }; + } + break; + } + return null; + } + + // Camera frequency refresh to clients packet + public void sendFreqPacket() + { + Side side = FMLCommonHandler.instance().getEffectiveSide(); + + if (side == Side.SERVER) + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(8); + DataOutputStream outputStream = new DataOutputStream(bos); + + try + { + // Write source vector + outputStream.writeInt(xCoord); + outputStream.writeInt(yCoord); + outputStream.writeInt(zCoord); + outputStream.writeInt(this.camFreq); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + Packet250CustomPayload packet = new Packet250CustomPayload(); + packet.channel = "WarpDriveFreq"; + packet.data = bos.toByteArray(); + packet.length = bos.size(); + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(xCoord, yCoord, zCoord, 100, worldObj.provider.dimensionId, packet); + } + } + + @Override + public boolean canAttachToSide(int side) + { + return true; + } + + @Override + public void attach(IComputerAccess computer) + { + } + + @Override + public void detach(IComputerAccess computer) + { + } } diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index c6dae0dd..a72685ca 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -6,7 +6,6 @@ import cpw.mods.fml.relauncher.SideOnly; import dan200.computer.api.IComputerAccess; import dan200.computer.api.ILuaContext; import dan200.computer.api.IPeripheral; -import ic2.api.item.Items; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -55,41 +54,14 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG private String[] methodsArray = { - "startMining", "stop", // 0, 1 - "isMining", // 2 - "startQuarry", // 3 - "getMinerState", // 4 - "setStartLayerOffset" // 5 + "mine", //0 + "stop", //1 + "isMining", //2 + "quarry", //3 + "state", //4 + "offset" //5 }; - public static final ArrayList<Integer> valuableOres = new ArrayList<Integer>(Arrays.asList( - Block.oreIron.blockID, - Block.oreGold.blockID, - Block.oreCoal.blockID, - Block.oreEmerald.blockID, - Block.oreLapis.blockID, - Block.oreRedstoneGlowing.blockID, - Block.oreRedstone.blockID, - Block.oreNetherQuartz.blockID, - Items.getItem("uraniumOre").itemID, // IC - Items.getItem("copperOre").itemID, // IC - Items.getItem("tinOre").itemID, // IC - 4095 // AS uranus - )); - - public static final ArrayList<Integer> otherValuables = new ArrayList<Integer>(Arrays.asList( - Block.wood.blockID, - Block.planks.blockID, - Items.getItem("rubberWood").itemID, - Block.rail.blockID, - 902, // Quarz (AE), - Block.oreDiamond.blockID, - Block.obsidian.blockID, - Block.web.blockID, - Block.fence.blockID, - Block.torchWood.blockID - )); - private final int SCAN_DELAY = 20 * 5; private int delayTicksScan = 0; @@ -113,8 +85,6 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG TileEntityParticleBooster booster = null; - private final int MFFS_FIELD_BLOCKID = 1681; - private boolean isOnEarth = false; //int t = 20; @Override @@ -197,7 +167,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG private boolean canDig(int blockID) { - return (blockID != MFFS_FIELD_BLOCKID && blockID != Block.bedrock.blockID && Block.blocksList[blockID] != null && Block.blocksList[blockID].blockResistance <= Block.obsidian.blockResistance); + return (blockID != WarpDriveConfig.i.MFFS_Field && blockID != Block.bedrock.blockID && Block.blocksList[blockID] != null && Block.blocksList[blockID].blockResistance <= Block.obsidian.blockResistance); } private void harvestBlock(Vector3 valuable) @@ -415,7 +385,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG valuablesInLayer.add(new Vector3(x, currentLayer, z)); } else // Not-quarry collect only valuables blocks - if (valuableOres.contains((worldObj.getBlockId(x, currentLayer, z))) || otherValuables.contains((worldObj.getBlockId(x, currentLayer, z)))) + if (WarpDriveConfig.i.MinerOres.contains(worldObj.getBlockId(x, currentLayer, z))) valuablesInLayer.add(new Vector3(x, currentLayer, z)); } @@ -579,16 +549,16 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG { switch (method) { - case 0: // startMining() + case 0: // Mine() if (isMining) - return new Object[] { -1 }; + return new Boolean[] { false }; isQuarry = false; delayTicksScan = 0; currentMode = 0; minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); currentLayer = yCoord - layerOffset; isMining = true; - return new Object[] { 0 }; + return new Boolean[] { true }; case 1: // stop() isMining = false; @@ -596,9 +566,9 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG case 2: // isMining() return new Boolean[] { isMining }; - case 3: // startQuarry() + case 3: // Quarry() if (isMining) - return new Object[] { -1 }; + return new Boolean[] { false }; isQuarry = true; delayTicksScan = 0; @@ -606,47 +576,36 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); currentLayer = yCoord - layerOffset; isMining = true; - return new Object[] { 0 }; + return new Boolean[] { true }; - // State is: state, energy, currentLayer, valuablesMined, valuablesInLayer = getMinerState() - case 4: // getMinerState() + case 4: // State is: state, energy, currentLayer, valuablesMined, valuablesInLayer = getMinerState() int energy = 0; - if (booster != null) - { energy = booster.getCurrentEnergyValue(); - } - String state = "not mining"; Integer valuablesInLayer, valuablesMined; - if (isMining) { valuablesInLayer = this.valuablesInLayer.size(); valuablesMined = this.valuableIndex; state = "mining" + ((isQuarry) ? " (quarry mode)" : ""); - if (energy < 0) - { state = "out of energy"; - } - return new Object[] {state, energy, currentLayer, valuablesMined, valuablesInLayer}; } - return new Object[] {state, energy, currentLayer, 0, 0}; - case 5: // setStartLayerOffset + case 5: // Offset if (arguments.length == 1) { - int a = ((Double)arguments[0]).intValue(); - if (a < 1) - a = 1; - layerOffset = a + 1; + int t = ((Double)arguments[0]).intValue(); + if (t < 0) + t = 0; + layerOffset = t + 1; } + return new Integer[] { layerOffset-1 }; } - - return new Object[] { 0 }; + return null; } @Override diff --git a/src/cr0s/WarpDrive/TileEntityMonitor.java b/src/cr0s/WarpDrive/TileEntityMonitor.java index 8813ad23..c5819990 100644 --- a/src/cr0s/WarpDrive/TileEntityMonitor.java +++ b/src/cr0s/WarpDrive/TileEntityMonitor.java @@ -34,131 +34,118 @@ import net.minecraftforge.common.MinecraftForge; public class TileEntityMonitor extends TileEntity implements IPeripheral { - private int frequency; + private int frequency; - private String[] methodsArray = - { - "setFrequency", // 0 - "getFrequency" - }; + private String[] methodsArray = + { + "freq" + }; - private int packetSendTicks = 20; + private int packetSendTicks = 20; - @Override - public void updateEntity() - { - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) - { - if (packetSendTicks-- == 0) - { - packetSendTicks = 20 * 5; - sendFreqPacket(); - } + @Override + public void updateEntity() + { + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) + { + if (packetSendTicks-- == 0) + { + packetSendTicks = 20 * 5; + sendFreqPacket(); + } - return; - } - } + return; + } + } - public int getFrequency() - { - return frequency; - } + public int getFrequency() + { + return frequency; + } - public void setFrequency(int freq) - { - frequency = freq; - } + public void setFrequency(int freq) + { + frequency = freq; + } - @Override - public void readFromNBT(NBTTagCompound tag) - { - super.readFromNBT(tag); - frequency = tag.getInteger("frequency"); - } + @Override + public void readFromNBT(NBTTagCompound tag) + { + super.readFromNBT(tag); + frequency = tag.getInteger("frequency"); + } - @Override - public void writeToNBT(NBTTagCompound tag) - { - super.writeToNBT(tag); - tag.setInteger("frequency", frequency); - } + @Override + public void writeToNBT(NBTTagCompound tag) + { + super.writeToNBT(tag); + tag.setInteger("frequency", frequency); + } - // IPeripheral methods implementation - @Override - public String getType() - { - return "monitor"; - } + // IPeripheral methods implementation + @Override + public String getType() + { + return "monitor"; + } - @Override - public String[] getMethodNames() - { - return methodsArray; - } + @Override + public String[] getMethodNames() + { + return methodsArray; + } - @Override - public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception - { - switch (method) - { - case 0: // setFrequency - if (arguments.length == 1) - { - frequency = ((Double)arguments[0]).intValue(); - } + @Override + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception + { + if (arguments.length == 1) + frequency = ((Double)arguments[0]).intValue(); + return new Integer[] { frequency }; + } - break; + public void sendFreqPacket() + { + Side side = FMLCommonHandler.instance().getEffectiveSide(); - case 1: - return new Object[] { (Integer)frequency }; - } + if (side == Side.SERVER) + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(8); + DataOutputStream outputStream = new DataOutputStream(bos); - return new Object[] { 0 }; - } + try + { + // Write source vector + outputStream.writeInt(xCoord); + outputStream.writeInt(yCoord); + outputStream.writeInt(zCoord); + outputStream.writeInt(this.frequency); + } + catch (Exception ex) + { + ex.printStackTrace(); + } - public void sendFreqPacket() - { - Side side = FMLCommonHandler.instance().getEffectiveSide(); + Packet250CustomPayload packet = new Packet250CustomPayload(); + packet.channel = "WarpDriveFreq"; + packet.data = bos.toByteArray(); + packet.length = bos.size(); + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(xCoord, yCoord, zCoord, 100, worldObj.provider.dimensionId, packet); + } + } - if (side == Side.SERVER) - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(8); - DataOutputStream outputStream = new DataOutputStream(bos); + @Override + public boolean canAttachToSide(int side) + { + return true; + } - try - { - // Write source vector - outputStream.writeInt(xCoord); - outputStream.writeInt(yCoord); - outputStream.writeInt(zCoord); - outputStream.writeInt(this.frequency); - } - catch (Exception ex) - { - ex.printStackTrace(); - } + @Override + public void attach(IComputerAccess computer) + { + } - Packet250CustomPayload packet = new Packet250CustomPayload(); - packet.channel = "WarpDriveFreq"; - packet.data = bos.toByteArray(); - packet.length = bos.size(); - MinecraftServer.getServer().getConfigurationManager().sendToAllNear(xCoord, yCoord, zCoord, 100, worldObj.provider.dimensionId, packet); - } - } - - @Override - public boolean canAttachToSide(int side) - { - return true; - } - - @Override - public void attach(IComputerAccess computer) - { - } - - @Override - public void detach(IComputerAccess computer) - { - } + @Override + public void detach(IComputerAccess computer) + { + } } diff --git a/src/cr0s/WarpDrive/TileEntityRadar.java b/src/cr0s/WarpDrive/TileEntityRadar.java index 3b04ea9b..5a1ae375 100644 --- a/src/cr0s/WarpDrive/TileEntityRadar.java +++ b/src/cr0s/WarpDrive/TileEntityRadar.java @@ -24,261 +24,236 @@ import net.minecraftforge.common.MinecraftForge; public class TileEntityRadar extends TileEntity implements IPeripheral, IEnergySink { - public boolean addedToEnergyNet = false; + public boolean addedToEnergyNet = false; - private final int MAX_ENERGY_VALUE = 100 * (1000 * 1000); // 100 000 000 Eu - private int currentEnergyValue = 0; + private final int MAX_ENERGY_VALUE = 100 * (1000 * 1000); // 100 000 000 Eu + private int currentEnergyValue = 0; - private String[] methodsArray = - { - "scanRay", // 0 - "scanRadiusW", // 1 - "getResultsCountW", // 2 - "getResultW", // 3 - "getEnergyLevel", // 4 + private String[] methodsArray = + { + "scanRay", // 0 + "scanRadius", // 1 + "getResultsCount", // 2 + "getResult", // 3 + "getEnergyLevel", // 4 + "pos" // 5 + }; - "getRadarX", "getRadarY", "getRadarZ", // 5, 6, 7 - }; + private ArrayList<TileEntityReactor> results; - private ArrayList<TileEntityReactor> results; + private int scanRadius = 0; + private int cooldownTime = 0; - private int scanRadius = 0; - private int cooldownTime = 0; + private boolean isEnergyEnoughForScanRadiusW(int radius) + { + int needEnergy = (radius * radius); + return ((getCurrentEnergyValue() - needEnergy) > 0); + } - private boolean isEnergyEnoughForScanRadiusW(int radius) - { - int needEnergy = (radius * radius); - return ((getCurrentEnergyValue() - needEnergy) > 0); - } + @Override + public void updateEntity() + { + if (!addedToEnergyNet && !this.tileEntityInvalid) + { + MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this)); + addedToEnergyNet = true; + } - @Override - public void updateEntity() - { - if (!addedToEnergyNet && !this.tileEntityInvalid) - { - MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this)); - addedToEnergyNet = true; - } + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + return; + } - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) - { - return; - } + try + { + if (worldObj.getBlockMetadata(xCoord, yCoord, zCoord) == 2) + { + if (cooldownTime++ > (20 * ((scanRadius / 1000) + 1))) + { + //System.out.println("Scanning..."); + WarpDrive.instance.registry.removeDeadCores(); + results = WarpDrive.instance.registry.searchWarpCoresInRadius(xCoord, yCoord, zCoord, scanRadius); + worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1, 1 + 2); + cooldownTime = 0; + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } - try - { - if (worldObj.getBlockMetadata(xCoord, yCoord, zCoord) == 2) - { - if (cooldownTime++ > (20 * ((scanRadius / 1000) + 1))) - { - //System.out.println("Scanning..."); - WarpDrive.instance.registry.removeDeadCores(); - results = WarpDrive.instance.registry.searchWarpCoresInRadius(xCoord, yCoord, zCoord, scanRadius); - worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1, 1 + 2); - cooldownTime = 0; - } - } - } - catch (Exception e) - { - e.printStackTrace(); - } - } + @Override + public void readFromNBT(NBTTagCompound tag) + { + super.readFromNBT(tag); + this.currentEnergyValue = tag.getInteger("energy"); + } - @Override - public void readFromNBT(NBTTagCompound tag) - { - super.readFromNBT(tag); - this.currentEnergyValue = tag.getInteger("energy"); - } + @Override + public void writeToNBT(NBTTagCompound tag) + { + super.writeToNBT(tag); + tag.setInteger("energy", this.getCurrentEnergyValue()); + } - @Override - public void writeToNBT(NBTTagCompound tag) - { - super.writeToNBT(tag); - tag.setInteger("energy", this.getCurrentEnergyValue()); - } + // IPeripheral methods implementation + @Override + public String getType() + { + return "radar"; + } - // IPeripheral methods implementation - @Override - public String getType() - { - return "radar"; - } + @Override + public String[] getMethodNames() + { + return methodsArray; + } - @Override - public String[] getMethodNames() - { - return methodsArray; - } + @Override + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception + { + switch (method) + { + case 0: // scanRay (toX, toY, toZ) + return new Object[] { -1 }; + case 1: // scanRadius (radius) + if (arguments.length == 1) + { + int radius = ((Double)arguments[0]).intValue(); + if (radius <= 0 || radius > 10000) + { + scanRadius = 0; + return new Boolean[] { false }; + } + if (radius != 0 && isEnergyEnoughForScanRadiusW(radius)) + { + // Consume energy + this.currentEnergyValue -= radius * radius; + // Begin searching + scanRadius = radius; + cooldownTime = 0; + worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 2, 1 + 2); + } + else + { + results = null; + System.out.println("Radius: " + radius + " | Enough energy: " + isEnergyEnoughForScanRadiusW(radius)); + return new Boolean[] { false }; + } + } + else + return new Boolean[] { false }; + return new Boolean[] { true }; - @Override - public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception - { - switch (method) - { - case 0: // scanRay (toX, toY, toZ) - return new Object[] { -1 }; - case 1: // scanRadiusW (radius) - if (arguments.length == 1) - { - int radius; + case 2: // getResultsCount + if (results != null) + return new Integer[] { results.size() }; + return new Integer[] { 0 }; + case 3: // getResult + if (arguments.length == 1 && (results != null)) + { + int index = ((Double)arguments[0]).intValue(); + if (index > -1 && index < results.size()) + { + TileEntityReactor res = results.get(index); + if (res != null) + { + int yAddition = (res.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID) ? 256 : (res.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) ? 512 : 0; + return new Object[] { (String)res.coreFrequency, (Integer)res.xCoord, (Integer)res.yCoord + yAddition, (Integer)res.zCoord }; + } + } + } + return new Object[] { (String)"FAIL", 0, 0, 0 }; + case 4: // getEnergyLevel + return new Integer[] { getCurrentEnergyValue() }; + case 5: // Pos + return new Integer[] { xCoord, yCoord, zCoord }; + } - try - { - radius = ((Double)arguments[0]).intValue(); - } - catch (Exception e) - { - radius = 0; - } + return null; + } - if (radius < 0 || radius > 10000) - { - scanRadius = 0; - return new Object[] { 0 }; - } + @Override + public boolean canAttachToSide(int side) + { + return true; + } - if (radius != 0 && isEnergyEnoughForScanRadiusW(radius)) - { - // Consume energy - this.currentEnergyValue -= radius * radius; - // Begin searching - scanRadius = radius; - cooldownTime = 0; - worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 2, 1 + 2); - } - else - { - results = null; - System.out.println("Radius: " + radius + " | Enough energy: " + isEnergyEnoughForScanRadiusW(radius)); - } - } + @Override + public void attach(IComputerAccess computer) + { + worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1, 1 + 2); + } - return new Object[] { 0 }; + @Override + public void detach(IComputerAccess computer) + { + worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 1 + 2); + } - case 2: // getResultsCountW - if (results != null) - { - return new Integer[] { results.size() }; - } + // IEnergySink methods implementation + @Override + public double demandedEnergyUnits() + { + return (MAX_ENERGY_VALUE - currentEnergyValue); + } - break; + @Override + public double injectEnergyUnits(ForgeDirection directionFrom, double amount) + { + double leftover = 0; + currentEnergyValue += Math.round(amount); - case 3: // getResultW - if (arguments.length == 1 && (results != null)) - { - int index; + if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) + { + leftover = (getCurrentEnergyValue() - MAX_ENERGY_VALUE); + currentEnergyValue = MAX_ENERGY_VALUE; + } - try - { - index = ((Double)arguments[0]).intValue(); - } - catch (Exception e) - { - index = -1; - } + return leftover; + } - if (index > -1 && index < results.size()) - { - TileEntityReactor res = results.get(index); - int yAddition = (res.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID) ? 255 : (res.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) ? 512 : 0; - return new Object[] { ((String)res.coreFrequency), ((Integer)res.xCoord), ((Integer)res.yCoord + yAddition), ((Integer)res.zCoord) }; - } - } + @Override + public int getMaxSafeInput() + { + return Integer.MAX_VALUE; + } - case 4: // getEnergyLevel - return new Integer[] { this.getCurrentEnergyValue()}; - case 5: // getRadarX - return new Integer[] { this.xCoord }; - case 6: // getRadarY - return new Integer[] { this.yCoord }; - case 7: // getRadarZ - return new Integer[] { this.zCoord }; - } + @Override + public boolean acceptsEnergyFrom(TileEntity emitter, ForgeDirection direction) + { + return true; + } - return new Object[] { 0 }; - } + /** + * @return the currentEnergyValue + */ + public int getCurrentEnergyValue() + { + return currentEnergyValue; + } - @Override - public boolean canAttachToSide(int side) - { - return true; - } + @Override + public void onChunkUnload() + { + if (addedToEnergyNet) + { + MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); + addedToEnergyNet = false; + } + } - @Override - public void attach(IComputerAccess computer) - { - worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1, 1 + 2); - } + @Override + public void invalidate() + { + if (addedToEnergyNet) + { + MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); + addedToEnergyNet = false; + } - @Override - public void detach(IComputerAccess computer) - { - worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 1 + 2); - } - - // IEnergySink methods implementation - @Override - public double demandedEnergyUnits() - { - return (MAX_ENERGY_VALUE - currentEnergyValue); - } - - @Override - public double injectEnergyUnits(ForgeDirection directionFrom, double amount) - { - double leftover = 0; - currentEnergyValue += Math.round(amount); - - if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) - { - leftover = (getCurrentEnergyValue() - MAX_ENERGY_VALUE); - currentEnergyValue = MAX_ENERGY_VALUE; - } - - return leftover; - } - - @Override - public int getMaxSafeInput() - { - return Integer.MAX_VALUE; - } - - @Override - public boolean acceptsEnergyFrom(TileEntity emitter, ForgeDirection direction) - { - return true; - } - - /** - * @return the currentEnergyValue - */ - public int getCurrentEnergyValue() - { - return currentEnergyValue; - } - - @Override - public void onChunkUnload() - { - if (addedToEnergyNet) - { - MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); - addedToEnergyNet = false; - } - } - - @Override - public void invalidate() - { - if (addedToEnergyNet) - { - MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); - addedToEnergyNet = false; - } - - super.invalidate(); - } + super.invalidate(); + } } diff --git a/src/cr0s/WarpDrive/TileEntityReactor.java b/src/cr0s/WarpDrive/TileEntityReactor.java index c844ca15..29cb02d7 100644 --- a/src/cr0s/WarpDrive/TileEntityReactor.java +++ b/src/cr0s/WarpDrive/TileEntityReactor.java @@ -297,7 +297,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { for (int z = zmin; z <= zmax; z++) { - if (worldObj.getBlockId(x, y, z) == WarpDrive.instance.config.isolationID) + if (worldObj.getBlockId(x, y, z) == WarpDriveConfig.i.isolationID) { this.isolationBlocksCount++; } @@ -1170,6 +1170,11 @@ public class TileEntityReactor extends TileEntity implements IEnergySink { super.validate(); WarpDrive.instance.registry.updateInRegistry(this); + if (!addedToEnergyNet) + { + MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this)); + addedToEnergyNet = true; + } } @Override diff --git a/src/cr0s/WarpDrive/WarpCoresRegistry.java b/src/cr0s/WarpDrive/WarpCoresRegistry.java index 62505d28..e0ffa18c 100644 --- a/src/cr0s/WarpDrive/WarpCoresRegistry.java +++ b/src/cr0s/WarpDrive/WarpCoresRegistry.java @@ -168,7 +168,7 @@ public class WarpCoresRegistry ArrayList<TileEntityReactor> oldRegistry = (ArrayList<TileEntityReactor>) registry.clone(); for (TileEntityReactor c : registry) - if (c == null || c.worldObj == null || c.worldObj.getBlockId(c.xCoord, c.yCoord, c.zCoord) != WarpDrive.instance.config.coreID || c.worldObj.getBlockTileEntity(c.xCoord, c.yCoord, c.zCoord) != c || c.worldObj.getBlockTileEntity(c.xCoord, c.yCoord, c.zCoord).isInvalid()) + if (c == null || c.worldObj == null || c.worldObj.getBlockId(c.xCoord, c.yCoord, c.zCoord) != WarpDriveConfig.i.coreID || c.worldObj.getBlockTileEntity(c.xCoord, c.yCoord, c.zCoord) != c || c.worldObj.getBlockTileEntity(c.xCoord, c.yCoord, c.zCoord).isInvalid()) oldRegistry.remove(c); // Update old registry to new witout dead cores diff --git a/src/cr0s/WarpDrive/WarpDrive.java b/src/cr0s/WarpDrive/WarpDrive.java index 973cbbf9..474feb53 100644 --- a/src/cr0s/WarpDrive/WarpDrive.java +++ b/src/cr0s/WarpDrive/WarpDrive.java @@ -16,7 +16,6 @@ import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.common.network.NetworkMod; import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.common.registry.LanguageRegistry; -import ic2.api.item.Items; import java.util.List; @@ -35,7 +34,7 @@ import net.minecraftforge.common.ForgeChunkManager.LoadingCallback; import net.minecraftforge.common.ForgeChunkManager.Ticket; import net.minecraftforge.common.MinecraftForge; -@Mod(modid = "WarpDrive", name = "WarpDrive", version = "1.0.5") +@Mod(modid = "WarpDrive", name = "WarpDrive", version = "1.1.5_ZLO", dependencies="required-after:IC2; required-after:ComputerCraft; after:CCTurtle; after:gregtech_addon; after:AppliedEnergistics; after:AdvancedSolarPanel; after:AtomicScience; after:ICBM|Explosion; after:MFFS; after:GraviSuite") @NetworkMod(clientSideRequired = true, serverSideRequired = true, channels = {"WarpDriveBeam", "WarpDriveFreq", "WarpDriveLaserT"}, packetHandler = PacketHandler.class) /** * @author Cr0s @@ -86,14 +85,11 @@ public class WarpDrive implements LoadingCallback public boolean isOverlayEnabled = false; public int overlayType = 0; - public WarpDriveConfig config; - @EventHandler //@PreInit public void preInit(FMLPreInitializationEvent event) { - this.config = new WarpDriveConfig(new Configuration(event.getSuggestedConfigurationFile())); - this.config.loadAndSave(); + WarpDriveConfig.Init(new Configuration(event.getSuggestedConfigurationFile())); if (FMLCommonHandler.instance().getSide().isClient()) { @@ -106,97 +102,97 @@ public class WarpDrive implements LoadingCallback public void load(FMLInitializationEvent event) { // WARP CORE - this.warpCore = new BlockReactor(this.config.coreID, 0, Material.rock) + this.warpCore = new BlockReactor(WarpDriveConfig.i.coreID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Warp Core"); LanguageRegistry.addName(warpCore, "Warp Core"); GameRegistry.registerBlock(warpCore, "warpCore"); GameRegistry.registerTileEntity(TileEntityReactor.class, "warpCore"); // CORE CONTROLLER - this.protocolBlock = new BlockProtocol(config.controllerID, 0, Material.rock) + this.protocolBlock = new BlockProtocol(WarpDriveConfig.i.controllerID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Warp Controller"); LanguageRegistry.addName(protocolBlock, "Warp Controller"); GameRegistry.registerBlock(protocolBlock, "protocolBlock"); GameRegistry.registerTileEntity(TileEntityProtocol.class, "protocolBlock"); // WARP RADAR - this.radarBlock = new BlockRadar(config.radarID, 0, Material.rock) + this.radarBlock = new BlockRadar(WarpDriveConfig.i.radarID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("W-Radar"); LanguageRegistry.addName(radarBlock, "W-Radar"); GameRegistry.registerBlock(radarBlock, "radarBlock"); GameRegistry.registerTileEntity(TileEntityRadar.class, "radarBlock"); // WARP ISOLATION - this.isolationBlock = new BlockWarpIsolation(config.isolationID, 0, Material.rock) + this.isolationBlock = new BlockWarpIsolation(WarpDriveConfig.i.isolationID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Warp-Field Isolation Block"); LanguageRegistry.addName(isolationBlock, "Warp-Field Isolation Block"); GameRegistry.registerBlock(isolationBlock, "isolationBlock"); // AIR GENERATOR - this.airgenBlock = new BlockAirGenerator(config.airgenID, 0, Material.rock) + this.airgenBlock = new BlockAirGenerator(WarpDriveConfig.i.airgenID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Air Generator"); LanguageRegistry.addName(airgenBlock, "Air Generator"); GameRegistry.registerBlock(airgenBlock, "airgenBlock"); GameRegistry.registerTileEntity(TileEntityAirGenerator.class, "airgenBlock"); // AIR BLOCK - this.airBlock = (new BlockAir(config.airID)).setHardness(0.0F).setUnlocalizedName("Air block"); + this.airBlock = (new BlockAir(WarpDriveConfig.i.airID)).setHardness(0.0F).setUnlocalizedName("Air block"); LanguageRegistry.addName(airBlock, "Air block"); GameRegistry.registerBlock(airBlock, "airBlock"); // GAS BLOCK - this.gasBlock = (new BlockGas(config.gasID)).setHardness(0.0F).setUnlocalizedName("Gas block"); + this.gasBlock = (new BlockGas(WarpDriveConfig.i.gasID)).setHardness(0.0F).setUnlocalizedName("Gas block"); LanguageRegistry.addName(gasBlock, "Gas block"); GameRegistry.registerBlock(gasBlock, "gasBlock"); // LASER EMITTER - this.laserBlock = new BlockLaser(config.laserID, 0, Material.rock) + this.laserBlock = new BlockLaser(WarpDriveConfig.i.laserID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser Emitter"); LanguageRegistry.addName(laserBlock, "Laser Emitter"); GameRegistry.registerBlock(laserBlock, "laserBlock"); GameRegistry.registerTileEntity(TileEntityLaser.class, "laserBlock"); // LASER EMITTER WITH CAMERA - this.laserCamBlock = new BlockLaserCam(config.laserCamID, 0, Material.rock) + this.laserCamBlock = new BlockLaserCam(WarpDriveConfig.i.laserCamID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser Emitter + Camera"); LanguageRegistry.addName(laserCamBlock, "Laser Emitter + Camera"); GameRegistry.registerBlock(laserCamBlock, "laserCamBlock"); // CAMERA - this.cameraBlock = new BlockCamera(config.camID, 0, Material.rock) + this.cameraBlock = new BlockCamera(WarpDriveConfig.i.camID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Camera block"); LanguageRegistry.addName(cameraBlock, "Camera"); GameRegistry.registerBlock(cameraBlock, "cameraBlock"); GameRegistry.registerTileEntity(TileEntityCamera.class, "cameraBlock"); // MONITOR - this.monitorBlock = new BlockMonitor(config.monitorID) + this.monitorBlock = new BlockMonitor(WarpDriveConfig.i.monitorID) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Monitor"); LanguageRegistry.addName(monitorBlock, "Monitor"); GameRegistry.registerBlock(monitorBlock, "monitorBlock"); GameRegistry.registerTileEntity(TileEntityMonitor.class, "monitorBlock"); // MINING LASER - this.miningLaserBlock = new BlockMiningLaser(config.miningLaserID, 0, Material.rock) + this.miningLaserBlock = new BlockMiningLaser(WarpDriveConfig.i.miningLaserID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Mining Laser"); LanguageRegistry.addName(miningLaserBlock, "Mining Laser"); GameRegistry.registerBlock(miningLaserBlock, "miningLaserBlock"); GameRegistry.registerTileEntity(TileEntityMiningLaser.class, "miningLaserBlock"); // PARTICLE BOOSTER - this.boosterBlock = new BlockParticleBooster(config.particleBoosterID, 0, Material.rock) + this.boosterBlock = new BlockParticleBooster(WarpDriveConfig.i.particleBoosterID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Particle Booster"); LanguageRegistry.addName(boosterBlock, "Particle Booster"); GameRegistry.registerBlock(boosterBlock, "boosterBlock"); GameRegistry.registerTileEntity(TileEntityParticleBooster.class, "boosterBlock"); // RAY LIFT - this.liftBlock = new BlockLift(config.liftID, 0, Material.rock) + this.liftBlock = new BlockLift(WarpDriveConfig.i.liftID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser lift"); LanguageRegistry.addName(liftBlock, "Laser lift"); GameRegistry.registerBlock(liftBlock, "liftBlock"); GameRegistry.registerTileEntity(TileEntityLift.class, "liftBlock"); // IRIDIUM BLOCK - this.iridiumBlock = new BlockIridium(config.iridiumID) + this.iridiumBlock = new BlockIridium(WarpDriveConfig.i.iridiumID) .setHardness(0.8F).setResistance(150 * 4).setStepSound(Block.soundMetalFootstep) .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Block of Iridium"); LanguageRegistry.addName(iridiumBlock, "Block of Iridium"); @@ -223,36 +219,36 @@ public class WarpDrive implements LoadingCallback space = DimensionManager.getWorld(spaceDimID); hyperSpace = DimensionManager.getWorld(hyperSpaceDimID); GameRegistry.addRecipe(new ItemStack(warpCore), "ici", "cmc", "ici", - 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit")); + 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit")); GameRegistry.addRecipe(new ItemStack(protocolBlock), "iic", "imi", "cii", - 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit")); + 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit")); GameRegistry.addRecipe(new ItemStack(radarBlock), "ifi", "imi", "imi", - 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'f', Items.getItem("frequencyTransmitter")); + 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'f', WarpDriveConfig.i.getIC2Item("frequencyTransmitter")); GameRegistry.addRecipe(new ItemStack(isolationBlock), "iii", "idi", "iii", - 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'd', Block.blockDiamond); + 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'd', Block.blockDiamond); GameRegistry.addRecipe(new ItemStack(airgenBlock), "lcl", "lml", "lll", - 'l', Block.leaves, 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit")); + 'l', Block.leaves, 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit")); GameRegistry.addRecipe(new ItemStack(laserBlock), "sss", "ama", "aaa", - 'm', Items.getItem("advancedMachine"), 'a', Items.getItem("advancedAlloy"), 's', Items.getItem("advancedCircuit")); + 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy"), 's', WarpDriveConfig.i.getIC2Item("advancedCircuit")); GameRegistry.addRecipe(new ItemStack(miningLaserBlock), "aaa", "ama", "ccc", - 'c', Items.getItem("advancedCircuit"), 'a', Items.getItem("advancedAlloy"), 'm', Items.getItem("miner")); + 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy"), 'm', WarpDriveConfig.i.getIC2Item("miner")); GameRegistry.addRecipe(new ItemStack(boosterBlock), "afc", "ama", "cfa", - 'c', Items.getItem("advancedCircuit"), 'a', Items.getItem("advancedAlloy"), 'f', Items.getItem("glassFiberCableItem"), 'm', Items.getItem("mfeUnit")); + 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy"), 'f', WarpDriveConfig.i.getIC2Item("glassFiberCableItem"), 'm', WarpDriveConfig.i.getIC2Item("mfeUnit")); GameRegistry.addRecipe(new ItemStack(liftBlock), "aca", "ama", "a#a", - 'c', Items.getItem("advancedCircuit"), 'a', Items.getItem("advancedAlloy"), 'm', Items.getItem("magnetizer")); + 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy"), 'm', WarpDriveConfig.i.getIC2Item("magnetizer")); /* GameRegistry.addRecipe(new ItemStack(Item.enderPearl), "uuu", "uuu", "uuu", - 'u', Items.getItem("uraniumDrop")); + 'u', WarpDriveConfig.i.getIC2Item("uraniumDrop")); */ GameRegistry.addRecipe(new ItemStack(iridiumBlock), "iii", "iii", "iii", - 'i', Items.getItem("iridiumPlate")); - GameRegistry.addShapelessRecipe(new ItemStack(Items.getItem("iridiumPlate").getItem(), 9), new ItemStack(iridiumBlock)); + 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate")); + GameRegistry.addShapelessRecipe(new ItemStack(WarpDriveConfig.i.getIC2Item("iridiumPlate").getItem(), 9), new ItemStack(iridiumBlock)); GameRegistry.addRecipe(new ItemStack(laserCamBlock), "imi", "cec", "#k#", - 'i', Items.getItem("iridiumPlate"), 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit"), 'e', laserBlock, 'k', cameraBlock); + 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'e', laserBlock, 'k', cameraBlock); GameRegistry.addRecipe(new ItemStack(cameraBlock), "cgc", "gmg", "cgc", - 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit"), 'g', Block.glass); + 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'g', Block.glass); GameRegistry.addRecipe(new ItemStack(monitorBlock), "gcg", "gmg", "ggg", - 'm', Items.getItem("advancedMachine"), 'c', Items.getItem("advancedCircuit"), 'g', Block.glass); + 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'g', Block.glass); registry = new WarpCoresRegistry(); if (FMLCommonHandler.instance().getEffectiveSide().isServer()) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index f57a01e5..4ebc246e 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -1,63 +1,439 @@ package cr0s.WarpDrive; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.HashSet; import java.util.Set; - +import java.util.Random; +import java.lang.reflect.*; +import cpw.mods.fml.common.Loader; import net.minecraftforge.common.Configuration; +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import ic2.api.item.Items; public class WarpDriveConfig { - private Configuration config; + public static WarpDriveConfig i; + private Configuration config; + public int coreID, controllerID, radarID, isolationID, airID, airgenID, gasID, laserID, miningLaserID, particleBoosterID, liftID, laserCamID, camID, monitorID, iridiumID; +// + public boolean isGregLoaded = false, isAELoaded = false, isAdvSolPanelLoaded = false, isASLoaded = false, isICBMLoaded = false, isMFFSLoaded = false, isGraviSuiteLoaded = false; +// + public int IC2_Air = 0, CC_Computer = 0, CC_peripheral = 0, CCT_Turtle = 0, CCT_Upgraded = 0, CCT_Advanced = 0, GT_Ores = 0, GT_Granite = 0, GT_Machine = 0, ASP = 0, AS_Turbine = 0, ICBM_Machine = 0, ICBM_Missile = 0, MFFS_Field = 0; + public Set<Integer> SpaceHelmets, Jetpacks, MinerOres; + private Class<?> AEBlocks; + private Class<?> AEMaterials; + private Class<?> AEItems; + public ArrayList<int[]> CommonWorldGenOres; - public Set<Integer> valuableOres; - public Set<Integer> minerValuables; + private WarpDriveConfig() {} - public int coreID, controllerID, radarID, isolationID, airID, airgenID, gasID, laserID, miningLaserID, particleBoosterID, liftID, laserCamID, camID, monitorID, iridiumID; - /* - * public final static int WARP_CORE_BLOCKID = 500; - public final static int PROTOCOL_BLOCK_BLOCKID = 501; - public final static int RADAR_BLOCK_BLOCKID = 502; - public final static int ISOLATION_BLOCKID = 503; - public final static int AIR_BLOCKID = 504; - public final static int AIRGEN_BLOCKID = 505; - public final static int GAS_BLOCKID = 506; + public ItemStack getIC2Item(String id) + { + return Items.getItem(id); + } - public final static int LASER_BLOCK_BLOCKID = 507; - public final static int MINING_LASER_BLOCK_BLOCKID = 508; - public final static int PARTICLE_BOOSTER_BLOCKID = 509; - public final static int LIFT_BLOCKID = 510; + public ItemStack getAEBlock(String id) + { + try + { + Object ret = AEBlocks.getField(id).get(null); + if (ret instanceof ItemStack) + return (ItemStack)ret; + } + catch (Exception e) + { + System.out.println("WarpDriveConfig Call getAEBlock failed for " + id); + } + return null; + } - public final static int LASER_BLOCKCAM_BLOCKID = 512; - public final static int CAMERA_BLOCKID = 513; - public final static int MONITOR_BLOCKID = 514; + public ItemStack getAEMaterial(String id) + { + try + { + Object ret = AEMaterials.getField(id).get(null); + if (ret instanceof ItemStack) + return (ItemStack)ret; + } + catch (Exception e) + { + System.out.println("WarpDriveConfig Call getAEMaterial failed for " + id); + } + return null; + } - public final static int IRIDIUM_BLOCKID = 515; - */ - public WarpDriveConfig(Configuration config) - { - this.config = config; - this.valuableOres = new HashSet<Integer>(); - this.minerValuables = new HashSet<Integer>(); - } + public ItemStack getAEItem(String id) + { + try + { + Object ret = AEItems.getField(id).get(null); + if (ret instanceof ItemStack) + return (ItemStack)ret; + } + catch (Exception e) + { + System.out.println("WarpDriveConfig Call getAEItem failed for " + id); + } + return null; + } - public void loadAndSave() - { - this.config.load(); - this.coreID = this.config.getBlock("core", 500).getInt(); - this.controllerID = this.config.getBlock("controller", 501).getInt(); - this.radarID = this.config.getBlock("radar", 502).getInt(); - this.isolationID = this.config.getBlock("isolation", 503).getInt(); - this.airID = this.config.getBlock("air", 504).getInt(); - this.airgenID = this.config.getBlock("airgen", 505).getInt(); - this.gasID = this.config.getBlock("gas", 506).getInt(); - this.laserID = this.config.getBlock("laser", 507).getInt(); - this.miningLaserID = this.config.getBlock("mininglaser", 508).getInt(); - this.particleBoosterID = this.config.getBlock("particlebooster", 509).getInt(); - this.liftID = this.config.getBlock("lift", 510).getInt(); - this.laserCamID = this.config.getBlock("lasercam", 512).getInt(); - this.camID = this.config.getBlock("camera", 513).getInt(); - this.monitorID = this.config.getBlock("monitor", 514).getInt(); - this.iridiumID = this.config.getBlock("iridium", 515).getInt(); - this.config.save(); - } + public static void Init(Configuration config) + { + if (i == null) + i = new WarpDriveConfig(); + i.config = config; + i.Init2(); + } + + private void Init2() + { + CommonWorldGenOres = new ArrayList<int[]>(); + CommonWorldGenOres.add(new int[] {Block.oreIron.blockID, 0}); + CommonWorldGenOres.add(new int[] {Block.oreGold.blockID, 0}); + CommonWorldGenOres.add(new int[] {Block.oreCoal.blockID, 0}); + CommonWorldGenOres.add(new int[] {Block.oreEmerald.blockID, 0}); + CommonWorldGenOres.add(new int[] {Block.oreLapis.blockID, 0}); + CommonWorldGenOres.add(new int[] {Block.oreRedstoneGlowing.blockID, 0}); + CommonWorldGenOres.add(new int[] {Block.oreRedstone.blockID, 0}); +// + SpaceHelmets = new HashSet<Integer>(); + Jetpacks = new HashSet<Integer>(); + MinerOres = new HashSet<Integer>(); + config.load(); + coreID = config.getBlock("core", 500).getInt(); + controllerID = config.getBlock("controller", 501).getInt(); + radarID = config.getBlock("radar", 502).getInt(); + isolationID = config.getBlock("isolation", 503).getInt(); + airID = config.getBlock("air", 504).getInt(); + airgenID = config.getBlock("airgen", 505).getInt(); + gasID = config.getBlock("gas", 506).getInt(); + laserID = config.getBlock("laser", 507).getInt(); + miningLaserID = config.getBlock("mininglaser", 508).getInt(); + particleBoosterID = config.getBlock("particlebooster", 509).getInt(); + liftID = config.getBlock("lift", 510).getInt(); + laserCamID = config.getBlock("lasercam", 512).getInt(); + camID = config.getBlock("camera", 513).getInt(); + monitorID = config.getBlock("monitor", 514).getInt(); + iridiumID = config.getBlock("iridium", 515).getInt(); + config.save(); + LoadIC2(); + LoadCC(); + isGregLoaded = Loader.isModLoaded("gregtech_addon"); + if (isGregLoaded) + LoadGT(); + isAELoaded = Loader.isModLoaded("AppliedEnergistics"); + if (isAELoaded) + LoadAE(); + isAdvSolPanelLoaded = Loader.isModLoaded("AdvancedSolarPanel"); + if (isAdvSolPanelLoaded) + LoadASP(); + isASLoaded = Loader.isModLoaded("AtomicScience"); + if (isASLoaded) + LoadAS(); + isICBMLoaded = Loader.isModLoaded("ICBM|Explosion"); + if (isICBMLoaded) + LoadICBM(); + isMFFSLoaded = Loader.isModLoaded("MFFS"); + if (isMFFSLoaded) + LoadMFFS(); + isGraviSuiteLoaded = Loader.isModLoaded("GraviSuite"); + if (isGraviSuiteLoaded) + LoadGS(); +// + MinerOres.add(iridiumID); + MinerOres.add(Block.oreNetherQuartz.blockID); + for (int[] t : CommonWorldGenOres) + MinerOres.add(t[0]); + MinerOres.add(Block.wood.blockID); + MinerOres.add(Block.planks.blockID); + MinerOres.add(Block.rail.blockID); + MinerOres.add(Block.oreDiamond.blockID); + MinerOres.add(Block.obsidian.blockID); + MinerOres.add(Block.web.blockID); + MinerOres.add(Block.fence.blockID); + MinerOres.add(Block.torchWood.blockID); + } + + private void LoadIC2() + { + ASP = Items.getItem("solarPanel").itemID; + SpaceHelmets.add(Items.getItem("hazmatHelmet").itemID); + SpaceHelmets.add(Items.getItem("quantumHelmet").itemID); + Jetpacks.add(Items.getItem("jetpack").itemID); + Jetpacks.add(Items.getItem("electricJetpack").itemID); + IC2_Air = Items.getItem("airCell").itemID; + CommonWorldGenOres.add(new int[] {Items.getItem("uraniumOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); + CommonWorldGenOres.add(new int[] {Items.getItem("copperOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); + CommonWorldGenOres.add(new int[] {Items.getItem("tinOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); + MinerOres.add(Items.getItem("rubberWood").itemID); + } + + private void LoadCC() + { + try + { + Class<?> z = Class.forName("dan200.ComputerCraft"); + CC_Computer = z.getField("computerBlockID").getInt(null); + CC_peripheral = z.getField("peripheralBlockID").getInt(null); + z = Class.forName("dan200.CCTurtle"); + CCT_Turtle = z.getField("turtleBlockID").getInt(null); + CCT_Upgraded = z.getField("turtleUpgradedBlockID").getInt(null); + CCT_Advanced = z.getField("turtleAdvancedBlockID").getInt(null); + } + catch (Exception e) + { + System.out.println("WarpDriveConfig Error loading CC classes AWWW SHEEEEET NIGGA"); + } + } + + private void LoadGT() + { + try + { + Class<?> z = Class.forName("gregtechmod.api.GregTech_API"); + GT_Machine = ((int[])z.getField("sBlockIDs").get(null))[1]; + GT_Ores = ((int[])z.getField("sBlockIDs").get(null))[2]; // meta 1-15 = ores + GT_Granite = ((int[])z.getField("sBlockIDs").get(null))[5]; // 0 - black, 1 - black cobble, 8 - red, 9 - red cobble + MinerOres.add(GT_Ores); + } + catch (Exception e) + { + System.out.println("WarpDriveConfig Error loading GT classes"); + isGregLoaded = false; + } + } + + private void LoadAE() + { + try + { + AEBlocks = Class.forName("appeng.api.Blocks"); + AEMaterials = Class.forName("appeng.api.Materials"); + AEItems = Class.forName("appeng.api.Items"); + MinerOres.add(((ItemStack)AEBlocks.getField("blkQuartzOre").get(null)).itemID); + } + catch (Exception e) + { + System.out.println("WarpDriveConfig Error loading AE classes"); + isAELoaded = false; + } + } + + private void LoadASP() + { + try + { + Class<?> z = Class.forName("advsolar.common.AdvancedSolarPanel"); + ASP = z.getField("idAdv").getInt(null); + SpaceHelmets.add(z.getField("advSolarHelmetID").getInt(null)); + SpaceHelmets.add(z.getField("hybridSolarHelmetID").getInt(null)); + SpaceHelmets.add(z.getField("ultimateSolarHelmetID").getInt(null)); + } + catch (Exception e) + { + System.out.println("WarpDriveConfig Error loading ASP classes"); + isAdvSolPanelLoaded = false; + } + } + + private void LoadAS() + { + try + { + Class<?> z = Class.forName("atomicscience.ZhuYaoAS"); + CommonWorldGenOres.add(new int[] {((Block)z.getField("bHeOre").get(null)).blockID, 0}); + AS_Turbine = ((Block)z.getField("bWoLun").get(null)).blockID; + } + catch (Exception e) + { + System.out.println("WarpDriveConfig Error loading AS classes"); + isASLoaded = false; + } + } + + private void LoadICBM() + { + try + { + Class<?> z = Class.forName("icbm.core.ICBMCore"); + CommonWorldGenOres.add(new int[] {((Block)z.getField("blockSulfurOre").get(null)).blockID, 0}); + z = Class.forName("icbm.explosion.ICBMExplosion"); + ICBM_Machine = ((Block)z.getField("blockMachine").get(null)).blockID; + ICBM_Missile = ((Item)z.getField("itemMissile").get(null)).itemID; + } + catch (Exception e) + { + System.out.println("WarpDriveConfig Error loading ICBM classes"); + isICBMLoaded = false; + } + } + + private void LoadMFFS() + { + try + { + Class<?> z = Class.forName("mffs.ModularForceFieldSystem"); + MFFS_Field = ((Block)z.getField("blockForceField").get(null)).blockID; + } + catch (Exception e) + { + System.out.println("WarpDriveConfig Error loading MFFS classes"); + isICBMLoaded = false; + } + } + + private void LoadGS() + { + try + { + Class<?> z = Class.forName("gravisuite.GraviSuite"); + SpaceHelmets.add(z.getField("ultimateSolarHelmetID").getInt(null)); + } + catch (Exception e) + { + System.out.println("WarpDriveConfig Error loading GS classes"); + isGraviSuiteLoaded = false; + } + } + + public int[] getDefaultSurfaceBlock(Random random, boolean corrupted, boolean isMoon) + { + if (isMoon) + { + if (random.nextInt(100) == 1) + if (random.nextBoolean()) + return new int[] {GT_Granite, (corrupted && random.nextBoolean())?1:0}; + else + return new int[] {GT_Granite, (corrupted && random.nextBoolean())?9:8}; + else if (random.nextInt(666) == 1) + return new int[] {Block.netherrack.blockID, 0}; + else if (random.nextInt(1000) == 1) + return new int[] {Block.whiteStone.blockID, 0}; + } + else + { + if (random.nextInt(50) == 1) + if (random.nextBoolean()) + return new int[] {GT_Granite, (corrupted && random.nextBoolean())?1:0}; + else + return new int[] {GT_Granite, (corrupted && random.nextBoolean())?9:8}; + else if (random.nextInt(100) == 1) + return new int[] {Block.netherrack.blockID, 0}; + else if (random.nextInt(300) == 1) + return new int[] {Block.whiteStone.blockID, 0}; + } + if (corrupted && random.nextBoolean()) + return new int[] {Block.cobblestone.blockID, 0}; + return new int[] {Block.stone.blockID, 0}; + } + + public int[] getRandomSurfaceBlock(Random random, int blockID, int blockMeta, boolean bedrock) + { + if (bedrock && random.nextInt(1000) == 1) + return new int[] {Block.bedrock.blockID, 0}; + if (blockID == GT_Granite) + if (blockMeta == 0 || blockMeta == 1) + { + int[] t; + t = getRandomOverworldBlock(random, blockID, blockMeta); + if (t[0] == blockID) + t = getRandomOverworldBlock(random, blockID, blockMeta); + if (t[0] == blockID) + t = getRandomEndBlock(random, blockID, blockMeta); + return t; + } + else if (blockMeta == 8 || blockMeta == 9) + { + int[] t; + t = getRandomOverworldBlock(random, blockID, blockMeta); + if (t[0] == blockID) + t = getRandomEndBlock(random, blockID, blockMeta); + if (t[0] == blockID) + t = getRandomOverworldBlock(random, blockID, blockMeta); + return t; + } + else if (blockID == Block.whiteStone.blockID) + return getRandomEndBlock(random, blockID, blockMeta); + else if (blockID == Block.netherrack.blockID) + return getRandomNetherBlock(random, blockID, blockMeta); + return getRandomOverworldBlock(random, blockID, blockMeta); + } + + private int[] getRandomOverworldBlock(Random random, int blockID, int blockMeta) + { + if (random.nextInt(25) == 5) + return CommonWorldGenOres.get(random.nextInt(CommonWorldGenOres.size())); + else if (isAELoaded && random.nextInt(750) == 1) + return new int[] {getAEBlock("blkQuartzOre").itemID, getAEBlock("blkQuartzOre").getItemDamage()}; + else if (random.nextInt(250) == 1) + return new int[] {Block.oreDiamond.blockID, 0}; + else if (random.nextInt(10000) == 42) + return new int[] {iridiumID, 0}; + if (isGregLoaded) + { + if (random.nextInt(50) == 1) + return new int[] {GT_Ores, 5}; //Bauxite S /* Stone/Iron/Diamod pick | +S = Silktouch recommended */ + else if (random.nextInt(50) == 1) + return new int[] {GT_Ores, 1}; //Galena S + else if (random.nextInt(100) == 1) + return new int[] {GT_Ores, 8}; //Sphalerite S+S + else if (random.nextInt(250) == 1) + return new int[] {GT_Ores, 13}; //Tetrahedrite I + else if (random.nextInt(250) == 1) + return new int[] {GT_Ores, 14}; //Cassiterite I + else if (random.nextInt(250) == 1) + return new int[] {GT_Ores, 15}; //Nickel I + else if (random.nextInt(500) == 1) + return new int[] {GT_Ores, 3}; //Ruby I+S + else if (random.nextInt(500) == 1) + return new int[] {GT_Ores, 4}; //Sapphire I+S + else if (random.nextInt(2000) == 1) + return new int[] {GT_Ores, 2}; //Iridium D+S + } + return new int[] {blockID, blockMeta}; + } + + private int[] getRandomNetherBlock(Random random, int blockID, int blockMeta) + { + if (random.nextInt(500) == 1) + return new int[] {Block.oreNetherQuartz.blockID, 0}; + else if (random.nextInt(10000) == 42) + return new int[] {iridiumID, 0}; + else if (isGregLoaded) + { + if (random.nextInt(100) == 1) + return new int[] {GT_Ores, 6}; //Pyrite S+S + else if (random.nextInt(100) == 1) + return new int[] {GT_Ores, 8}; //Sphalerite S+S + else if (random.nextInt(500) == 1) + return new int[] {GT_Ores, 7}; //Cinnabar I+S + } + if (random.nextInt(100) == 13) + return CommonWorldGenOres.get(random.nextInt(CommonWorldGenOres.size())); + return new int[] {blockID, blockMeta}; + } + + private int[] getRandomEndBlock(Random random, int blockID, int blockMeta) + { + if (random.nextInt(10000) == 42) + return new int[] {iridiumID, 0}; + else if (isGregLoaded) + { + if (random.nextInt(250) == 1) + return new int[] {GT_Ores, 9}; //Tungstate I + else if (random.nextInt(500) == 1) + return new int[] {GT_Ores, 12}; //Sodalite I+S + else if (random.nextInt(500) == 1) + return new int[] {GT_Ores, 10}; //Cooperite=Sheldonite D + else if (random.nextInt(1000) == 1) + return new int[] {GT_Ores, 11}; //Olivine D+S + } + if (random.nextInt(200) == 13) + return CommonWorldGenOres.get(random.nextInt(CommonWorldGenOres.size())); + return new int[] {blockID, blockMeta}; + } } diff --git a/src/cr0s/WarpDrive/WorldGenSmallShip.java b/src/cr0s/WarpDrive/WorldGenSmallShip.java index 875f5374..43592fcc 100644 --- a/src/cr0s/WarpDrive/WorldGenSmallShip.java +++ b/src/cr0s/WarpDrive/WorldGenSmallShip.java @@ -1,7 +1,6 @@ package cr0s.WarpDrive; import cpw.mods.fml.common.Loader; -import ic2.api.item.Items; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.entity.monster.EntityZombie; @@ -14,696 +13,686 @@ import net.minecraft.world.gen.feature.WorldGenerator; public class WorldGenSmallShip extends WorldGenerator { - private boolean corrupted; - private boolean isICBMLoaded = false, isAELoaded = false, isAdvSolPanelLoaded = false; + private boolean corrupted; + private int solarType; - public WorldGenSmallShip(boolean corrupted) - { - this.corrupted = corrupted; - isICBMLoaded = Loader.isModLoaded("ICBM|Explosion"); - isAELoaded = Loader.isModLoaded("AppliedEnergistics"); - isAdvSolPanelLoaded = Loader.isModLoaded("AdvancedSolarPanel"); - } + public WorldGenSmallShip(boolean corrupted) + { + this.corrupted = corrupted; + solarType = WarpDriveConfig.i.getIC2Item("solarPanel").getItemDamage(); + } - @Override - public boolean generate(World world, Random rand, int i, int j, int k) - { - ItemStack cableType = Items.getItem("copperCableBlock").copy(); + @Override + public boolean generate(World world, Random rand, int i, int j, int k) + { + if (WarpDriveConfig.i.isAdvSolPanelLoaded) + solarType = rand.nextInt(2); - switch (rand.nextInt(4)) - { - case 0: - cableType = Items.getItem("glassFiberCableBlock").copy(); - break; + ItemStack cableType = WarpDriveConfig.i.getIC2Item("copperCableBlock").copy(); - case 1: - cableType = Items.getItem("glassFiberCableBlock").copy(); - break; + switch (rand.nextInt(4)) + { + case 0: + cableType = WarpDriveConfig.i.getIC2Item("glassFiberCableBlock").copy(); + break; - case 2: - cableType = Items.getItem("insulatedGoldCableBlock").copy(); - break; + case 1: + cableType = WarpDriveConfig.i.getIC2Item("glassFiberCableBlock").copy(); + break; - case 3: - cableType = Items.getItem("doubleInsulatedIronCableBlock").copy(); - break; - } + case 2: + cableType = WarpDriveConfig.i.getIC2Item("insulatedGoldCableBlock").copy(); + break; - int ADV_SOLAR_BLOCKID = 194; - int solarType = rand.nextInt(2); + case 3: + cableType = WarpDriveConfig.i.getIC2Item("doubleInsulatedIronCableBlock").copy(); + break; + } - if (!isAdvSolPanelLoaded) - { - ADV_SOLAR_BLOCKID = Items.getItem("solarPanel").itemID; - solarType = Items.getItem("solarPanel").getItemDamage(); - } + world.setBlock(i + 0, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 0, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 1, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 1, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 1, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 1, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 1, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 1, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 3, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 3, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 3, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 2, j + 4, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 2, j + 4, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 2, j + 4, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 2, j + 5, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 2, j + 5, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 2, j + 5, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 3, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 3, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 3, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 4, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 4, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 5, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 5, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 3, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 2, k + 5, Block.glowStone.blockID); + world.setBlock(i + 4, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 2, k + 9, Block.glowStone.blockID); + world.setBlock(i + 4, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 4, k + 4, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 4, j + 4, k + 10, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 4, j + 5, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 5, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 5, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 5, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 4, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 2, k + 4, Block.glowStone.blockID); + world.setBlock(i + 5, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 2, k + 7, Block.cloth.blockID, 14, 0); + world.setBlock(i + 5, j + 2, k + 8, Block.cloth.blockID, 8, 0); + world.setBlock(i + 5, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 2, k + 10, Block.glowStone.blockID); + world.setBlock(i + 5, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 3, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 3, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 4, k + 3, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 5, j + 4, k + 11, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 5, j + 5, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 5, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 5, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 5, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 5, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 2, k + 6, Block.cloth.blockID, 14, 0); + world.setBlock(i + 6, j + 2, k + 7, Block.cloth.blockID, 8, 0); + world.setBlock(i + 6, j + 2, k + 8, Block.cloth.blockID, 14, 0); + world.setBlock(i + 6, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 3, k + 3, Block.chest.blockID, 3, 0); + fillChestWithBonuses(world, rand, i + 6, j + 3, k + 3); + world.setBlock(i + 6, j + 3, k + 11, Block.chest.blockID, 2, 0); + fillChestWithBonuses(world, rand, i + 6, j + 3, k + 11); + world.setBlock(i + 6, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 4, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 4, k + 3, Block.chest.blockID, 3, 0); + fillChestWithBonuses(world, rand, i + 6, j + 4, k + 3); + world.setBlock(i + 6, j + 4, k + 11, Block.chest.blockID, 2, 0); + fillChestWithBonuses(world, rand, i + 6, j + 4, k + 11); + world.setBlock(i + 6, j + 4, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 5, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 5, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 6, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 2, k + 7, Block.cloth.blockID, 8, 0); + world.setBlock(i + 7, j + 2, k + 8, Block.cloth.blockID, 8, 0); + world.setBlock(i + 7, j + 2, k + 9, Block.cloth.blockID, 14, 0); + world.setBlock(i + 7, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 7, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 7, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 7, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 7, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 7, j + 6, k + 7, WarpDriveConfig.i.ASP, solarType, 0); + world.setBlock(i + 7, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 7, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 7, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 2, k + 6, Block.cloth.blockID, 14, 0); + world.setBlock(i + 8, j + 2, k + 7, Block.cloth.blockID, 14, 0); + world.setBlock(i + 8, j + 2, k + 8, Block.cloth.blockID, 14, 0); + world.setBlock(i + 8, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 8, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 8, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 8, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 8, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 8, j + 6, k + 7, WarpDriveConfig.i.ASP, solarType, 0); + world.setBlock(i + 8, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 8, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 2, k + 5, Block.cloth.blockID, 14, 0); + world.setBlock(i + 9, j + 2, k + 6, Block.cloth.blockID, 8, 0); + world.setBlock(i + 9, j + 2, k + 7, Block.cloth.blockID, 14, 0); + world.setBlock(i + 9, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 2, k + 10, Block.cloth.blockID, 14, 0); + world.setBlock(i + 9, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 9, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 9, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 9, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 9, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 9, j + 6, k + 7, WarpDriveConfig.i.ASP, solarType, 0); + // Placing air generator + world.setBlock(i + 9, j + 5, k + 7, WarpDriveConfig.i.airgenID, 0, 0); + world.setBlock(i + 9, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 8, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 9, j + 8, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 2, k + 5, Block.cloth.blockID, 8, 0); + world.setBlock(i + 10, j + 2, k + 6, Block.cloth.blockID, 8, 0); + world.setBlock(i + 10, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 2, k + 9, Block.cloth.blockID, 8, 0); + world.setBlock(i + 10, j + 2, k + 10, Block.cloth.blockID, 14, 0); + world.setBlock(i + 10, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 3, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 10, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 10, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 10, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 10, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 10, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 10, j + 6, k + 7, WarpDriveConfig.i.ASP, solarType, 0); + // Placing air generator + world.setBlock(i + 10, j + 5, k + 7, WarpDriveConfig.i.airgenID, 0, 0); + world.setBlock(i + 10, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 8, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 10, j + 8, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 3, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 0, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 0, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 1, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 1, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 1, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 1, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 1, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 1, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 3, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 3, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 3, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 2, j + 4, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 2, j + 4, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 2, j + 4, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 2, j + 5, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 2, j + 5, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 2, j + 5, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 3, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 3, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 3, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 4, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 4, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 5, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 5, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 3, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 2, k + 5, Block.glowStone.blockID); - world.setBlock(i + 4, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 2, k + 9, Block.glowStone.blockID); - world.setBlock(i + 4, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 4, k + 4, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 4, j + 4, k + 10, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 4, j + 5, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 5, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 5, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 5, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 4, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 2, k + 4, Block.glowStone.blockID); - world.setBlock(i + 5, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 2, k + 7, Block.cloth.blockID, 14, 0); - world.setBlock(i + 5, j + 2, k + 8, Block.cloth.blockID, 8, 0); - world.setBlock(i + 5, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 2, k + 10, Block.glowStone.blockID); - world.setBlock(i + 5, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 3, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 3, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 4, k + 3, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 5, j + 4, k + 11, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 5, j + 5, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 5, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 5, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 5, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 5, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 2, k + 6, Block.cloth.blockID, 14, 0); - world.setBlock(i + 6, j + 2, k + 7, Block.cloth.blockID, 8, 0); - world.setBlock(i + 6, j + 2, k + 8, Block.cloth.blockID, 14, 0); - world.setBlock(i + 6, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 3, k + 3, Block.chest.blockID, 3, 0); - fillChestWithBonuses(world, rand, i + 6, j + 3, k + 3); - world.setBlock(i + 6, j + 3, k + 11, Block.chest.blockID, 2, 0); - fillChestWithBonuses(world, rand, i + 6, j + 3, k + 11); - world.setBlock(i + 6, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 4, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 4, k + 3, Block.chest.blockID, 3, 0); - fillChestWithBonuses(world, rand, i + 6, j + 4, k + 3); - world.setBlock(i + 6, j + 4, k + 11, Block.chest.blockID, 2, 0); - fillChestWithBonuses(world, rand, i + 6, j + 4, k + 11); - world.setBlock(i + 6, j + 4, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 5, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 5, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 6, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 2, k + 7, Block.cloth.blockID, 8, 0); - world.setBlock(i + 7, j + 2, k + 8, Block.cloth.blockID, 8, 0); - world.setBlock(i + 7, j + 2, k + 9, Block.cloth.blockID, 14, 0); - world.setBlock(i + 7, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 7, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 7, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 7, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 7, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 7, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); - world.setBlock(i + 7, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 7, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 7, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 2, k + 6, Block.cloth.blockID, 14, 0); - world.setBlock(i + 8, j + 2, k + 7, Block.cloth.blockID, 14, 0); - world.setBlock(i + 8, j + 2, k + 8, Block.cloth.blockID, 14, 0); - world.setBlock(i + 8, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 8, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 8, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 8, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 8, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 8, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); - world.setBlock(i + 8, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 8, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 2, k + 5, Block.cloth.blockID, 14, 0); - world.setBlock(i + 9, j + 2, k + 6, Block.cloth.blockID, 8, 0); - world.setBlock(i + 9, j + 2, k + 7, Block.cloth.blockID, 14, 0); - world.setBlock(i + 9, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 2, k + 10, Block.cloth.blockID, 14, 0); - world.setBlock(i + 9, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 9, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 9, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 9, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 9, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 9, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); - // Placing air generator - world.setBlock(i + 9, j + 5, k + 7, WarpDrive.instance.config.airgenID, 0, 0); - world.setBlock(i + 9, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 8, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 9, j + 8, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 2, k + 5, Block.cloth.blockID, 8, 0); - world.setBlock(i + 10, j + 2, k + 6, Block.cloth.blockID, 8, 0); - world.setBlock(i + 10, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 2, k + 9, Block.cloth.blockID, 8, 0); - world.setBlock(i + 10, j + 2, k + 10, Block.cloth.blockID, 14, 0); - world.setBlock(i + 10, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 3, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 10, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 10, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 10, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 10, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 10, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 10, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); - // Placing air generator - world.setBlock(i + 10, j + 5, k + 7, WarpDrive.instance.config.airgenID, 0, 0); - world.setBlock(i + 10, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 8, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 10, j + 8, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 3, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); + // Place warp-controller + if (rand.nextBoolean()) + { + world.setBlock(i + 11, j + 3, k + 7, WarpDriveConfig.i.controllerID); + } - // Place warp-controller - if (rand.nextBoolean()) - { - world.setBlock(i + 11, j + 3, k + 7, WarpDrive.instance.config.controllerID); - } + world.setBlock(i + 11, j + 3, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 4, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 3, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 4, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); + // Place computer + if (rand.nextBoolean()) + { + world.setBlock(i + 11, j + 4, k + 7, 1225, 16384, 0); + } - // Place computer - if (rand.nextBoolean()) - { - world.setBlock(i + 11, j + 4, k + 7, 1225, 16384, 0); - } + world.setBlock(i + 11, j + 4, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 5, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 11, j + 6, k + 7, WarpDriveConfig.i.ASP, solarType, 0); + world.setBlock(i + 11, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 8, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 8, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 9, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 11, j + 9, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 3, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 4, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 5, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 11, j + 6, k + 7, ADV_SOLAR_BLOCKID, solarType, 0); - world.setBlock(i + 11, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 7, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 7, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 8, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 8, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 9, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 11, j + 9, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 3, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); + // Place warp-core + if (rand.nextBoolean()) + { + world.setBlock(i + 12, j + 3, k + 7, WarpDriveConfig.i.coreID); + } - // Place warp-core - if (rand.nextBoolean()) - { - world.setBlock(i + 12, j + 3, k + 7, WarpDrive.instance.config.coreID); - } + world.setBlock(i + 12, j + 3, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 4, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 4, k + 7, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 12, j + 4, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 5, k + 7, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 12, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 12, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 12, j + 6, k + 7, cableType.itemID, cableType.getItemDamage(), 0); + world.setBlock(i + 12, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 3, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 11, WorldGenStructure.getGlassBlock(corrupted, rand)); + world.setBlock(i + 13, j + 4, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 4, Block.glowStone.blockID); + world.setBlock(i + 13, j + 5, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 10, Block.glowStone.blockID); + world.setBlock(i + 13, j + 5, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 5, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 13, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 4, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 4, k + 5, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 4, k + 6, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 4, k + 8, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 4, k + 9, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 4, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 5, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 5, k + 5, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 5, k + 6, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 5, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 5, k + 8, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 5, k + 9, Block.blockRedstone.blockID); + world.setBlock(i + 14, j + 5, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 14, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 5, k + 7, Block.blockRedstone.blockID); + world.setBlock(i + 15, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 15, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 16, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 16, j + 5, k + 7, Block.blockRedstone.blockID); + world.setBlock(i + 16, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 17, j + 5, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); + world.setBlock(i + 12, j + 2, k + 9, Block.trapdoor.blockID, 10, 0); + spawnNPC(world, i + 9, j + 3, k + 5); + return true; + } - world.setBlock(i + 12, j + 3, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 4, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 4, k + 6, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 4, k + 7, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 12, j + 4, k + 8, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 4, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 5, k + 2, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 5, k + 7, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 12, j + 5, k + 12, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 12, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 6, k + 6, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 12, j + 6, k + 7, cableType.itemID, cableType.getItemDamage(), 0); - world.setBlock(i + 12, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 7, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 7, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 1, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 3, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 3, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 11, WorldGenStructure.getGlassBlock(corrupted, rand)); - world.setBlock(i + 13, j + 4, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 2, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 4, Block.glowStone.blockID); - world.setBlock(i + 13, j + 5, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 10, Block.glowStone.blockID); - world.setBlock(i + 13, j + 5, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 5, k + 12, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 6, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 7, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 7, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 13, j + 7, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 4, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 4, k + 5, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 4, k + 6, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 4, k + 8, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 4, k + 9, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 4, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 5, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 5, k + 5, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 5, k + 6, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 5, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 5, k + 8, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 5, k + 9, Block.blockRedstone.blockID); - world.setBlock(i + 14, j + 5, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 5, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 6, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 8, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 9, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 14, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 2, k + 3, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 2, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 2, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 2, k + 11, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 3, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 3, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 5, k + 7, Block.blockRedstone.blockID); - world.setBlock(i + 15, j + 6, k + 4, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 15, j + 6, k + 10, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 16, j + 4, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 16, j + 5, k + 7, Block.blockRedstone.blockID); - world.setBlock(i + 16, j + 6, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 17, j + 5, k + 7, WorldGenStructure.getStoneBlock(corrupted, rand)); - world.setBlock(i + 12, j + 2, k + 9, Block.trapdoor.blockID, 10, 0); - spawnNPC(world, i + 9, j + 3, k + 5); - return true; - } + public void spawnNPC(World world, int i, int j, int k) + { + int numMobs = 2 + world.rand.nextInt(10); - public void spawnNPC(World world, int i, int j, int k) - { - int numMobs = 2 + world.rand.nextInt(10); + if (world.rand.nextBoolean()) // Villagers + { + for (int idx = 0; idx < numMobs; idx++) + { + EntityVillager entityvillager = new EntityVillager(world, 0); + entityvillager.setLocationAndAngles((double)i + 0.5D, (double)j, (double)k + 0.5D, 0.0F, 0.0F); + world.spawnEntityInWorld(entityvillager); + } + } + else // Zombies + { + for (int idx = 0; idx < numMobs; idx++) + { + EntityZombie entityzombie = new EntityZombie(world); + entityzombie.setLocationAndAngles((double)i + 0.5D, (double)j, (double)k + 0.5D, 0.0F, 0.0F); + world.spawnEntityInWorld(entityzombie); + } + } + } - if (world.rand.nextBoolean()) // Villagers - { - for (int idx = 0; idx < numMobs; idx++) - { - EntityVillager entityvillager = new EntityVillager(world, 0); - entityvillager.setLocationAndAngles((double)i + 0.5D, (double)j, (double)k + 0.5D, 0.0F, 0.0F); - world.spawnEntityInWorld(entityvillager); - } - } - else // Zombies - { - for (int idx = 0; idx < numMobs; idx++) - { - EntityZombie entityzombie = new EntityZombie(world); - entityzombie.setLocationAndAngles((double)i + 0.5D, (double)j, (double)k + 0.5D, 0.0F, 0.0F); - world.spawnEntityInWorld(entityzombie); - } - } - } + public void fillChestWithBonuses(World worldObj, Random rand, int x, int y, int z) + { + TileEntity te = worldObj.getBlockTileEntity(x, y, z); - public void fillChestWithBonuses(World worldObj, Random rand, int x, int y, int z) - { - TileEntity te = worldObj.getBlockTileEntity(x, y, z); + if (te != null) + { + TileEntityChest chest = (TileEntityChest)te; + int numBonuses = rand.nextInt(28); - if (te != null) - { - TileEntityChest chest = (TileEntityChest)te; - int numBonuses = rand.nextInt(28); + for (int i = 0; i < chest.getSizeInventory(); i++) + { + if (rand.nextInt(15) == 0) + { + numBonuses--; + chest.setInventorySlotContents(i, getRandomBonus(rand)); + } + } + } + } - for (int i = 0; i < chest.getSizeInventory(); i++) - { - if (rand.nextInt(15) == 0) - { - numBonuses--; - chest.setInventorySlotContents(i, getRandomBonus(rand)); - } - } - } - } + private ItemStack getRandomBonus(Random rand) + { + ItemStack res = null; + boolean isDone = false; - private ItemStack getRandomBonus(Random rand) - { - ItemStack res = null; - boolean isDone = false; + while (!isDone) + { + switch (rand.nextInt(14)) + { + case 0: + res = WarpDriveConfig.i.getIC2Item("massFabricator").copy(); + res.stackSize = 1 + rand.nextInt(2); + isDone = true; + break; - while (!isDone) - { - switch (rand.nextInt(14)) - { - case 0: - res = Items.getItem("massFabricator").copy(); - res.stackSize = 1 + rand.nextInt(2); - isDone = true; - break; + case 1: + res = WarpDriveConfig.i.getIC2Item("nuke").copy(); + res.stackSize = 1 + rand.nextInt(64); + isDone = true; + break; - case 1: - res = Items.getItem("nuke").copy(); - res.stackSize = 1 + rand.nextInt(64); - isDone = true; - break; + case 2: // Quantum armor bonuses + case 3: + case 4: + case 5: + isDone = true; + break;// skipped - case 2: // Quantum armor bonuses - case 3: - case 4: - case 5: - isDone = true; - break;// skipped + case 6: + res = WarpDriveConfig.i.getIC2Item("glassFiberCableItem").copy(); + res.stackSize = 2 + rand.nextInt(63); + isDone = true; + break; - case 6: - res = Items.getItem("glassFiberCableItem").copy(); - res.stackSize = 2 + rand.nextInt(63); - isDone = true; - break; + case 7: + res = WarpDriveConfig.i.getIC2Item("matter").copy(); + res.stackSize = 2 + rand.nextInt(63); + isDone = true; + break; - case 7: - res = Items.getItem("matter").copy(); - res.stackSize = 2 + rand.nextInt(63); - isDone = true; - break; + case 8: + isDone = true; + break;// skipped - case 8: - isDone = true; - break;// skipped + // AE Quarz + case 9: + if (WarpDriveConfig.i.isAELoaded) + { + res = WarpDriveConfig.i.getAEMaterial("matQuartz").copy(); + res.stackSize = 2 + rand.nextInt(63); + isDone = true; + } - // AE Quarz - case 9: - if (isAELoaded) - { - res = new ItemStack(4362, 2 + rand.nextInt(63), 6).copy(); - isDone = true; - } + break; - break; + // AE improved processor + case 10: + if (WarpDriveConfig.i.isAELoaded) + { + res = WarpDriveConfig.i.getAEMaterial("matProcessorAdvanced").copy(); + res.stackSize = 2 + rand.nextInt(63); + isDone = true; + } + break; - // AE improved processor - case 10: - if (isAELoaded) - { - res = new ItemStack(4362, 2 + rand.nextInt(15), 19).copy(); - isDone = true; - } + // Rocket launcher platform Tier3 + case 11: + if (WarpDriveConfig.i.isICBMLoaded) + { + res = new ItemStack(WarpDriveConfig.i.ICBM_Machine, 2 + rand.nextInt(1), 2).copy(); + isDone = true; + } + break; - break; + // Missles from conventional to hypersonic + case 12: + if (WarpDriveConfig.i.isICBMLoaded) + { + res = new ItemStack(WarpDriveConfig.i.ICBM_Missile, 2 + rand.nextInt(1), rand.nextInt(21)).copy(); + isDone = true; + } + break; - // Rocket launcher platform Tier3 - case 11: - if (isICBMLoaded) - { - res = new ItemStack(3884, 2 + rand.nextInt(1), 2).copy(); - isDone = true; - } + // Advanced solar panels + case 13: + if (WarpDriveConfig.i.isAdvSolPanelLoaded) + { + res = new ItemStack(WarpDriveConfig.i.ASP, rand.nextInt(3), solarType).copy(); + isDone = true; + } + break; + } + } - break; - - // Missles from conventional to hypersonic - case 12: - if (isICBMLoaded) - { - res = new ItemStack(4159, 2 + rand.nextInt(1), rand.nextInt(21)).copy(); - isDone = true; - } - - break; - - // Advanced solar panels - case 13: - if (isAdvSolPanelLoaded) - { - res = new ItemStack(194, 2 + rand.nextInt(1), rand.nextInt(3)).copy(); - isDone = true; - } - - break; - } - } - - return res; - } + return res; + } } diff --git a/src/cr0s/WarpDrive/WorldGenStructure.java b/src/cr0s/WarpDrive/WorldGenStructure.java index 7ba29f1b..263be895 100644 --- a/src/cr0s/WarpDrive/WorldGenStructure.java +++ b/src/cr0s/WarpDrive/WorldGenStructure.java @@ -1,31 +1,20 @@ package cr0s.WarpDrive; -import ic2.api.item.Items; import java.util.Random; public class WorldGenStructure { - public static int getStoneBlock(boolean corrupted, Random rand) - { - int res = Items.getItem("reinforcedStone").itemID; + public static int getStoneBlock(boolean corrupted, Random rand) + { + if (corrupted && (rand.nextInt(15) == 1)) + return 0; + return WarpDriveConfig.i.getIC2Item("reinforcedStone").itemID; + } - if (corrupted && (rand.nextInt(15) == 1)) - { - res = 0; - } - - return res; - } - - public static int getGlassBlock(boolean corrupted, Random rand) - { - int res = Items.getItem("reinforcedGlass").itemID; - - if (corrupted && (rand.nextInt(30) == 1)) - { - res = 0; - } - - return res; - } + public static int getGlassBlock(boolean corrupted, Random rand) + { + if (corrupted && (rand.nextInt(30) == 1)) + return 0; + return WarpDriveConfig.i.getIC2Item("reinforcedGlass").itemID; + } } diff --git a/src/cr0s/WarpDrive/client/ClientProxy.java b/src/cr0s/WarpDrive/client/ClientProxy.java deleted file mode 100644 index 52e12840..00000000 --- a/src/cr0s/WarpDrive/client/ClientProxy.java +++ /dev/null @@ -1,22 +0,0 @@ -package cr0s.WarpDrive.client; - -import net.minecraft.world.World; -import cpw.mods.fml.client.FMLClientHandler; -import cr0s.WarpDrive.CommonProxy; -import cr0s.WarpDrive.FXBeam; -import cr0s.WarpDrive.Vector3; - -public class ClientProxy extends CommonProxy -{ - @Override - public void registerRenderers() - { - } - - @Override - public void renderBeam(World world, Vector3 position, Vector3 target, float red, float green, float blue, int age, int energy) - { - System.out.println("Rendering beam..."); - FMLClientHandler.instance().getClient().effectRenderer.addEffect(new FXBeam(world, position, target, red, green, blue, age, energy)); - } -} \ No newline at end of file From b312e8dff828e686d09ce8a27f87518538f37a6d Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Mon, 25 Nov 2013 03:14:36 +0400 Subject: [PATCH 08/56] Fix --- src/cr0s/WarpDrive/EntitySphereGen.java | 27 ++++----- src/cr0s/WarpDrive/SpaceWorldGenerator.java | 63 +++++++++++++-------- src/cr0s/WarpDrive/WarpDrive.java | 1 + src/cr0s/WarpDrive/WarpDriveConfig.java | 41 ++++++++------ 4 files changed, 75 insertions(+), 57 deletions(-) diff --git a/src/cr0s/WarpDrive/EntitySphereGen.java b/src/cr0s/WarpDrive/EntitySphereGen.java index 1db5f56b..6c88825d 100644 --- a/src/cr0s/WarpDrive/EntitySphereGen.java +++ b/src/cr0s/WarpDrive/EntitySphereGen.java @@ -35,7 +35,8 @@ public final class EntitySphereGen extends Entity private final int STATE_SAVING = 0; private final int STATE_SETUP = 1; private final int STATE_STOP = 2; - private int state = STATE_SAVING; + private final int STATE_DELETE = 3; + private int state = STATE_DELETE; private int currentIndex = 0; @@ -44,6 +45,7 @@ public final class EntitySphereGen extends Entity public EntitySphereGen(World world) { super(world); +System.out.println("ZLO EntitySphereGen THE FUCK create"); } public EntitySphereGen(World world, int x, int y, int z, int radius, int blockID, int blockMeta, boolean hollow, boolean fillingSphere) @@ -56,7 +58,6 @@ public final class EntitySphereGen extends Entity this.zCoord = z; this.posZ = (double) z; this.radius = radius; - this.block = new int[] {blockID, blockMeta}; this.hollow = hollow; this.fillingSphere = fillingSphere; this.surfaceSphere = (blockID == 0); @@ -65,7 +66,7 @@ public final class EntitySphereGen extends Entity if (surfaceSphere) defaultBlock = WarpDriveConfig.i.getDefaultSurfaceBlock(world.rand, world.rand.nextInt(10) > 8, true); else - defaultBlock = new int[] {blockID, blockMeta}; + this.block = new int[] {blockID, blockMeta}; } public void killEntity() @@ -89,17 +90,16 @@ public final class EntitySphereGen extends Entity saveSphereBlocks(); this.state = STATE_SETUP; break; - case STATE_SETUP: if (currentIndex >= blocks.size() - 1) - { - currentIndex = 0; - killEntity(); - } + this.state = STATE_DELETE; else - { setupBlocksTick(); - } + break; + case STATE_DELETE: + currentIndex = 0; + killEntity(); + break; } } @@ -113,10 +113,7 @@ public final class EntitySphereGen extends Entity for (int index = 0; index < blocksToMove; index++) { if (currentIndex >= blocks.size()) - { break; - } - notifyFlag = (currentIndex % 1000 == 0 ? 2 : 0); JumpBlock jb = blocks.get(currentIndex); mySetBlock(worldObj, jb.x, jb.y, jb.z, jb.blockID, jb.blockMeta, notifyFlag); @@ -196,7 +193,7 @@ public final class EntitySphereGen extends Entity } @Override - protected void readEntityFromNBT(NBTTagCompound nbttagcompound) + protected void readEntityFromNBT(NBTTagCompound tag) { } @@ -206,7 +203,7 @@ public final class EntitySphereGen extends Entity } @Override - protected void writeEntityToNBT(NBTTagCompound var1) + protected void writeEntityToNBT(NBTTagCompound tag) { } diff --git a/src/cr0s/WarpDrive/SpaceWorldGenerator.java b/src/cr0s/WarpDrive/SpaceWorldGenerator.java index e514a8e4..8b129202 100644 --- a/src/cr0s/WarpDrive/SpaceWorldGenerator.java +++ b/src/cr0s/WarpDrive/SpaceWorldGenerator.java @@ -122,11 +122,11 @@ public class SpaceWorldGenerator implements IWorldGenerator world.setBlock(x, y + MOON_RADIUS / 2, z, Block.bedrock.blockID, 0, 0); world.setBlock(x, y - MOON_RADIUS / 2, z, Block.bedrock.blockID, 0, 0); world.setBlock(x + MOON_RADIUS - 10, y, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x - MOON_RADIUS - 10, y, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x - MOON_RADIUS + 10, y, z, Block.bedrock.blockID, 0, 0); world.setBlock(x, y, z + MOON_RADIUS - 10, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y, z - MOON_RADIUS - 10, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y, z - MOON_RADIUS + 10, Block.bedrock.blockID, 0, 0); world.setBlock(x, y + MOON_RADIUS - 10, z, Block.bedrock.blockID, 0, 0); - world.setBlock(x, y - MOON_RADIUS - 10, z, Block.bedrock.blockID, 0, 0); + world.setBlock(x, y - MOON_RADIUS + 10, z, Block.bedrock.blockID, 0, 0); } private void placeStarCore(World world, int x, int y, int z, int radius) @@ -200,9 +200,16 @@ public class SpaceWorldGenerator implements IWorldGenerator { if (world.rand.nextInt(30) == 1) { - int[] t = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, 0, 0, false); - while(t[0] == 0) - t = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, 0, 0, false); + int[] t = new int[] {0, 0}; + if (world.rand.nextInt(25) == 1) + while(t[0] == 0) + t = WarpDriveConfig.i.getRandomNetherBlock(world.rand, 0, 0); + else if (world.rand.nextInt(50) == 1) + while(t[0] == 0) + t = WarpDriveConfig.i.getRandomEndBlock(world.rand, 0, 0); + else + while(t[0] == 0) + t = WarpDriveConfig.i.getRandomOverworldBlock(world.rand, 0, 0); generateAsteroidOfBlock(world, x, y, z, asteroidSizeMax, centerRadiusMax, t[0], t[1]); } else @@ -307,7 +314,8 @@ public class SpaceWorldGenerator implements IWorldGenerator centerRadius = Math.min(centerRadiusMax, centerRadius); final int CENTER_SHIFT = 2; // Offset from center of central ball // Asteroid's center - generateSphere2(world, x, y, z, centerRadius, true, blockID, meta, false); + int[] t = WarpDriveConfig.i.getDefaultSurfaceBlock(world.rand, true, false); + generateSphere2(world, x, y, z, centerRadius, true, blockID, meta, false, t); // Asteroids knolls for (int i = 1; i <= asteroidSize; i++) { @@ -315,7 +323,7 @@ public class SpaceWorldGenerator implements IWorldGenerator int newX = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); int newY = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); int newZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - generateSphere2(world, newX, newY, newZ, radius, true, blockID, meta, false); + generateSphere2(world, newX, newY, newZ, radius, true, blockID, meta, false, t); } } @@ -337,14 +345,15 @@ public class SpaceWorldGenerator implements IWorldGenerator if (centerRadiusMax != 0) centerRadius = Math.min(centerRadiusMax, centerRadius); final int CENTER_SHIFT = 2; - generateSphere2(world, x, y, z, centerRadius, true, -1, 0, false); + int[] t = WarpDriveConfig.i.getDefaultSurfaceBlock(world.rand, true, false); + generateSphere2(world, x, y, z, centerRadius, true, -1, 0, false, t); for (int i = 1; i <= asteroidSize; i++) { int radius = 2 + world.rand.nextInt(centerRadius); int newX = x + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); int newY = y + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); int newZ = z + (((world.rand.nextBoolean()) ? -1 : 1) * world.rand.nextInt(CENTER_SHIFT + centerRadius / 2)); - generateSphere2(world, newX, newY, newZ, radius, true, -1, 0, false); + generateSphere2(world, newX, newY, newZ, radius, true, -1, 0, false, t); } } @@ -360,6 +369,14 @@ public class SpaceWorldGenerator implements IWorldGenerator * @return */ public void generateSphere2(World world, int xCoord, int yCoord, int zCoord, double radius, boolean corrupted, int forcedID, int meta, boolean hollow) + { + if (forcedID == -1) + generateSphere2(world, xCoord, yCoord, zCoord, radius, corrupted, forcedID, meta, hollow, WarpDriveConfig.i.getDefaultSurfaceBlock(world.rand, corrupted, false)); + else + generateSphere2(world, xCoord, yCoord, zCoord, radius, corrupted, forcedID, meta, hollow, new int[] {forcedID, meta}); + } + + public void generateSphere2(World world, int xCoord, int yCoord, int zCoord, double radius, boolean corrupted, int forcedID, int meta, boolean hollow, int[] defaultBlock) { radius += 0.5D; // Radius from center of block double radiusSq = radius * radius; // Optimization to avoid sqrts... @@ -370,13 +387,9 @@ public class SpaceWorldGenerator implements IWorldGenerator if (forcedID == 0) blockID = new int[] {0, 0}; else if (forcedID == -1) - { - blockID = WarpDriveConfig.i.getDefaultSurfaceBlock(world.rand, corrupted, false); - forcedID = blockID[0]; - meta = blockID[1]; - } - else // STUPID JAVA variable blockID might not have been initialized BLA BLA BLA - blockID = WarpDriveConfig.i.getDefaultSurfaceBlock(world.rand, corrupted, false); + blockID = new int[] {forcedID, meta};//SRANYA JABA might not have been initialized + else + blockID = new int[] {forcedID, meta}; // Pass the cube and check points for sphere equation x^2 + y^2 + z^2 = r^2 for (int x = 0; x <= ceilRadius; x++) for (int y = 0; y <= ceilRadius; y++) @@ -395,29 +408,29 @@ public class SpaceWorldGenerator implements IWorldGenerator // Place blocks if (!corrupted || world.rand.nextInt(10) != 1) { - if (forcedID > 0) - blockID = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, forcedID, meta, false); + if (forcedID == -1) + blockID = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, defaultBlock[0], defaultBlock[1], false); world.setBlock(xCoord + x, yCoord + y, zCoord + z, blockID[0], blockID[1], 2); world.setBlock(xCoord - x, yCoord + y, zCoord + z, blockID[0], blockID[1], 2); } if (!corrupted || world.rand.nextInt(10) != 1) { - if (forcedID > 0) - blockID = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, forcedID, meta, false); + if (forcedID == -1) + blockID = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, defaultBlock[0], defaultBlock[1], false); world.setBlock(xCoord + x, yCoord - y, zCoord + z, blockID[0], blockID[1], 2); world.setBlock(xCoord + x, yCoord + y, zCoord - z, blockID[0], blockID[1], 2); } if (!corrupted || world.rand.nextInt(10) != 1) { - if (forcedID > 0) - blockID = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, forcedID, meta, false); + if (forcedID == -1) + blockID = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, defaultBlock[0], defaultBlock[1], false); world.setBlock(xCoord - x, yCoord - y, zCoord + z, blockID[0], blockID[1], 2); world.setBlock(xCoord + x, yCoord - y, zCoord - z, blockID[0], blockID[1], 2); } if (!corrupted || world.rand.nextInt(10) != 1) { - if (forcedID > 0) - blockID = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, forcedID, meta, false); + if (forcedID == -1) + blockID = WarpDriveConfig.i.getRandomSurfaceBlock(world.rand, defaultBlock[0], defaultBlock[1], false); world.setBlock(xCoord - x, yCoord + y, zCoord - z, blockID[0], blockID[1], 2); world.setBlock(xCoord - x, yCoord - y, zCoord - z, blockID[0], blockID[1], 2); } diff --git a/src/cr0s/WarpDrive/WarpDrive.java b/src/cr0s/WarpDrive/WarpDrive.java index 474feb53..1cefde55 100644 --- a/src/cr0s/WarpDrive/WarpDrive.java +++ b/src/cr0s/WarpDrive/WarpDrive.java @@ -101,6 +101,7 @@ public class WarpDrive implements LoadingCallback @Init public void load(FMLInitializationEvent event) { + WarpDriveConfig.i.Init2(); // WARP CORE this.warpCore = new BlockReactor(WarpDriveConfig.i.coreID, 0, Material.rock) .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 4ebc246e..b272668c 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -86,10 +86,9 @@ public class WarpDriveConfig if (i == null) i = new WarpDriveConfig(); i.config = config; - i.Init2(); } - private void Init2() + public void Init2() { CommonWorldGenOres = new ArrayList<int[]>(); CommonWorldGenOres.add(new int[] {Block.oreIron.blockID, 0}); @@ -187,6 +186,7 @@ public class WarpDriveConfig catch (Exception e) { System.out.println("WarpDriveConfig Error loading CC classes AWWW SHEEEEET NIGGA"); + e.printStackTrace(); } } @@ -194,15 +194,17 @@ public class WarpDriveConfig { try { - Class<?> z = Class.forName("gregtechmod.api.GregTech_API"); - GT_Machine = ((int[])z.getField("sBlockIDs").get(null))[1]; - GT_Ores = ((int[])z.getField("sBlockIDs").get(null))[2]; // meta 1-15 = ores - GT_Granite = ((int[])z.getField("sBlockIDs").get(null))[5]; // 0 - black, 1 - black cobble, 8 - red, 9 - red cobble + Class<?> z = Class.forName("gregtechmod.GT_Mod"); + int[] t = (int[])z.getField("sBlockIDs").get(null); + GT_Machine = t[1]; + GT_Ores = t[2]; // meta 1-15 = ores + GT_Granite = t[5]; // 0 - black, 1 - black cobble, 8 - red, 9 - red cobble MinerOres.add(GT_Ores); } catch (Exception e) { System.out.println("WarpDriveConfig Error loading GT classes"); + e.printStackTrace(); isGregLoaded = false; } } @@ -219,6 +221,7 @@ public class WarpDriveConfig catch (Exception e) { System.out.println("WarpDriveConfig Error loading AE classes"); + e.printStackTrace(); isAELoaded = false; } } @@ -236,6 +239,7 @@ public class WarpDriveConfig catch (Exception e) { System.out.println("WarpDriveConfig Error loading ASP classes"); + e.printStackTrace(); isAdvSolPanelLoaded = false; } } @@ -268,6 +272,7 @@ public class WarpDriveConfig catch (Exception e) { System.out.println("WarpDriveConfig Error loading ICBM classes"); + e.printStackTrace(); isICBMLoaded = false; } } @@ -282,6 +287,7 @@ public class WarpDriveConfig catch (Exception e) { System.out.println("WarpDriveConfig Error loading MFFS classes"); + e.printStackTrace(); isICBMLoaded = false; } } @@ -296,6 +302,7 @@ public class WarpDriveConfig catch (Exception e) { System.out.println("WarpDriveConfig Error loading GS classes"); + e.printStackTrace(); isGraviSuiteLoaded = false; } } @@ -316,14 +323,14 @@ public class WarpDriveConfig } else { - if (random.nextInt(50) == 1) + if (random.nextInt(25) == 1) if (random.nextBoolean()) return new int[] {GT_Granite, (corrupted && random.nextBoolean())?1:0}; else return new int[] {GT_Granite, (corrupted && random.nextBoolean())?9:8}; - else if (random.nextInt(100) == 1) + else if (random.nextInt(50) == 1) return new int[] {Block.netherrack.blockID, 0}; - else if (random.nextInt(300) == 1) + else if (random.nextInt(150) == 1) return new int[] {Block.whiteStone.blockID, 0}; } if (corrupted && random.nextBoolean()) @@ -363,7 +370,7 @@ public class WarpDriveConfig return getRandomOverworldBlock(random, blockID, blockMeta); } - private int[] getRandomOverworldBlock(Random random, int blockID, int blockMeta) + public int[] getRandomOverworldBlock(Random random, int blockID, int blockMeta) { if (random.nextInt(25) == 5) return CommonWorldGenOres.get(random.nextInt(CommonWorldGenOres.size())); @@ -397,12 +404,12 @@ public class WarpDriveConfig return new int[] {blockID, blockMeta}; } - private int[] getRandomNetherBlock(Random random, int blockID, int blockMeta) + public int[] getRandomNetherBlock(Random random, int blockID, int blockMeta) { - if (random.nextInt(500) == 1) - return new int[] {Block.oreNetherQuartz.blockID, 0}; - else if (random.nextInt(10000) == 42) + if (random.nextInt(10000) == 42) return new int[] {iridiumID, 0}; + else if (random.nextInt(50) == 1) + return new int[] {Block.oreNetherQuartz.blockID, 0}; else if (isGregLoaded) { if (random.nextInt(100) == 1) @@ -412,12 +419,12 @@ public class WarpDriveConfig else if (random.nextInt(500) == 1) return new int[] {GT_Ores, 7}; //Cinnabar I+S } - if (random.nextInt(100) == 13) + else if (random.nextInt(100) == 13) return CommonWorldGenOres.get(random.nextInt(CommonWorldGenOres.size())); return new int[] {blockID, blockMeta}; } - private int[] getRandomEndBlock(Random random, int blockID, int blockMeta) + public int[] getRandomEndBlock(Random random, int blockID, int blockMeta) { if (random.nextInt(10000) == 42) return new int[] {iridiumID, 0}; @@ -432,7 +439,7 @@ public class WarpDriveConfig else if (random.nextInt(1000) == 1) return new int[] {GT_Ores, 11}; //Olivine D+S } - if (random.nextInt(200) == 13) + else if (random.nextInt(200) == 13) return CommonWorldGenOres.get(random.nextInt(CommonWorldGenOres.size())); return new int[] {blockID, blockMeta}; } From 971514d597c94181c6bbfab15afcff5dbf2dec07 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Mon, 25 Nov 2013 18:14:49 +0400 Subject: [PATCH 09/56] =?UTF-8?q?=D0=A0=D0=95=D0=9C=D0=9E=D0=9D=D0=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 31 ++++++++++++------- src/cr0s/WarpDrive/WarpDriveConfig.java | 3 +- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index a72685ca..e710efb8 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -92,7 +92,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG { isOnEarth = (worldObj.provider.dimensionId == 0); - if (isMining && powerStatus) + if (isMining) { if (minerVector != null) { @@ -107,8 +107,6 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG if (++delayTicksScan > SCAN_DELAY) { delayTicksScan = 0; - currentMode = 1; - if (currentLayer <= 0) { isMining = false; @@ -117,12 +115,18 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG int blockID = worldObj.getBlockId(xCoord, currentLayer, zCoord); - if (blockID != 0 && worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && canDig(blockID)) - { - sendLaserPacket(minerVector, new Vector3(xCoord, currentLayer, zCoord).add(0.5), 0, 0, 1, 20, 0, 50); - worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); - harvestBlock(new Vector3(xCoord, currentLayer, zCoord)); - } + if (blockID != 0) + if (worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && canDig(blockID)) + { + sendLaserPacket(minerVector, new Vector3(xCoord, currentLayer, zCoord).add(0.5), 0, 0, 1, 20, 0, 50); + worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); + harvestBlock(new Vector3(xCoord, currentLayer, zCoord)); + } + else + { + isMining = false; + return; + } if (collectEnergyPacketFromBooster(isOnEarth ? EU_PER_LAYER_EARTH : EU_PER_LAYER_SPACE)) scanLayer(); @@ -131,6 +135,8 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG isMining = false; return; } + if (valuablesInLayer.size() > 0) + currentMode = 1; } } else @@ -147,7 +153,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); // Skip if block is too hard or its empty block - if (worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && (worldObj.isAirBlock(valuable.intX(), valuable.intY(), valuable.intZ()) || Block.blocksList[blockID].blockResistance > Block.obsidian.blockResistance)) + if (worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) == Material.water || !canDig(blockID)) return; sendLaserPacket(minerVector, new Vector3(valuable.intX(), valuable.intY(), valuable.intZ()).add(0.5), 1, 1, 0, 2 * MINE_DELAY, 0, 50); @@ -167,7 +173,10 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG private boolean canDig(int blockID) { - return (blockID != WarpDriveConfig.i.MFFS_Field && blockID != Block.bedrock.blockID && Block.blocksList[blockID] != null && Block.blocksList[blockID].blockResistance <= Block.obsidian.blockResistance); + if (Block.blocksList[blockID] != null) + return ((blockID == WarpDriveConfig.i.GT_Granite || blockID == WarpDriveConfig.i.GT_Ores || blockID == WarpDriveConfig.i.iridiumID || Block.blocksList[blockID].blockResistance <= Block.obsidian.blockResistance) && blockID != WarpDriveConfig.i.MFFS_Field && blockID != Block.bedrock.blockID); + else + return (blockID != WarpDriveConfig.i.MFFS_Field && blockID != Block.bedrock.blockID); } private void harvestBlock(Vector3 valuable) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index b272668c..a41dd6e4 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -200,6 +200,7 @@ public class WarpDriveConfig GT_Ores = t[2]; // meta 1-15 = ores GT_Granite = t[5]; // 0 - black, 1 - black cobble, 8 - red, 9 - red cobble MinerOres.add(GT_Ores); + MinerOres.add(GT_Granite); } catch (Exception e) { @@ -408,7 +409,7 @@ public class WarpDriveConfig { if (random.nextInt(10000) == 42) return new int[] {iridiumID, 0}; - else if (random.nextInt(50) == 1) + else if (random.nextInt(25) == 1) return new int[] {Block.oreNetherQuartz.blockID, 0}; else if (isGregLoaded) { From 4b48c050598768d3b5f0fa3070a6f5d90d8ba5b2 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Mon, 25 Nov 2013 20:44:21 +0400 Subject: [PATCH 10/56] O2 Fix --- src/cr0s/WarpDrive/SpaceEventHandler.java | 204 ++++++++++++---------- src/cr0s/WarpDrive/WarpDriveConfig.java | 5 +- 2 files changed, 110 insertions(+), 99 deletions(-) diff --git a/src/cr0s/WarpDrive/SpaceEventHandler.java b/src/cr0s/WarpDrive/SpaceEventHandler.java index 5e2ef2ec..b34ba19d 100644 --- a/src/cr0s/WarpDrive/SpaceEventHandler.java +++ b/src/cr0s/WarpDrive/SpaceEventHandler.java @@ -5,6 +5,7 @@ import java.util.HashMap; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; import net.minecraft.util.DamageSource; import net.minecraft.util.MathHelper; import net.minecraftforge.common.DimensionManager; @@ -17,115 +18,124 @@ import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; */ public class SpaceEventHandler { - private HashMap<String, Integer> vacuumPlayers; + private HashMap<String, Integer> vacuumPlayers; - public SpaceEventHandler() - { - vacuumPlayers = new HashMap<String, Integer>(); - } + public SpaceEventHandler() + { + vacuumPlayers = new HashMap<String, Integer>(); + } - @ForgeSubscribe - public void livingUpdate(LivingUpdateEvent event) - { - EntityLivingBase entity = event.entityLiving; + @ForgeSubscribe + public void livingUpdate(LivingUpdateEvent event) + { + EntityLivingBase entity = event.entityLiving; - if (Math.abs(MathHelper.floor_double(entity.posX)) > WarpDrive.WORLD_LIMIT_BLOCKS || Math.abs(MathHelper.floor_double(entity.posZ)) > WarpDrive.WORLD_LIMIT_BLOCKS) - { - if (entity instanceof EntityPlayerMP) - { - if (((EntityPlayerMP)entity).capabilities.isCreativeMode) - { - return; - } - } + if (Math.abs(MathHelper.floor_double(entity.posX)) > WarpDrive.WORLD_LIMIT_BLOCKS || Math.abs(MathHelper.floor_double(entity.posZ)) > WarpDrive.WORLD_LIMIT_BLOCKS) + { + if (entity instanceof EntityPlayerMP) + { + if (((EntityPlayerMP)entity).capabilities.isCreativeMode) + { + return; + } + } - entity.attackEntityFrom(DamageSource.outOfWorld, 9000); - return; - } + entity.attackEntityFrom(DamageSource.outOfWorld, 9000); + return; + } - // Обновление происходит в космическом или гипер пространстве - if (entity.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID || entity.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) - { - boolean inVacuum = isEntityInVacuum(entity); + // Обновление происходит в космическом или гипер пространстве + if (entity.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID || entity.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) + { + boolean inVacuum = isEntityInVacuum(entity); - // Damage entity if in vacuum without protection - if (inVacuum) - { - if (entity instanceof EntityPlayerMP) - { + // Damage entity if in vacuum without protection + if (inVacuum) + { + if (entity instanceof EntityPlayerMP) + { - if (((EntityPlayerMP)entity).getCurrentArmor(3) != null && WarpDriveConfig.i.SpaceHelmets.contains(((EntityPlayerMP)entity).getCurrentArmor(3).itemID)) - { - Integer airValue = vacuumPlayers.get(((EntityPlayerMP)entity).username); + if (((EntityPlayerMP)entity).getCurrentArmor(3) != null && WarpDriveConfig.i.SpaceHelmets.contains(((EntityPlayerMP)entity).getCurrentArmor(3).itemID)) + { + Integer airValue = vacuumPlayers.get(((EntityPlayerMP)entity).username); - if (airValue == null) - { - vacuumPlayers.put(((EntityPlayerMP)entity).username, 300); - airValue = 300; - } + if (airValue == null) + { + vacuumPlayers.put(((EntityPlayerMP)entity).username, 300); + airValue = 300; + } - if (airValue <= 0) - { - if (((EntityPlayerMP)entity).inventory.consumeInventoryItem(WarpDriveConfig.i.IC2_Air)) - { - setPlayerAirValue(entity, 300); - } - else - { - setPlayerAirValue(entity, 0); - entity.attackEntityFrom(DamageSource.drown, 1); - } - } - else - { - setPlayerAirValue(entity, airValue - 1); - } - } - else - { - entity.attackEntityFrom(DamageSource.drown, 1); - } + if (airValue <= 0) + { + if (consumeO2(((EntityPlayerMP)entity).inventory.mainInventory)) + { + setPlayerAirValue(entity, 300); + } + else + { + setPlayerAirValue(entity, 0); + entity.attackEntityFrom(DamageSource.drown, 1); + } + } + else + { + setPlayerAirValue(entity, airValue - 1); + } + } + else + { + entity.attackEntityFrom(DamageSource.drown, 1); + } - // Отправить назад на Землю - if (entity.posY < -10.0D) - { - ((EntityPlayerMP)entity).mcServer.getConfigurationManager().transferPlayerToDimension(((EntityPlayerMP) entity), 0, new SpaceTeleporter(DimensionManager.getWorld(WarpDrive.instance.spaceDimID), 0, MathHelper.floor_double(entity.posX), 250, MathHelper.floor_double(entity.posZ))); - ((EntityPlayerMP)entity).setFire(30); - ((EntityPlayerMP)entity).setPositionAndUpdate(entity.posX, 250D, entity.posZ); - } - } - else - { - entity.attackEntityFrom(DamageSource.drown, 1); - } - } - } - } + // Отправить назад на Землю + if (entity.posY < -10.0D) + { + ((EntityPlayerMP)entity).mcServer.getConfigurationManager().transferPlayerToDimension(((EntityPlayerMP) entity), 0, new SpaceTeleporter(DimensionManager.getWorld(WarpDrive.instance.spaceDimID), 0, MathHelper.floor_double(entity.posX), 250, MathHelper.floor_double(entity.posZ))); + ((EntityPlayerMP)entity).setFire(30); + ((EntityPlayerMP)entity).setPositionAndUpdate(entity.posX, 250D, entity.posZ); + } + } + else + { + entity.attackEntityFrom(DamageSource.drown, 1); + } + } + } + } - private void setPlayerAirValue(EntityLivingBase entity, Integer air) - { - vacuumPlayers.remove(((EntityPlayerMP)entity).username); - vacuumPlayers.put(((EntityPlayerMP)entity).username, air); - } + private void setPlayerAirValue(EntityLivingBase entity, Integer air) + { + vacuumPlayers.remove(((EntityPlayerMP)entity).username); + vacuumPlayers.put(((EntityPlayerMP)entity).username, air); + } - /** - * Проверка, находится ли Entity в открытом космосе - * @param e - * @return - */ - private boolean isEntityInVacuum(Entity e) - { - int x = MathHelper.floor_double(e.posX); - int y = MathHelper.floor_double(e.posY); - int z = MathHelper.floor_double(e.posZ); - int id1 = e.worldObj.getBlockId(x, y, z); - int id2 = e.worldObj.getBlockId(x, y + 1, z); + /** + * Проверка, находится ли Entity в открытом космосе + * @param e + * @return + */ + private boolean isEntityInVacuum(Entity e) + { + int x = MathHelper.floor_double(e.posX); + int y = MathHelper.floor_double(e.posY); + int z = MathHelper.floor_double(e.posZ); + int id1 = e.worldObj.getBlockId(x, y, z); + int id2 = e.worldObj.getBlockId(x, y + 1, z); - if (id1 == WarpDriveConfig.i.airID || id2 == WarpDriveConfig.i.airID) - { - return false; - } + if (id1 == WarpDriveConfig.i.airID || id2 == WarpDriveConfig.i.airID) + return false; + return true; + } - return true; - } + private boolean consumeO2(ItemStack[] i) + { + for (int j = 0; j < i.length; ++j) + if (i[j] != null && i[j].itemID == WarpDriveConfig.i.IC2_Air[0] && i[j].getItemDamage() == WarpDriveConfig.i.IC2_Air[1]) + { + if (--i[j].stackSize <= 0) + i[j] = null; + return true; + } + return false; + } } diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index a41dd6e4..051ac427 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -22,7 +22,8 @@ public class WarpDriveConfig // public boolean isGregLoaded = false, isAELoaded = false, isAdvSolPanelLoaded = false, isASLoaded = false, isICBMLoaded = false, isMFFSLoaded = false, isGraviSuiteLoaded = false; // - public int IC2_Air = 0, CC_Computer = 0, CC_peripheral = 0, CCT_Turtle = 0, CCT_Upgraded = 0, CCT_Advanced = 0, GT_Ores = 0, GT_Granite = 0, GT_Machine = 0, ASP = 0, AS_Turbine = 0, ICBM_Machine = 0, ICBM_Missile = 0, MFFS_Field = 0; + public int[] IC2_Air; + public int CC_Computer = 0, CC_peripheral = 0, CCT_Turtle = 0, CCT_Upgraded = 0, CCT_Advanced = 0, GT_Ores = 0, GT_Granite = 0, GT_Machine = 0, ASP = 0, AS_Turbine = 0, ICBM_Machine = 0, ICBM_Missile = 0, MFFS_Field = 0; public Set<Integer> SpaceHelmets, Jetpacks, MinerOres; private Class<?> AEBlocks; private Class<?> AEMaterials; @@ -164,7 +165,7 @@ public class WarpDriveConfig SpaceHelmets.add(Items.getItem("quantumHelmet").itemID); Jetpacks.add(Items.getItem("jetpack").itemID); Jetpacks.add(Items.getItem("electricJetpack").itemID); - IC2_Air = Items.getItem("airCell").itemID; + IC2_Air = new int[] {Items.getItem("airCell").itemID, Items.getItem("airCell").getItemDamage()}; CommonWorldGenOres.add(new int[] {Items.getItem("uraniumOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); CommonWorldGenOres.add(new int[] {Items.getItem("copperOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); CommonWorldGenOres.add(new int[] {Items.getItem("tinOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); From 1202dd9c9cc398beefc70324f190079ffd8f3568 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Mon, 25 Nov 2013 22:00:17 +0400 Subject: [PATCH 11/56] O2 Fix --- src/cr0s/WarpDrive/WarpDriveConfig.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 051ac427..3586d64f 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -234,9 +234,9 @@ public class WarpDriveConfig { Class<?> z = Class.forName("advsolar.common.AdvancedSolarPanel"); ASP = z.getField("idAdv").getInt(null); - SpaceHelmets.add(z.getField("advSolarHelmetID").getInt(null)); - SpaceHelmets.add(z.getField("hybridSolarHelmetID").getInt(null)); - SpaceHelmets.add(z.getField("ultimateSolarHelmetID").getInt(null)); + SpaceHelmets.add(((Item)z.getField("advancedSolarHelmet").get(null)).itemID); + SpaceHelmets.add(((Item)z.getField("hybridSolarHelmet").get(null)).itemID); + SpaceHelmets.add(((Item)z.getField("ultimateSolarHelmet").get(null)).itemID); } catch (Exception e) { @@ -299,7 +299,7 @@ public class WarpDriveConfig try { Class<?> z = Class.forName("gravisuite.GraviSuite"); - SpaceHelmets.add(z.getField("ultimateSolarHelmetID").getInt(null)); + SpaceHelmets.add(((Item)z.getField("ultimateSolarHelmet").get(null)).itemID); } catch (Exception e) { From d7cc3d1e72d7cef5cbdae2c5578a9e043a22f940 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Tue, 26 Nov 2013 01:18:33 +0400 Subject: [PATCH 12/56] GS fix --- src/cr0s/WarpDrive/WarpDriveConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 3586d64f..681f6f84 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -299,7 +299,8 @@ public class WarpDriveConfig try { Class<?> z = Class.forName("gravisuite.GraviSuite"); - SpaceHelmets.add(((Item)z.getField("ultimateSolarHelmet").get(null)).itemID); + if (z.getField("ultimateSolarHelmet").get(null) != null) + SpaceHelmets.add(((Item)z.getField("ultimateSolarHelmet").get(null)).itemID); } catch (Exception e) { From f776ea748933767506d0639c797c36e358ce26a0 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Tue, 26 Nov 2013 02:06:10 +0400 Subject: [PATCH 13/56] GS jetpacks --- src/cr0s/WarpDrive/WarpDriveConfig.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 681f6f84..d4664ad6 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -301,6 +301,8 @@ public class WarpDriveConfig Class<?> z = Class.forName("gravisuite.GraviSuite"); if (z.getField("ultimateSolarHelmet").get(null) != null) SpaceHelmets.add(((Item)z.getField("ultimateSolarHelmet").get(null)).itemID); + Jetpacks.add(z.getField("advJetpackID").getInt(null)); + Jetpacks.add(z.getField("graviChestPlateID").getInt(null)); } catch (Exception e) { From 5b97cc30d5215ec494389545750a24b052f76392 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Wed, 27 Nov 2013 06:05:55 +0400 Subject: [PATCH 14/56] =?UTF-8?q?=D0=9A=D0=BE=D0=BC=D0=BF=D0=BE=D1=81?= =?UTF-8?q?=D1=82->=D1=81=D1=82=D0=B0=D0=BB=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cr0s/WarpDrive/WarpDrive.java | 8 ++++---- src/cr0s/WarpDrive/WarpDriveConfig.java | 12 ++++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/cr0s/WarpDrive/WarpDrive.java b/src/cr0s/WarpDrive/WarpDrive.java index 1cefde55..b87b7940 100644 --- a/src/cr0s/WarpDrive/WarpDrive.java +++ b/src/cr0s/WarpDrive/WarpDrive.java @@ -230,13 +230,13 @@ public class WarpDrive implements LoadingCallback GameRegistry.addRecipe(new ItemStack(airgenBlock), "lcl", "lml", "lll", 'l', Block.leaves, 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit")); GameRegistry.addRecipe(new ItemStack(laserBlock), "sss", "ama", "aaa", - 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy"), 's', WarpDriveConfig.i.getIC2Item("advancedCircuit")); + 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'a', WarpDriveConfig.i.Compot, 's', WarpDriveConfig.i.getIC2Item("advancedCircuit")); GameRegistry.addRecipe(new ItemStack(miningLaserBlock), "aaa", "ama", "ccc", - 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy"), 'm', WarpDriveConfig.i.getIC2Item("miner")); + 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.Compot, 'm', WarpDriveConfig.i.getIC2Item("miner")); GameRegistry.addRecipe(new ItemStack(boosterBlock), "afc", "ama", "cfa", - 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy"), 'f', WarpDriveConfig.i.getIC2Item("glassFiberCableItem"), 'm', WarpDriveConfig.i.getIC2Item("mfeUnit")); + 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.Compot, 'f', WarpDriveConfig.i.getIC2Item("glassFiberCableItem"), 'm', WarpDriveConfig.i.getIC2Item("mfeUnit")); GameRegistry.addRecipe(new ItemStack(liftBlock), "aca", "ama", "a#a", - 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy"), 'm', WarpDriveConfig.i.getIC2Item("magnetizer")); + 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.Compot, 'm', WarpDriveConfig.i.getIC2Item("magnetizer")); /* GameRegistry.addRecipe(new ItemStack(Item.enderPearl), "uuu", "uuu", "uuu", 'u', WarpDriveConfig.i.getIC2Item("uraniumDrop")); diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index d4664ad6..fbe4a92a 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -9,6 +9,7 @@ import java.util.Random; import java.lang.reflect.*; import cpw.mods.fml.common.Loader; import net.minecraftforge.common.Configuration; +import net.minecraftforge.oredict.OreDictionary; import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -24,6 +25,7 @@ public class WarpDriveConfig // public int[] IC2_Air; public int CC_Computer = 0, CC_peripheral = 0, CCT_Turtle = 0, CCT_Upgraded = 0, CCT_Advanced = 0, GT_Ores = 0, GT_Granite = 0, GT_Machine = 0, ASP = 0, AS_Turbine = 0, ICBM_Machine = 0, ICBM_Missile = 0, MFFS_Field = 0; + public ItemStack Compot; public Set<Integer> SpaceHelmets, Jetpacks, MinerOres; private Class<?> AEBlocks; private Class<?> AEMaterials; @@ -170,6 +172,7 @@ public class WarpDriveConfig CommonWorldGenOres.add(new int[] {Items.getItem("copperOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); CommonWorldGenOres.add(new int[] {Items.getItem("tinOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); MinerOres.add(Items.getItem("rubberWood").itemID); + Compot = Items.getItem("advancedAlloy"); } private void LoadCC() @@ -195,13 +198,18 @@ public class WarpDriveConfig { try { - Class<?> z = Class.forName("gregtechmod.GT_Mod"); - int[] t = (int[])z.getField("sBlockIDs").get(null); + int[] t = (int[])Class.forName("gregtechmod.GT_Mod").getField("sBlockIDs").get(null); GT_Machine = t[1]; GT_Ores = t[2]; // meta 1-15 = ores GT_Granite = t[5]; // 0 - black, 1 - black cobble, 8 - red, 9 - red cobble MinerOres.add(GT_Ores); MinerOres.add(GT_Granite); + ArrayList<ItemStack> t1 = new ArrayList<ItemStack>(); + t1.addAll(OreDictionary.getOres("craftingPlateSteel")); + if (t1.size() >= 3) + Compot = t1.get(2); + else + System.out.println("WarpDriveConfig Error getting craftingPlateSteel " + t1.size()); } catch (Exception e) { From 74c49e014a8d06776fc45fed49331d8adb23196c Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Thu, 28 Nov 2013 00:37:46 +0400 Subject: [PATCH 15/56] =?UTF-8?q?=D0=9E=D1=82=D0=BA=D0=B0=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cr0s/WarpDrive/WarpDriveConfig.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index fbe4a92a..8fb5d573 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -204,12 +204,14 @@ public class WarpDriveConfig GT_Granite = t[5]; // 0 - black, 1 - black cobble, 8 - red, 9 - red cobble MinerOres.add(GT_Ores); MinerOres.add(GT_Granite); +/* ArrayList<ItemStack> t1 = new ArrayList<ItemStack>(); t1.addAll(OreDictionary.getOres("craftingPlateSteel")); if (t1.size() >= 3) Compot = t1.get(2); else System.out.println("WarpDriveConfig Error getting craftingPlateSteel " + t1.size()); +*/ } catch (Exception e) { From 6f89b72702951c90214a2c4b5ecb500f47776556 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Wed, 4 Dec 2013 22:15:31 +0400 Subject: [PATCH 16/56] Fix --- src/cr0s/WarpDrive/EntityJump.java | 25 +++--- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 76 +++++++------------ 2 files changed, 43 insertions(+), 58 deletions(-) diff --git a/src/cr0s/WarpDrive/EntityJump.java b/src/cr0s/WarpDrive/EntityJump.java index d43ae7c2..5cd27efe 100644 --- a/src/cr0s/WarpDrive/EntityJump.java +++ b/src/cr0s/WarpDrive/EntityJump.java @@ -498,7 +498,18 @@ public class EntityJump extends Entity te = worldObj.getBlockTileEntity(jb.x + moveX, jb.y + moveY, jb.z + moveZ); if (te != null) { - c = te.getClass().getSuperclass(); + c = te.getClass(); + if (c.getName().equals("atomicscience.jiqi.TTurbine")) + try + { + if (c.getField("shiDa").getBoolean(te)) + ASTurbines.add(te); + } + catch (Exception e) + { + e.printStackTrace(); + } + c = c.getSuperclass(); if (c.getName().equals("ic2.core.block.wiring.TileEntityElectricBlock") || c.getName().equals("ic2.core.block.TileEntityBlock") || c.getName().contains("ic2.core.block.generator")) { try @@ -511,18 +522,12 @@ public class EntityJump extends Entity } catch (Exception e) {} te.updateContainingBlockInfo(); - } - c = te.getClass(); - if (c.getName().equals("atomicscience.jiqi.TTurbine")) try { - if (c.getField("shiDa").getBoolean(te)) - ASTurbines.add(te); - } - catch (Exception e) - { - e.printStackTrace(); + NetworkHelper.updateTileEntityField(te, "facing"); } + catch (Exception e) {} + } } worldObj.setBlockToAir(jb.x, jb.y, jb.z); currentIndexInShip++; diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index e710efb8..152f3f73 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -90,10 +90,9 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG @Override public void updateEntity() { - isOnEarth = (worldObj.provider.dimensionId == 0); - if (isMining) { + isOnEarth = (worldObj.provider.dimensionId == 0); if (minerVector != null) { minerVector.x = xCoord; @@ -107,36 +106,33 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG if (++delayTicksScan > SCAN_DELAY) { delayTicksScan = 0; - if (currentLayer <= 0) - { - isMining = false; + valuablesInLayer.clear(); + valuableIndex = 0; + if (!collectEnergyPacketFromBooster(isOnEarth ? EU_PER_LAYER_EARTH : EU_PER_LAYER_SPACE, true)) return; - } - - int blockID = worldObj.getBlockId(xCoord, currentLayer, zCoord); - - if (blockID != 0) - if (worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && canDig(blockID)) + while (currentLayer > 0) + { + scanLayer(); + if (valuablesInLayer.size() > 0) { + if (!collectEnergyPacketFromBooster(isOnEarth ? EU_PER_LAYER_EARTH : EU_PER_LAYER_SPACE, false)) + return; sendLaserPacket(minerVector, new Vector3(xCoord, currentLayer, zCoord).add(0.5), 0, 0, 1, 20, 0, 50); worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); - harvestBlock(new Vector3(xCoord, currentLayer, zCoord)); - } - else - { - isMining = false; + int blockID = worldObj.getBlockId(xCoord, currentLayer, zCoord); + if (blockID != 0) + if (worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && canDig(blockID)) + harvestBlock(new Vector3(xCoord, currentLayer, zCoord)); + else + isMining = false; + currentMode = 1; return; } - - if (collectEnergyPacketFromBooster(isOnEarth ? EU_PER_LAYER_EARTH : EU_PER_LAYER_SPACE)) - scanLayer(); - else - { - isMining = false; - return; + else + --currentLayer; } - if (valuablesInLayer.size() > 0) - currentMode = 1; + if (currentLayer <= 0) + isMining = false; } } else @@ -183,13 +179,10 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG { int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); int blockMeta = worldObj.getBlockMetadata(valuable.intX(), valuable.intY(), valuable.intZ()); - if (blockID != Block.waterMoving.blockID && blockID != Block.waterStill.blockID && blockID != Block.lavaMoving.blockID && blockID != Block.lavaStill.blockID) { List<ItemStack> stacks = getItemStackFromBlock(valuable.intX(), valuable.intY(), valuable.intZ(), blockID, blockMeta); - if (stacks != null) - { for (ItemStack stack : stacks) { if (grid != null) @@ -197,16 +190,11 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG else putInChest(findChest(), stack); } - } - worldObj.playAuxSFXAtEntity(null, 2001, valuable.intX(), valuable.intY(), valuable.intZ(), blockID + (blockMeta << 12)); - // Evaporate water } else if (blockID == Block.waterMoving.blockID || blockID == Block.waterStill.blockID) - { + // Evaporate water worldObj.playSoundEffect((double)((float)valuable.intX() + 0.5F), (double)((float)valuable.intY() + 0.5F), (double)((float)valuable.intZ() + 0.5F), "random.fizz", 0.5F, 2.6F + (worldObj.rand.nextFloat() - worldObj.rand.nextFloat()) * 0.8F); - } - worldObj.setBlockToAir(valuable.intX(), valuable.intY(), valuable.intZ()); } @@ -254,12 +242,8 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG public List<ItemStack> getItemStackFromBlock(int i, int j, int k, int blockID, int blockMeta) { Block block = Block.blocksList[blockID]; - if (block == null) - { return null; - } - return block.getBlockDropped(worldObj, i, j, k, blockMeta, 0); } @@ -401,20 +385,16 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG valuableIndex = 0; //System.out.println("[ML] Found " + valuablesInLayer.size() + " valuables"); } - private boolean collectEnergyPacketFromBooster(int packet) + + private boolean collectEnergyPacketFromBooster(int packet, boolean test) { - int energyCollected = 0; - if (booster == null) - { booster = findFirstBooster(); - } - if (booster != null) - { - return booster.consumeEnergy(packet); - } - + if (test) + return packet <= booster.getCurrentEnergyValue(); + else + return booster.consumeEnergy(packet); return false; } From 16c4c993a120ecbb05839cfcb9ddfd810a058f97 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Thu, 5 Dec 2013 22:35:40 +0400 Subject: [PATCH 17/56] Miner fix + silktouch --- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 29 ++++++++++++++++--- src/cr0s/WarpDrive/WarpDrive.java | 2 +- src/cr0s/WarpDrive/WarpDriveConfig.java | 23 ++++++++++++++- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index 152f3f73..12a78e3a 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -30,6 +30,7 @@ import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.ForgeDirection; +import net.minecraftforge.fluids.FluidRegistry; import appeng.api.WorldCoord; import appeng.api.IAEItemStack; import appeng.api.Util; @@ -51,6 +52,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG private int dx, dz, dy; private boolean isMining = false; private boolean isQuarry = false; + private boolean useDeiterium = false; private String[] methodsArray = { @@ -121,10 +123,8 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); int blockID = worldObj.getBlockId(xCoord, currentLayer, zCoord); if (blockID != 0) - if (worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) != Material.water && canDig(blockID)) + if (canDig(blockID)) harvestBlock(new Vector3(xCoord, currentLayer, zCoord)); - else - isMining = false; currentMode = 1; return; } @@ -149,7 +149,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); // Skip if block is too hard or its empty block - if (worldObj.getBlockMaterial(xCoord, currentLayer, zCoord) == Material.water || !canDig(blockID)) + if (!canDig(blockID)) return; sendLaserPacket(minerVector, new Vector3(valuable.intX(), valuable.intY(), valuable.intZ()).add(0.5), 1, 1, 0, 2 * MINE_DELAY, 0, 50); @@ -244,6 +244,23 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG Block block = Block.blocksList[blockID]; if (block == null) return null; + if (useDeiterium) + { + IMEInventoryHandler cellArray = grid.getCellArray(); + if (cellArray != null) + { + int consume = isQuarry?15:1000; + IAEItemStack entryToAEIS = Util.createItemStack(new ItemStack(WarpDriveConfig.i.AEExtraFDI, consume, FluidRegistry.getFluidID("deuterium"))); + long contained = cellArray.countOfItemType(entryToAEIS); + if (block.canSilkHarvest(worldObj, null, i, j, k, blockMeta) && contained >= consume) + { + cellArray.extractItems(entryToAEIS); + ArrayList<ItemStack> t = new ArrayList<ItemStack>(); + t.add(new ItemStack(blockID, 1, blockMeta)); + return t; + } + } + } return block.getBlockDropped(worldObj, i, j, k, blockMeta, 0); } @@ -508,6 +525,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG isMining = tag.getBoolean("isMining"); isQuarry = tag.getBoolean("isQuarry"); currentLayer = tag.getInteger("currentLayer"); + useDeiterium = tag.getBoolean("useDeiterium"); minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); } @@ -518,6 +536,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG tag.setBoolean("isMining", isMining); tag.setBoolean("isQuarry", isQuarry); tag.setInteger("currentLayer", currentLayer); + tag.setBoolean("useDeiterium", useDeiterium); } //CC // IPeripheral methods implementation @@ -547,6 +566,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); currentLayer = yCoord - layerOffset; isMining = true; + useDeiterium = (arguments.length == 1 && FluidRegistry.isFluidRegistered("deuterium")); return new Boolean[] { true }; case 1: // stop() @@ -565,6 +585,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG minerVector = new Vector3(xCoord, yCoord - 1, zCoord).add(0.5); currentLayer = yCoord - layerOffset; isMining = true; + useDeiterium = (arguments.length == 1 && FluidRegistry.isFluidRegistered("deuterium")); return new Boolean[] { true }; case 4: // State is: state, energy, currentLayer, valuablesMined, valuablesInLayer = getMinerState() diff --git a/src/cr0s/WarpDrive/WarpDrive.java b/src/cr0s/WarpDrive/WarpDrive.java index b87b7940..f8df7b6a 100644 --- a/src/cr0s/WarpDrive/WarpDrive.java +++ b/src/cr0s/WarpDrive/WarpDrive.java @@ -34,7 +34,7 @@ import net.minecraftforge.common.ForgeChunkManager.LoadingCallback; import net.minecraftforge.common.ForgeChunkManager.Ticket; import net.minecraftforge.common.MinecraftForge; -@Mod(modid = "WarpDrive", name = "WarpDrive", version = "1.1.5_ZLO", dependencies="required-after:IC2; required-after:ComputerCraft; after:CCTurtle; after:gregtech_addon; after:AppliedEnergistics; after:AdvancedSolarPanel; after:AtomicScience; after:ICBM|Explosion; after:MFFS; after:GraviSuite") +@Mod(modid = "WarpDrive", name = "WarpDrive", version = "1.1.5_ZLO", dependencies="required-after:IC2; after:required-AppliedEnergistics; after:extracells; required-after:ComputerCraft; after:CCTurtle; after:gregtech_addon; after:AdvancedSolarPanel; after:AtomicScience; after:ICBM|Explosion; after:MFFS; after:GraviSuite") @NetworkMod(clientSideRequired = true, serverSideRequired = true, channels = {"WarpDriveBeam", "WarpDriveFreq", "WarpDriveLaserT"}, packetHandler = PacketHandler.class) /** * @author Cr0s diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 8fb5d573..59d31d3b 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -21,7 +21,7 @@ public class WarpDriveConfig private Configuration config; public int coreID, controllerID, radarID, isolationID, airID, airgenID, gasID, laserID, miningLaserID, particleBoosterID, liftID, laserCamID, camID, monitorID, iridiumID; // - public boolean isGregLoaded = false, isAELoaded = false, isAdvSolPanelLoaded = false, isASLoaded = false, isICBMLoaded = false, isMFFSLoaded = false, isGraviSuiteLoaded = false; + public boolean isGregLoaded = false, isAELoaded = false, isAEExtraLoaded = false, isAdvSolPanelLoaded = false, isASLoaded = false, isICBMLoaded = false, isMFFSLoaded = false, isGraviSuiteLoaded = false; // public int[] IC2_Air; public int CC_Computer = 0, CC_peripheral = 0, CCT_Turtle = 0, CCT_Upgraded = 0, CCT_Advanced = 0, GT_Ores = 0, GT_Granite = 0, GT_Machine = 0, ASP = 0, AS_Turbine = 0, ICBM_Machine = 0, ICBM_Missile = 0, MFFS_Field = 0; @@ -30,6 +30,7 @@ public class WarpDriveConfig private Class<?> AEBlocks; private Class<?> AEMaterials; private Class<?> AEItems; + public Item AEExtraFDI; public ArrayList<int[]> CommonWorldGenOres; private WarpDriveConfig() {} @@ -130,6 +131,9 @@ public class WarpDriveConfig isAELoaded = Loader.isModLoaded("AppliedEnergistics"); if (isAELoaded) LoadAE(); + isAEExtraLoaded = Loader.isModLoaded("extracells"); + if (isAEExtraLoaded) + LoadAEExtra(); isAdvSolPanelLoaded = Loader.isModLoaded("AdvancedSolarPanel"); if (isAdvSolPanelLoaded) LoadASP(); @@ -173,6 +177,7 @@ public class WarpDriveConfig CommonWorldGenOres.add(new int[] {Items.getItem("tinOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); MinerOres.add(Items.getItem("rubberWood").itemID); Compot = Items.getItem("advancedAlloy"); + AEExtraFDI = Items.getItem("FluidCell").getItem(); } private void LoadCC() @@ -238,6 +243,22 @@ public class WarpDriveConfig } } + private void LoadAEExtra() + { + try + { + Class<?> z = Class.forName("extracells.ItemEnum"); + Object z1 = z.getEnumConstants()[6]; + AEExtraFDI = (Item)z1.getClass().getDeclaredMethod("getItemEntry").invoke(z1); + } + catch (Exception e) + { + System.out.println("WarpDriveConfig Error loading AEExtra classes"); + e.printStackTrace(); + isAEExtraLoaded = false; + } + } + private void LoadASP() { try From eda76eca77a09e72c65e47dfb8dd61d1369490f4 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Fri, 6 Dec 2013 00:25:25 +0400 Subject: [PATCH 18/56] GraviFix --- src/cr0s/WarpDrive/WarpDriveConfig.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 59d31d3b..83a09a65 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -170,7 +170,9 @@ public class WarpDriveConfig SpaceHelmets.add(Items.getItem("hazmatHelmet").itemID); SpaceHelmets.add(Items.getItem("quantumHelmet").itemID); Jetpacks.add(Items.getItem("jetpack").itemID); +System.out.println("ZLO1 " + Items.getItem("jetpack").itemID); Jetpacks.add(Items.getItem("electricJetpack").itemID); +System.out.println("ZLO1 " + Items.getItem("electricJetpack").itemID); IC2_Air = new int[] {Items.getItem("airCell").itemID, Items.getItem("airCell").getItemDamage()}; CommonWorldGenOres.add(new int[] {Items.getItem("uraniumOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); CommonWorldGenOres.add(new int[] {Items.getItem("copperOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); @@ -332,8 +334,8 @@ public class WarpDriveConfig Class<?> z = Class.forName("gravisuite.GraviSuite"); if (z.getField("ultimateSolarHelmet").get(null) != null) SpaceHelmets.add(((Item)z.getField("ultimateSolarHelmet").get(null)).itemID); - Jetpacks.add(z.getField("advJetpackID").getInt(null)); - Jetpacks.add(z.getField("graviChestPlateID").getInt(null)); + Jetpacks.add(z.getField("advJetpackID").getInt(null) + 256); + Jetpacks.add(z.getField("graviChestPlateID").getInt(null) + 256); } catch (Exception e) { From b2d5d7f1674201089e26014da34c3f416fdbc8cf Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Thu, 12 Dec 2013 03:00:53 +0400 Subject: [PATCH 19/56] FUUU --- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index 12a78e3a..9f48c6f4 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -244,7 +244,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG Block block = Block.blocksList[blockID]; if (block == null) return null; - if (useDeiterium) + if (useDeiterium && grid != null) { IMEInventoryHandler cellArray = grid.getCellArray(); if (cellArray != null) From 09ed8621d2e378eaf10b48feea4ff1d1562f8392 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Wed, 12 Feb 2014 17:07:12 +0400 Subject: [PATCH 20/56] =?UTF-8?q?=D0=9F=D0=BE=D1=81=D0=BB=D0=B5=D0=B4?= =?UTF-8?q?=D0=BD=D0=B8=D0=B9=20=D0=BA=D1=80=D0=BE=D1=81=D0=BE=D0=B0=D0=BF?= =?UTF-8?q?=D0=B4=D0=B5=D0=B9=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cr0s/WarpDrive/BlockAir.java | 471 ++++----- src/cr0s/WarpDrive/BlockCloakingCoil.java | 72 ++ .../WarpDrive/BlockCloakingDeviceCore.java | 98 ++ src/cr0s/WarpDrive/BlockReactor.java | 2 +- src/cr0s/WarpDrive/BlockShipScanner.java | 106 ++ src/cr0s/WarpDrive/CloakChunkWatcher.java | 26 + src/cr0s/WarpDrive/CloakManager.java | 343 +++++++ src/cr0s/WarpDrive/CloakedArea.java | 206 ++++ src/cr0s/WarpDrive/EntityJump.java | 42 +- src/cr0s/WarpDrive/PacketHandler.java | 390 +++++--- src/cr0s/WarpDrive/SpaceEventHandler.java | 66 +- .../WarpDrive/TileEntityAirGenerator.java | 4 +- .../TileEntityCloakingDeviceCore.java | 484 +++++++++ src/cr0s/WarpDrive/TileEntityLaser.java | 27 +- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 17 +- .../WarpDrive/TileEntityParticleBooster.java | 11 +- src/cr0s/WarpDrive/TileEntityProtocol.java | 4 +- src/cr0s/WarpDrive/TileEntityRadar.java | 9 +- src/cr0s/WarpDrive/TileEntityReactor.java | 69 +- src/cr0s/WarpDrive/TileEntityShipScanner.java | 931 ++++++++++++++++++ src/cr0s/WarpDrive/WarpCoresRegistry.java | 6 +- src/cr0s/WarpDrive/WarpDrive.java | 517 +++++----- src/cr0s/WarpDrive/WarpDriveConfig.java | 152 ++- .../WarpDriveCore/WCClassTransformer.java | 53 +- src/cr0s/WarpDriveCore/WCDummyContainer.java | 2 +- .../WarpDriveCore/WCFMLLoadingPlugin.java | 2 +- 26 files changed, 3337 insertions(+), 773 deletions(-) create mode 100644 src/cr0s/WarpDrive/BlockCloakingCoil.java create mode 100644 src/cr0s/WarpDrive/BlockCloakingDeviceCore.java create mode 100644 src/cr0s/WarpDrive/BlockShipScanner.java create mode 100644 src/cr0s/WarpDrive/CloakChunkWatcher.java create mode 100644 src/cr0s/WarpDrive/CloakManager.java create mode 100644 src/cr0s/WarpDrive/CloakedArea.java create mode 100644 src/cr0s/WarpDrive/TileEntityCloakingDeviceCore.java create mode 100644 src/cr0s/WarpDrive/TileEntityShipScanner.java diff --git a/src/cr0s/WarpDrive/BlockAir.java b/src/cr0s/WarpDrive/BlockAir.java index 8546fdb7..1de83d80 100644 --- a/src/cr0s/WarpDrive/BlockAir.java +++ b/src/cr0s/WarpDrive/BlockAir.java @@ -10,278 +10,279 @@ import net.minecraft.world.World; public class BlockAir extends Block { - private final boolean TRANSPARENT_AIR = true; + private final boolean TRANSPARENT_AIR = true; - public BlockAir(int par1) - { - super(par1, Material.air); - } + public BlockAir(int par1) + { + super(par1, Material.air); + } - @Override - public boolean isOpaqueCube() - { - return false; - } + @Override + public boolean isOpaqueCube() + { + return false; + } - @Override - public boolean isAirBlock(World var1, int var2, int var3, int var4) - { - return true; - } + @Override + public boolean isAirBlock(World var1, int var2, int var3, int var4) + { + return true; + } - @Override - public AxisAlignedBB getCollisionBoundingBoxFromPool(World var1, int var2, int var3, int var4) - { - return null; - } + @Override + public AxisAlignedBB getCollisionBoundingBoxFromPool(World var1, int var2, int var3, int var4) + { + return null; + } - @Override - public boolean isBlockReplaceable(World var1, int var2, int var3, int var4) - { - return true; - } + @Override + public boolean isBlockReplaceable(World var1, int var2, int var3, int var4) + { + return true; + } - @Override - public boolean canPlaceBlockAt(World var1, int var2, int var3, int var4) - { - return true; - } + @Override + public boolean canPlaceBlockAt(World var1, int var2, int var3, int var4) + { + return true; + } - @Override - public boolean canCollideCheck(int var1, boolean var2) - { - return false; - } + @Override + public boolean canCollideCheck(int var1, boolean var2) + { + return false; + } - @Override - public int getRenderBlockPass() - { - return TRANSPARENT_AIR ? 1 : 0; - } + @Override + public int getRenderBlockPass() + { + return TRANSPARENT_AIR ? 1 : 0; + } - @Override - public void registerIcons(IconRegister par1IconRegister) - { - this.blockIcon = par1IconRegister.registerIcon("warpdrive:airBlock"); - } + @Override + public void registerIcons(IconRegister par1IconRegister) + { + this.blockIcon = par1IconRegister.registerIcon("warpdrive:airBlock"); + } - @Override - public int getMobilityFlag() - { - return 1; - } + @Override + public int getMobilityFlag() + { + return 1; + } - @Override - public int idDropped(int var1, Random var2, int var3) - { - return -1; - } + @Override + public int idDropped(int var1, Random var2, int var3) + { + return -1; + } - /** - * Returns the quantity of items to drop on block destruction. - */ - @Override - public int quantityDropped(Random par1Random) - { - return 0; - } + /** + * Returns the quantity of items to drop on block destruction. + */ + @Override + public int quantityDropped(Random par1Random) + { + return 0; + } - /** - * How many world ticks before ticking - */ - @Override - public int tickRate(World par1World) - { - return 20; - } + /** + * How many world ticks before ticking + */ + @Override + public int tickRate(World par1World) + { + return 20; + } - /** - * Ticks the block if it's been scheduled - */ - @Override - public void updateTick(World par1World, int x, int y, int z, Random par5Random) - { - int concentration = par1World.getBlockMetadata(x, y, z); - boolean isInSpaceWorld = par1World.provider.dimensionId == WarpDrive.instance.spaceDimID || par1World.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID; + /** + * Ticks the block if it's been scheduled + */ + @Override + public void updateTick(World par1World, int x, int y, int z, Random par5Random) + { + int concentration = par1World.getBlockMetadata(x, y, z); + boolean isInSpaceWorld = par1World.provider.dimensionId == WarpDrive.instance.spaceDimID || par1World.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID; - // Remove air block to vacuum block - if (concentration <= 0 || !isInSpaceWorld) - { - //System.out.println("Killing air block"); - par1World.setBlock(x, y, z, 0, 0, 2); // replace our air block to vacuum block - } - else - { - //System.out.println("Conc: current " + concentration + " new: " + (concentration - 1) + " to spread: " + (concentration - 2)); - // Try to spread the air - spreadAirBlock(par1World, x, y, z, concentration); - } + // Remove air block to vacuum block + if (concentration <= 0 || !isInSpaceWorld) + { + //System.out.println("Killing air block"); + par1World.setBlock(x, y, z, 0, 0, 2); // replace our air block to vacuum block + } + else + { + //System.out.println("Conc: current " + concentration + " new: " + (concentration - 1) + " to spread: " + (concentration - 2)); + // Try to spread the air + spreadAirBlock(par1World, x, y, z, concentration); + } - par1World.scheduleBlockUpdate(x, y, z, this.blockID, 20); - } + par1World.scheduleBlockUpdate(x, y, z, this.blockID, 20); + } - @Override - public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) - { - if (par1IBlockAccess.getBlockId(par2, par3, par4) == this.blockID) - { - return false; - } - else - { - final int i = par1IBlockAccess.getBlockId(par2, par3, par4); - boolean var6 = false; + @Override + public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) + { + if (par1IBlockAccess.getBlockId(par2, par3, par4) == this.blockID) + { + return false; + } + else + { + final int i = par1IBlockAccess.getBlockId(par2, par3, par4); + boolean var6 = false; - if (Block.blocksList[i] != null) - { - var6 = !Block.blocksList[i].isOpaqueCube(); - } + if (Block.blocksList[i] != null) + { + var6 = !Block.blocksList[i].isOpaqueCube(); + } - final boolean var7 = i == 0; + final boolean var7 = i == 0; - if ((var6 || var7) && par5 == 3 && !var6) - { - return true; - } - else if ((var6 || var7) && par5 == 4 && !var6) - { - return true; - } - else if ((var6 || var7) && par5 == 5 && !var6) - { - return true; - } - else if ((var6 || var7) && par5 == 2 && !var6) - { - return true; - } - else if ((var6 || var7) && par5 == 0 && !var6) - { - return true; - } - else if ((var6 || var7) && par5 == 1 && !var6) - { - return true; - } - else - { - return false; - } - } - } + if ((var6 || var7) && par5 == 3 && !var6) + { + return true; + } + else if ((var6 || var7) && par5 == 4 && !var6) + { + return true; + } + else if ((var6 || var7) && par5 == 5 && !var6) + { + return true; + } + else if ((var6 || var7) && par5 == 2 && !var6) + { + return true; + } + else if ((var6 || var7) && par5 == 0 && !var6) + { + return true; + } + else if ((var6 || var7) && par5 == 1 && !var6) + { + return true; + } + else + { + return false; + } + } + } - private void spreadAirBlock(World worldObj, int x, int y, int z, int concentration) - { - if (concentration <= 0) - { - return; - } + private void spreadAirBlock(World worldObj, int x, int y, int z, int concentration) + { + if (concentration <= 0) + { + return; + } - int mid_concentration; - int block_count = 1; - final int K = 128; - mid_concentration = worldObj.getBlockMetadata(x, y, z) * K; + int mid_concentration; + int block_count = 1; + mid_concentration = worldObj.getBlockMetadata(x, y, z); - if (worldObj.isAirBlock(x + 1, y, z)) - { - block_count++; - mid_concentration += worldObj.getBlockMetadata(x + 1, y, z) * K; - } + // Count air in adjacent blocks + if (worldObj.isAirBlock(x + 1, y, z)) + { + block_count++; + mid_concentration += worldObj.getBlockMetadata(x + 1, y, z); + } - if (worldObj.isAirBlock(x - 1, y, z)) - { - block_count++; - mid_concentration += worldObj.getBlockMetadata(x - 1, y, z) * K; - } + if (worldObj.isAirBlock(x - 1, y, z)) + { + block_count++; + mid_concentration += worldObj.getBlockMetadata(x - 1, y, z); + } - if (worldObj.isAirBlock(x, y + 1, z)) - { - block_count++; - mid_concentration += worldObj.getBlockMetadata(x, y + 1, z) * K; - } + if (worldObj.isAirBlock(x, y + 1, z)) + { + block_count++; + mid_concentration += worldObj.getBlockMetadata(x, y + 1, z); + } - if (worldObj.isAirBlock(x, y - 1, z)) - { - block_count++; - mid_concentration += worldObj.getBlockMetadata(x, y - 1, z) * K; - } + if (worldObj.isAirBlock(x, y - 1, z)) + { + block_count++; + mid_concentration += worldObj.getBlockMetadata(x, y - 1, z); + } - if (worldObj.isAirBlock(x, y, z + 1)) - { - block_count++; - mid_concentration += worldObj.getBlockMetadata(x, y, z + 1) * K; - } + if (worldObj.isAirBlock(x, y, z + 1)) + { + block_count++; + mid_concentration += worldObj.getBlockMetadata(x, y, z + 1); + } - if (worldObj.isAirBlock(x, y, z - 1)) - { - block_count++; - mid_concentration += worldObj.getBlockMetadata(x, y, z - 1) * K; - } + if (worldObj.isAirBlock(x, y, z - 1)) + { + block_count++; + mid_concentration += worldObj.getBlockMetadata(x, y, z - 1); + } - mid_concentration = mid_concentration / block_count; - SetAirBlockConcentration(worldObj, x, y, z, mid_concentration / K); + mid_concentration = (int)Math.floor(mid_concentration / block_count); + setNewAirBlockWithConcentration(worldObj, x, y, z, mid_concentration); - if (worldObj.isAirBlock(x + 1, y, z) && (mid_concentration > worldObj.getBlockMetadata(x + 1, y, z) * K)) - { - SetAirBlockConcentration(worldObj, x + 1, y, z, mid_concentration / K); - } + // Check and setup air to adjacent blocks + if (worldObj.isAirBlock(x + 1, y, z) && (mid_concentration > worldObj.getBlockMetadata(x + 1, y, z))) + { + setNewAirBlockWithConcentration(worldObj, x + 1, y, z, mid_concentration); + } - if (worldObj.isAirBlock(x - 1, y, z) && (mid_concentration > worldObj.getBlockMetadata(x - 1, y, z) * K)) - { - SetAirBlockConcentration(worldObj, x - 1, y, z, mid_concentration / K); - } + if (worldObj.isAirBlock(x - 1, y, z) && (mid_concentration > worldObj.getBlockMetadata(x - 1, y, z))) + { + setNewAirBlockWithConcentration(worldObj, x - 1, y, z, mid_concentration); + } - if (worldObj.isAirBlock(x, y + 1, z) && (mid_concentration > worldObj.getBlockMetadata(x, y + 1, z) * K)) - { - SetAirBlockConcentration(worldObj, x, y + 1, z, mid_concentration / K); - } + if (worldObj.isAirBlock(x, y + 1, z) && (mid_concentration > worldObj.getBlockMetadata(x, y + 1, z))) + { + setNewAirBlockWithConcentration(worldObj, x, y + 1, z, mid_concentration); + } - if (worldObj.isAirBlock(x, y - 1, z) && (mid_concentration > worldObj.getBlockMetadata(x, y - 1, z) * K)) - { - SetAirBlockConcentration(worldObj, x, y - 1, z, mid_concentration / K); - } + if (worldObj.isAirBlock(x, y - 1, z) && (mid_concentration > worldObj.getBlockMetadata(x, y - 1, z))) + { + setNewAirBlockWithConcentration(worldObj, x, y - 1, z, mid_concentration); + } - if (worldObj.isAirBlock(x, y, z + 1) && (mid_concentration > worldObj.getBlockMetadata(x, y, z + 1) * K)) - { - SetAirBlockConcentration(worldObj, x, y, z + 1, mid_concentration / K); - } + if (worldObj.isAirBlock(x, y, z + 1) && (mid_concentration > worldObj.getBlockMetadata(x, y, z + 1))) + { + setNewAirBlockWithConcentration(worldObj, x, y, z + 1, mid_concentration); + } - if (worldObj.isAirBlock(x, y, z - 1) && (mid_concentration > worldObj.getBlockMetadata(x, y, z - 1) * K)) - { - SetAirBlockConcentration(worldObj, x, y, z - 1, mid_concentration / K); - } - } + if (worldObj.isAirBlock(x, y, z - 1) && (mid_concentration > worldObj.getBlockMetadata(x, y, z - 1))) + { + setNewAirBlockWithConcentration(worldObj, x, y, z - 1, mid_concentration); + } + } - private void SetAirBlockConcentration(World worldObj, int x, int y, int z, int concentration) - { - worldObj.setBlock(x, y, z, this.blockID, concentration, 2); - } + private void setNewAirBlockWithConcentration(World worldObj, int x, int y, int z, int concentration) + { + worldObj.setBlock(x, y, z, this.blockID, concentration, 2); + } - @Override - public boolean func_82506_l() - { - return false; - } + @Override + public boolean func_82506_l() + { + return false; + } - /** - * Returns if this block is collidable. Args: x, y, z - */ - @Override - public boolean isCollidable() - { - return false; - } + /** + * Returns if this block is collidable. Args: x, y, z + */ + @Override + public boolean isCollidable() + { + return false; + } - @Override - public void onBlockAdded(World par1World, int par2, int par3, int par4) - { - if (par1World.provider.dimensionId == WarpDrive.instance.spaceDimID || par1World.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) - { - par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World)); - } - else - { - par1World.setBlockToAir(par2, par3, par4); - } - } + @Override + public void onBlockAdded(World par1World, int par2, int par3, int par4) + { + if (par1World.provider.dimensionId == WarpDrive.instance.spaceDimID || par1World.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) + { + par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World)); + } + else + { + par1World.setBlockToAir(par2, par3, par4); + } + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/BlockCloakingCoil.java b/src/cr0s/WarpDrive/BlockCloakingCoil.java new file mode 100644 index 00000000..db908dea --- /dev/null +++ b/src/cr0s/WarpDrive/BlockCloakingCoil.java @@ -0,0 +1,72 @@ +package cr0s.WarpDrive; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +import java.util.Random; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockContainer; +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraft.world.World; + +public class BlockCloakingCoil extends Block +{ + private Icon[] iconBuffer; + + public BlockCloakingCoil(int id, int texture, Material material) + { + super(id, material); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IconRegister par1IconRegister) + { + iconBuffer = new Icon[2]; + iconBuffer[0] = par1IconRegister.registerIcon("warpdrive:cloakCoilSide"); + iconBuffer[1] = par1IconRegister.registerIcon("warpdrive:cloakCoilSideActive"); + } + + @Override + public Icon getIcon(int side, int metadata) + { + return iconBuffer[metadata]; + } + + /** + * Returns the quantity of items to drop on block destruction. + */ + @Override + public int quantityDropped(Random par1Random) + { + return 1; + } + + /** + * Returns the ID of the items to drop on destruction. + */ + @Override + public int idDropped(int par1, Random par2Random, int par3) + { + return this.blockID; + } + + @Override + public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) + { + TileEntity te = par1World.getBlockTileEntity(par2, par3, par4); + + if (te != null) + { + te.invalidate(); + } + + super.breakBlock(par1World, par2, par3, par4, par5, par6); + } +} diff --git a/src/cr0s/WarpDrive/BlockCloakingDeviceCore.java b/src/cr0s/WarpDrive/BlockCloakingDeviceCore.java new file mode 100644 index 00000000..f94f4d41 --- /dev/null +++ b/src/cr0s/WarpDrive/BlockCloakingDeviceCore.java @@ -0,0 +1,98 @@ +package cr0s.WarpDrive; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +import java.util.Random; + +import net.minecraft.block.BlockContainer; +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraft.world.World; + +public class BlockCloakingDeviceCore extends BlockContainer +{ + private Icon[] iconBuffer; + + public BlockCloakingDeviceCore(int id, int texture, Material material) + { + super(id, material); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IconRegister par1IconRegister) + { + iconBuffer = new Icon[2]; + iconBuffer[0] = par1IconRegister.registerIcon("warpdrive:cloakingCoreInactive"); + iconBuffer[1] = par1IconRegister.registerIcon("warpdrive:cloakingCoreActive"); + } + + @Override + public Icon getIcon(int side, int metadata) + { + return iconBuffer[metadata]; + } + + @Override + public TileEntity createNewTileEntity(World var1) + { + return new TileEntityCloakingDeviceCore(); + } + + /** + * Returns the quantity of items to drop on block destruction. + */ + @Override + public int quantityDropped(Random par1Random) + { + return 1; + } + + /** + * Returns the ID of the items to drop on destruction. + */ + @Override + public int idDropped(int par1, Random par2Random, int par3) + { + return this.blockID; + } + + @Override + public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) + { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + return false; + } + + TileEntityCloakingDeviceCore me = (TileEntityCloakingDeviceCore)par1World.getBlockTileEntity(par2, par3, par4); + + if (me != null) + { + par5EntityPlayer.addChatMessage("[CloakDeviceCore] Energy level: " + me.getCurrentEnergyValue() + " Eu"); + } + + return true; + } + + @Override + public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) + { + TileEntity te = par1World.getBlockTileEntity(par2, par3, par4); + + if (te != null) + { + if (((TileEntityCloakingDeviceCore)te).isEnabled) + ((TileEntityCloakingDeviceCore)te).disableCloakingField(); + + te.invalidate(); + } + + super.breakBlock(par1World, par2, par3, par4, par5, par6); + } +} diff --git a/src/cr0s/WarpDrive/BlockReactor.java b/src/cr0s/WarpDrive/BlockReactor.java index 1bad6490..83b7c4c5 100644 --- a/src/cr0s/WarpDrive/BlockReactor.java +++ b/src/cr0s/WarpDrive/BlockReactor.java @@ -46,7 +46,7 @@ public class BlockReactor extends BlockContainer return iconBuffer[ICON_TOP]; } - if (metadata == 0) // Inactive state + if (metadata == 0) //Inactive state { return iconBuffer[ICON_INACTIVE_SIDE]; } diff --git a/src/cr0s/WarpDrive/BlockShipScanner.java b/src/cr0s/WarpDrive/BlockShipScanner.java new file mode 100644 index 00000000..7e69bb34 --- /dev/null +++ b/src/cr0s/WarpDrive/BlockShipScanner.java @@ -0,0 +1,106 @@ +package cr0s.WarpDrive; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +import java.util.Random; + +import net.minecraft.block.BlockContainer; +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraft.world.World; + +public class BlockShipScanner extends BlockContainer +{ + private Icon[] iconBuffer; + + public BlockShipScanner(int id, int texture, Material material) + { + super(id, material); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IconRegister par1IconRegister) + { + iconBuffer = new Icon[3]; + iconBuffer[0] = par1IconRegister.registerIcon("warpdrive:shipScannerUp"); + iconBuffer[1] = par1IconRegister.registerIcon("warpdrive:shipScannerSide"); + iconBuffer[2] = par1IconRegister.registerIcon("warpdrive:contBottom"); + } + + @Override + public Icon getIcon(int side, int metadata) + { + if (side == 1) // UP + { + return iconBuffer[0]; + } + else if (side == 0) // DOWN + { + return iconBuffer[2]; + } + + return iconBuffer[1]; + } + + @Override + public TileEntity createNewTileEntity(World var1) + { + return new TileEntityShipScanner(); + } + + /** + * Returns the quantity of items to drop on block destruction. + */ + @Override + public int quantityDropped(Random par1Random) + { + return 1; + } + + /** + * Returns the ID of the items to drop on destruction. + */ + @Override + public int idDropped(int par1, Random par2Random, int par3) + { + return this.blockID; + } + + /** + * Called upon block activation (right click on the block.) + */ + @Override + public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) + { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + return false; + } + + TileEntityShipScanner me = (TileEntityShipScanner)par1World.getBlockTileEntity(par2, par3, par4); + + if (me != null) + { + par5EntityPlayer.addChatMessage("[Ship Scanner] Energy level: " + me.getCurrentEnergyValue()); + } + + return true; + } + + @Override + public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) + { + TileEntity te = par1World.getBlockTileEntity(par2, par3, par4); + + if (te != null) + { + te.invalidate(); + } + } +} \ No newline at end of file diff --git a/src/cr0s/WarpDrive/CloakChunkWatcher.java b/src/cr0s/WarpDrive/CloakChunkWatcher.java new file mode 100644 index 00000000..0c23f044 --- /dev/null +++ b/src/cr0s/WarpDrive/CloakChunkWatcher.java @@ -0,0 +1,26 @@ +package cr0s.WarpDrive; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.packet.Packet56MapChunks; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.event.ForgeSubscribe; +import net.minecraftforge.event.world.ChunkWatchEvent; + +public class CloakChunkWatcher +{ + @ForgeSubscribe + public void chunkLoaded(ChunkWatchEvent event) + { + EntityPlayerMP p = event.player; + ChunkCoordIntPair chunk = event.chunk; + ArrayList<CloakedArea> cloaks = WarpDrive.instance.cloaks.getCloaksForPoint(p.worldObj.provider.dimensionId, chunk.getCenterXPos(), 0, chunk.getCenterZPosition(), true); + if (cloaks.size() == 0) + return; + for (CloakedArea area : cloaks) + area.sendCloakPacketToPlayer(p, false); + } +} diff --git a/src/cr0s/WarpDrive/CloakManager.java b/src/cr0s/WarpDrive/CloakManager.java new file mode 100644 index 00000000..c06e4027 --- /dev/null +++ b/src/cr0s/WarpDrive/CloakManager.java @@ -0,0 +1,343 @@ +package cr0s.WarpDrive; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.network.FMLNetworkHandler; +import cpw.mods.fml.relauncher.Side; +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLeashKnot; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.boss.EntityDragon; +import net.minecraft.entity.item.EntityBoat; +import net.minecraft.entity.item.EntityEnderCrystal; +import net.minecraft.entity.item.EntityEnderEye; +import net.minecraft.entity.item.EntityEnderPearl; +import net.minecraft.entity.item.EntityExpBottle; +import net.minecraft.entity.item.EntityFallingSand; +import net.minecraft.entity.item.EntityFireworkRocket; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.item.EntityItemFrame; +import net.minecraft.entity.item.EntityMinecart; +import net.minecraft.entity.item.EntityPainting; +import net.minecraft.entity.item.EntityTNTPrimed; +import net.minecraft.entity.item.EntityXPOrb; +import net.minecraft.entity.passive.IAnimals; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.projectile.EntityArrow; +import net.minecraft.entity.projectile.EntityEgg; +import net.minecraft.entity.projectile.EntityFireball; +import net.minecraft.entity.projectile.EntityFishHook; +import net.minecraft.entity.projectile.EntityPotion; +import net.minecraft.entity.projectile.EntitySmallFireball; +import net.minecraft.entity.projectile.EntitySnowball; +import net.minecraft.entity.projectile.EntityWitherSkull; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.Packet20NamedEntitySpawn; +import net.minecraft.network.packet.Packet23VehicleSpawn; +import net.minecraft.network.packet.Packet24MobSpawn; +import net.minecraft.network.packet.Packet250CustomPayload; +import net.minecraft.network.packet.Packet25EntityPainting; +import net.minecraft.network.packet.Packet26EntityExpOrb; +import net.minecraft.network.packet.Packet56MapChunks; +import net.minecraft.server.MinecraftServer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; + +/** + * Cloak manager stores cloaking devices covered areas + * @author Cr0s + * + */ + +public class CloakManager +{ + private ArrayList<CloakedArea> cloaks; + + public CloakManager() { + this.cloaks = new ArrayList<CloakedArea>(); + } + + public boolean isInCloak(int dimensionID, int x, int y, int z, boolean chunk) { + for (int i = 0; i < this.cloaks.size(); i++){ + if (this.cloaks.get(i).world == null || this.cloaks.get(i).world.provider.dimensionId != dimensionID) + continue; + + AxisAlignedBB axisalignedbb = this.cloaks.get(i).aabb; + + if (axisalignedbb.minX <= (double) x && axisalignedbb.maxX >= (double) x && (chunk || (axisalignedbb.minY <= (double) y && axisalignedbb.maxY >= (double) y)) && axisalignedbb.minZ <= (double) z && axisalignedbb.maxZ >= (double) z) { + return true; + } + } + + return false; + } + + public ArrayList<CloakedArea> getCloaksForPoint(int dimensionID, int x, int y, int z, boolean chunk) { + ArrayList<CloakedArea> res = new ArrayList<CloakedArea>(); + + for (int i = 0; i < this.cloaks.size(); i++){ + if (this.cloaks.get(i).world == null || this.cloaks.get(i).world.provider.dimensionId != dimensionID) + continue; + + AxisAlignedBB axisalignedbb = this.cloaks.get(i).aabb; + //System.outprint("[Cloak] checking (" + x + "; " + y + "; " + z + ") -> " + this.cloaks.get(i).aabb); + if (axisalignedbb.minX <= (double) x && axisalignedbb.maxX >= (double) x && (chunk || (axisalignedbb.minY <= (double) y && axisalignedbb.maxY >= (double) y)) && axisalignedbb.minZ <= (double) z && axisalignedbb.maxZ >= (double) z) { + res.add(cloaks.get(i)); + //System.outprintln(": YES"); + }// else + //System.outprintln(": NO"); + } + + return res; + } + + public boolean isAreaExists(int frequency) { + for (int i = 0; i < this.cloaks.size(); i++){ + if (this.cloaks.get(i).frequency == frequency) + return true; + } + + return false; + } + + public void addCloakedAreaWorld(World worldObj, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, int frequency, byte tier) { + cloaks.add(new CloakedArea(worldObj, frequency, AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ), tier)); + } + + public void removeCloakedArea(int frequency) { + int index = 0; + for (int i = 0; i < this.cloaks.size(); i++){ + if (this.cloaks.get(i).frequency == frequency) { + this.cloaks.get(i).sendCloakPacketToPlayersEx(true); // send info about collapsing cloaking field + index = i; + break; + } + } + + cloaks.remove(index); + } + + public CloakedArea getCloakedArea(int frequency) { + for (CloakedArea area : this.cloaks) { + if (area.frequency == frequency) + return area; + } + + return null; + } + + public void playerEnteringCloakedArea(CloakedArea area, EntityPlayer player) { + area.playersInArea.add(player); + revealChunksToPlayer(area, player); + revealEntityToPlayer(area, player); + area.sendCloakPacketToPlayer(player, false); + } + + public void revealEntityToPlayer(CloakedArea area, EntityPlayer p) { + List<Entity> list = p.worldObj.getEntitiesWithinAABBExcludingEntity(p, area.aabb); + + for (Entity e : list) { + ((EntityPlayerMP)p).playerNetServerHandler.sendPacketToPlayer(getPacketForThisEntity(e)); + } + } + + public void checkPlayerLeavedArea(EntityPlayer p) { + for (CloakedArea area : this.cloaks) { + if (!area.isPlayerWithinArea(p) && area.isPlayerInArea(p)) { + area.removePlayerFromArea(p); + //System.outprintln("[Cloak] Player " + p.username + " has leaved cloaked area " + area.frequency); + MinecraftServer.getServer().getConfigurationManager().sendToAllNearExcept(p, p.posX, p.posY, p.posZ, 100, p.worldObj.provider.dimensionId, getPacketForThisEntity(p)); + area.sendCloakPacketToPlayer(p, false); + } + } + } + + public void revealChunksToPlayer(CloakedArea area, EntityPlayer p) { + //System.outprintln("[Cloak] Revealing cloaked chunks in area " + area.frequency + " to player " + p.username); + for (int x = (int)area.aabb.minX; x < (int)area.aabb.maxX; x++) + for (int z = (int)area.aabb.minZ; z < (int)area.aabb.maxZ; z++) + for (int y = (int)area.aabb.minY; y < (int)area.aabb.maxY; y++) { + if (p.worldObj.getBlockId(x, y, z) != 0) + p.worldObj.markBlockForUpdate(x, y, z); + } + /*ArrayList<Chunk> chunksToSend = new ArrayList<Chunk>(); + + for (int x = (int)area.aabb.minX >> 4; x <= (int)area.aabb.maxX >> 4; x++) + for (int z = (int)area.aabb.minZ >> 4; z <= (int)area.aabb.maxZ >> 4; z++) { + chunksToSend.add(p.worldObj.getChunkFromChunkCoords(x, z)); + } + + //System.outprintln("[Cloak] Sending " + chunksToSend.size() + " chunks to player " + p.username); + ((EntityPlayerMP)p).playerNetServerHandler.sendPacketToPlayer(new Packet56MapChunks(chunksToSend)); + + //System.outprintln("[Cloak] Sending decloak packet to player " + p.username); + area.sendCloakPacketToPlayer(p, true); // decloak = true + */ + } + + private Packet getPacketForThisEntity(Entity e) + { + if (e.isDead) + { + e.worldObj.getWorldLogAgent().logWarning("Fetching addPacket for removed entity"); + } + + Packet pkt = FMLNetworkHandler.getEntitySpawningPacket(e); + + if (pkt != null) + { + return pkt; + } + + if (e instanceof EntityItem) + { + return new Packet23VehicleSpawn(e, 2, 1); + } + else if (e instanceof EntityPlayerMP) + { + return new Packet20NamedEntitySpawn((EntityPlayer)e); + } + else if (e instanceof EntityMinecart) + { + EntityMinecart entityminecart = (EntityMinecart)e; + return new Packet23VehicleSpawn(e, 10, entityminecart.getMinecartType()); + } + else if (e instanceof EntityBoat) + { + return new Packet23VehicleSpawn(e, 1); + } + else if (!(e instanceof IAnimals) && !(e instanceof EntityDragon)) + { + if (e instanceof EntityFishHook) + { + EntityPlayer entityplayer = ((EntityFishHook)e).angler; + return new Packet23VehicleSpawn(e, 90, entityplayer != null ? entityplayer.entityId : e.entityId); + } + else if (e instanceof EntityArrow) + { + Entity entity = ((EntityArrow)e).shootingEntity; + return new Packet23VehicleSpawn(e, 60, entity != null ? entity.entityId : e.entityId); + } + else if (e instanceof EntitySnowball) + { + return new Packet23VehicleSpawn(e, 61); + } + else if (e instanceof EntityPotion) + { + return new Packet23VehicleSpawn(e, 73, ((EntityPotion)e).getPotionDamage()); + } + else if (e instanceof EntityExpBottle) + { + return new Packet23VehicleSpawn(e, 75); + } + else if (e instanceof EntityEnderPearl) + { + return new Packet23VehicleSpawn(e, 65); + } + else if (e instanceof EntityEnderEye) + { + return new Packet23VehicleSpawn(e, 72); + } + else if (e instanceof EntityFireworkRocket) + { + return new Packet23VehicleSpawn(e, 76); + } + else + { + Packet23VehicleSpawn packet23vehiclespawn; + + if (e instanceof EntityFireball) + { + EntityFireball entityfireball = (EntityFireball)e; + packet23vehiclespawn = null; + byte b0 = 63; + + if (e instanceof EntitySmallFireball) + { + b0 = 64; + } + else if (e instanceof EntityWitherSkull) + { + b0 = 66; + } + + if (entityfireball.shootingEntity != null) + { + packet23vehiclespawn = new Packet23VehicleSpawn(e, b0, ((EntityFireball)e).shootingEntity.entityId); + } + else + { + packet23vehiclespawn = new Packet23VehicleSpawn(e, b0, 0); + } + + packet23vehiclespawn.speedX = (int)(entityfireball.accelerationX * 8000.0D); + packet23vehiclespawn.speedY = (int)(entityfireball.accelerationY * 8000.0D); + packet23vehiclespawn.speedZ = (int)(entityfireball.accelerationZ * 8000.0D); + return packet23vehiclespawn; + } + else if (e instanceof EntityEgg) + { + return new Packet23VehicleSpawn(e, 62); + } + else if (e instanceof EntityTNTPrimed) + { + return new Packet23VehicleSpawn(e, 50); + } + else if (e instanceof EntityEnderCrystal) + { + return new Packet23VehicleSpawn(e, 51); + } + else if (e instanceof EntityFallingSand) + { + EntityFallingSand entityfallingsand = (EntityFallingSand)e; + return new Packet23VehicleSpawn(e, 70, entityfallingsand.blockID | entityfallingsand.metadata << 16); + } + else if (e instanceof EntityPainting) + { + return new Packet25EntityPainting((EntityPainting)e); + } + else if (e instanceof EntityItemFrame) + { + EntityItemFrame entityitemframe = (EntityItemFrame)e; + packet23vehiclespawn = new Packet23VehicleSpawn(e, 71, entityitemframe.hangingDirection); + packet23vehiclespawn.xPosition = MathHelper.floor_float((float)(entityitemframe.xPosition * 32)); + packet23vehiclespawn.yPosition = MathHelper.floor_float((float)(entityitemframe.yPosition * 32)); + packet23vehiclespawn.zPosition = MathHelper.floor_float((float)(entityitemframe.zPosition * 32)); + return packet23vehiclespawn; + } + else if (e instanceof EntityLeashKnot) + { + EntityLeashKnot entityleashknot = (EntityLeashKnot)e; + packet23vehiclespawn = new Packet23VehicleSpawn(e, 77); + packet23vehiclespawn.xPosition = MathHelper.floor_float((float)(entityleashknot.xPosition * 32)); + packet23vehiclespawn.yPosition = MathHelper.floor_float((float)(entityleashknot.yPosition * 32)); + packet23vehiclespawn.zPosition = MathHelper.floor_float((float)(entityleashknot.zPosition * 32)); + return packet23vehiclespawn; + } + else if (e instanceof EntityXPOrb) + { + return new Packet26EntityExpOrb((EntityXPOrb)e); + } + else + { + throw new IllegalArgumentException("Don\'t know how to add " + e.getClass() + "!"); + } + } + } + else + { + return new Packet24MobSpawn((EntityLivingBase)e); + } + } +} diff --git a/src/cr0s/WarpDrive/CloakedArea.java b/src/cr0s/WarpDrive/CloakedArea.java new file mode 100644 index 00000000..dbae7818 --- /dev/null +++ b/src/cr0s/WarpDrive/CloakedArea.java @@ -0,0 +1,206 @@ +package cr0s.WarpDrive; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.util.LinkedList; +import java.util.List; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.network.FMLNetworkHandler; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.network.packet.Packet250CustomPayload; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; + +public class CloakedArea +{ + public int frequency; + public AxisAlignedBB aabb; + public LinkedList<EntityPlayer> playersInArea; + public byte tier = 0; + public World world = null; + + public boolean isPlayerInArea(EntityPlayer player) { + for (EntityPlayer p : this.playersInArea) { + //System.outprintln("[Cloak] Checking player: " + p.username + "(" + p.entityId + ")" + " =? " + player.username + " (" + p.entityId + ")"); + if (p.username.equals(player.username)) + return true; + } + + return false; + } + + public void removePlayerFromArea(EntityPlayer p) { + for (int i = 0; i < this.playersInArea.size(); i++) { + if (this.playersInArea.get(i).username.equals(p.username)) { + this.playersInArea.remove(i); + return; + } + } + } + + public boolean isPlayerWithinArea(EntityPlayer player) { + return (aabb.minX <= player.posX && aabb.maxX >= player.posX && aabb.minY <= player.posY && aabb.maxY >= player.posY && aabb.minZ <= player.posZ && aabb.maxZ >= player.posZ); + } + + public CloakedArea(World worldObj, int frequency, AxisAlignedBB aabb, byte tier) { + this.frequency = frequency; + this.aabb = aabb; + this.tier = tier; + this.playersInArea = new LinkedList<EntityPlayer>(); + + if (worldObj == null || aabb == null) + return; + + this.world = worldObj; + + if (this.world == null) + return; + + try { + // Added all players, who inside the field + List<Entity> list = worldObj.getEntitiesWithinAABB(EntityPlayerMP.class, this.aabb); + for (Entity e : list) { + if (e instanceof EntityPlayer) + this.playersInArea.add((EntityPlayer)e); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public Chunk obscureChunkBlocksWithinArea(Chunk chunk) { + for (int x = (int)this.aabb.minX; x < (int)this.aabb.maxX; x++) + for (int z = (int)this.aabb.minZ; z < (int)this.aabb.maxZ; z++) + for (int y = (int)this.aabb.minY; y < (int)this.aabb.maxY; y++) { + myChunkSBIDWMT(chunk, x & 15, y, z & 15, 0, 0); + } + + return chunk; + } + + // Sending only if field changes: sets up or collapsing + public void sendCloakPacketToPlayersEx(boolean decloak) { + final int RADIUS = 250; + + double midX = this.aabb.minX + (Math.abs(this.aabb.maxX - this.aabb.minX) / 2); + double midY = this.aabb.minY + (Math.abs(this.aabb.maxY - this.aabb.minY) / 2); + double midZ = this.aabb.minZ + (Math.abs(this.aabb.maxZ - this.aabb.minZ) / 2); + + for (int j = 0; j < MinecraftServer.getServer().getConfigurationManager().playerEntityList.size(); ++j) + { + EntityPlayerMP entityplayermp = (EntityPlayerMP)MinecraftServer.getServer().getConfigurationManager().playerEntityList.get(j); + + if (entityplayermp.dimension == this.world.provider.dimensionId) + { + double d4 = midX - entityplayermp.posX; + double d5 = midY - entityplayermp.posY; + double d6 = midZ - entityplayermp.posZ; + + if (d4 * d4 + d5 * d5 + d6 * d6 < RADIUS * RADIUS) + { + if (decloak) { + WarpDrive.instance.cloaks.revealChunksToPlayer(this, (EntityPlayer)entityplayermp); + WarpDrive.instance.cloaks.revealEntityToPlayer(this, (EntityPlayer)entityplayermp); + } + + if (!isPlayerWithinArea((EntityPlayer)entityplayermp) && !decloak) + sendCloakPacketToPlayer((EntityPlayer)entityplayermp, false); + else if (decloak) { + sendCloakPacketToPlayer((EntityPlayer)entityplayermp, true); + } + } + } + } + } + + public void sendCloakPacketToPlayer(EntityPlayer player, boolean decloak) { + //System.outprintln("[Cloak] Sending cloak packet to player " + player.username); + if (isPlayerInArea(player)) { + //System.outprintln("[Cloak] Player " + player.username + " is inside cloaking field"); + return; + } + + ByteArrayOutputStream bos = new ByteArrayOutputStream(8); + DataOutputStream outputStream = new DataOutputStream(bos); + + try + { + outputStream.writeInt((int) this.aabb.minX); + outputStream.writeInt((int) this.aabb.minY); + outputStream.writeInt((int) this.aabb.minZ); + + outputStream.writeInt((int) this.aabb.maxX); + outputStream.writeInt((int) this.aabb.maxY); + outputStream.writeInt((int) this.aabb.maxZ); + + outputStream.writeBoolean(decloak); + + outputStream.writeByte(this.tier); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + Packet250CustomPayload packet = new Packet250CustomPayload(); + packet.channel = "WarpDriveCloaks"; + packet.data = bos.toByteArray(); + packet.length = bos.size(); + + ((EntityPlayerMP)player).playerNetServerHandler.sendPacketToPlayer(packet); + } + + public boolean myChunkSBIDWMT(Chunk c, int x, int y, int z, int blockId, int blockMeta) + { + int j1 = z << 4 | x; + + if (y >= c.precipitationHeightMap[j1] - 1) + { + c.precipitationHeightMap[j1] = -999; + } + + int l1 = c.getBlockID(x, y, z); + int i2 = c.getBlockMetadata(x, y, z); + + if (l1 == blockId && i2 == blockMeta) + { + return false; + } + else + { + ExtendedBlockStorage[] storageArrays = c.getBlockStorageArray(); + ExtendedBlockStorage extendedblockstorage = storageArrays[y >> 4]; + + if (extendedblockstorage == null) + { + if (blockId == 0) + { + return false; + } + + extendedblockstorage = storageArrays[y >> 4] = new ExtendedBlockStorage(y >> 4 << 4, !c.worldObj.provider.hasNoSky); + } + + int j2 = c.xPosition * 16 + x; + int k2 = c.zPosition * 16 + z; + extendedblockstorage.setExtBlockID(x, y & 15, z, blockId); + + if (extendedblockstorage.getExtBlockID(x, y & 15, z) != blockId) + { + return false; + } + else + { + extendedblockstorage.setExtBlockMetadata(x, y & 15, z, blockMeta); + c.isModified = true; + return true; + } + } + } +} diff --git a/src/cr0s/WarpDrive/EntityJump.java b/src/cr0s/WarpDrive/EntityJump.java index 5cd27efe..64055e2c 100644 --- a/src/cr0s/WarpDrive/EntityJump.java +++ b/src/cr0s/WarpDrive/EntityJump.java @@ -384,7 +384,6 @@ public class EntityJump extends Entity moveY = movementVector[1] * distance; moveZ = movementVector[2] * distance; - // Нужно не упереться в пол мира и потолок космоса if ((maxY + moveY) > 255) { moveY = 255 - maxY; @@ -654,9 +653,6 @@ public class EntityJump extends Entity return testDistance; } - /* - * Получить реальное количество блоков, из которых состоит корабль - */ public int getRealShipSize() { LocalProfiler.start("EntityJump.getRealShipSize"); @@ -706,19 +702,10 @@ public class EntityJump extends Entity Entity entity = (Entity)o; MovingEntity movingEntity = new MovingEntity(entity); - // Добавим в список Entity entitiesOnShip.add(movingEntity); } } - /** - * Перемещение сущностей вместе с кораблем - * @param axisalignedbb область корабля - * @param distance расстояние перемещения - * @param direction направление перемещения - * @param restorePositions восстановление старых позиций для предотвращения выпадения, либо перемещение на новую - * @return - */ public boolean moveEntities(boolean restorePositions) { System.out.println("[JE] Moving entities"); @@ -779,7 +766,6 @@ public class EntityJump extends Entity if (entity instanceof EntityPlayerMP) { EntityPlayerMP player = (EntityPlayerMP) entity; - // Если на корабле есть кровать, то передвинуть точку спауна игрока ChunkCoordinates bedLocation = player.getBedLocation(); if (bedLocation != null && testBB(axisalignedbb, bedLocation.posX, bedLocation.posY, bedLocation.posZ)) @@ -802,15 +788,11 @@ public class EntityJump extends Entity return true; } - /** - * Проверка на вхождение точки в область (bounding-box) - */ public boolean testBB(AxisAlignedBB axisalignedbb, int x, int y, int z) { return axisalignedbb.minX <= (double) x && axisalignedbb.maxX >= (double) x && axisalignedbb.minY <= (double) y && axisalignedbb.maxY >= (double) y && axisalignedbb.minZ <= (double) z && axisalignedbb.maxZ >= (double) z; } - // Получение вектора в зависимости от направления прыжка public int[] getVector(int i) { int v[] = @@ -851,13 +833,6 @@ public class EntityJump extends Entity return v; } - /** - * Проверка возможности установки корабля в месте, удалённом от корабля на - * определённом расстоянии в сторону прыжка - * - * @param i - * @return true, если корабль уместился на новом месте - */ public boolean checkMovement(int testDistance) { if ((dir == -1 && maxY + testDistance > 255) && !toSpace) @@ -919,23 +894,11 @@ public class EntityJump extends Entity return true; } - /** - * Точка находится в варп-поле корабля? - * - * @param x - * @param y - * @param z - * @return true, если находится - */ public boolean isBlockInShip(int x, int y, int z) { return x >= minX && x <= maxX && y >= minY && y <= maxY && z >= minZ && z <= maxZ; } - /** - * Выключение модема, если периферийное устройство является модемом - * @param p - периферийное устройство - */ private void turnOffModem(IPeripheral p) { // FIXME @@ -954,9 +917,6 @@ public class EntityJump extends Entity }*/ } - /** - * Выключение всех модемов на корабле - */ private void turnOffModems() { // FIXME @@ -1109,7 +1069,7 @@ public class EntityJump extends Entity //System.out.println("[JE@"+this+"] writeEntityToNBT()"); } - // Own implementation of setting blocks withow light recalculation in optimization purposes + // Own implementation of setting blocks without light recalculation in optimization purposes public boolean mySetBlock(World w, int x, int y, int z, int blockId, int blockMeta, int par6) { if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) diff --git a/src/cr0s/WarpDrive/PacketHandler.java b/src/cr0s/WarpDrive/PacketHandler.java index d76842d7..508a02fd 100644 --- a/src/cr0s/WarpDrive/PacketHandler.java +++ b/src/cr0s/WarpDrive/PacketHandler.java @@ -3,165 +3,285 @@ package cr0s.WarpDrive; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; +import java.util.List; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.network.INetworkManager; import net.minecraft.network.packet.Packet250CustomPayload; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; import net.minecraft.world.ChunkPosition; import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; import cpw.mods.fml.common.network.IPacketHandler; import cpw.mods.fml.common.network.Player; +import net.minecraft.client.multiplayer.WorldClient; public class PacketHandler implements IPacketHandler { - @Override - public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) - { - if (packet.channel.equals("WarpDriveBeam")) - { - handleBeam(packet, (EntityPlayer)player); - } - else if (packet.channel.equals("WarpDriveFreq")) - { - handleFreqUpdate(packet, (EntityPlayer)player); - } - else if (packet.channel.equals("WarpDriveLaserT")) - { - handleLaserTargeting(packet, (EntityPlayer)player); - } - } + @Override + public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) + { + if (packet.channel.equals("WarpDriveBeam")) + { + handleBeam(packet, (EntityPlayer)player); + } + else if (packet.channel.equals("WarpDriveFreq")) + { + handleFreqUpdate(packet, (EntityPlayer)player); + } + else if (packet.channel.equals("WarpDriveLaserT")) + { + handleLaserTargeting(packet, (EntityPlayer)player); + } + else if (packet.channel.equals("WarpDriveCloaks")) + { + handleCloak(packet, (EntityPlayer)player); + } + } - public void handleLaserTargeting(Packet250CustomPayload packet, EntityPlayer player) - { - DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); + public void handleCloak(Packet250CustomPayload packet, EntityPlayer player) { + DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); - try - { - int x = inputStream.readInt(); - int y = inputStream.readInt(); - int z = inputStream.readInt(); - float yaw = inputStream.readFloat(); - float pitch = inputStream.readFloat(); - System.out.println("Got target packet: (" + x + "; " + y + "; " + z + ") | yaw: " + yaw + " | pitch: " + pitch); - TileEntity te = player.worldObj.getBlockTileEntity(x, y, z); + try + { + // Read cloaked area parameters + int minX = inputStream.readInt(); + int minY = inputStream.readInt(); + int minZ = inputStream.readInt(); + + int maxX = inputStream.readInt(); + int maxY = inputStream.readInt(); + int maxZ = inputStream.readInt(); + + boolean decloak = inputStream.readBoolean(); + + byte tier = inputStream.readByte(); + + int w = Math.abs(maxX - minX); + int h = Math.abs(maxY - minY); + int l = Math.abs(maxZ - minZ); + + //(-2099; 208; 423) -> (-2069; 243; 453) + // + int size = w * h * l; + + //System.out.println("[Cloak Packet] Received " + ((decloak) ? "DEcloaked" : "cloaked") + "area: (" + minX + "; " + minY + "; " + minZ + ") -> (" + maxX + "; " + maxY + "; " + maxZ + ")"); + + if (minX <= player.chunkCoordX && maxX >= player.chunkCoordY && minY <= player.chunkCoordY && maxY >= player.chunkCoordY && minZ <= player.chunkCoordZ && maxZ >= player.chunkCoordZ) + return; + + // Hide the area + if (!decloak) + { + //System.out.println("[Cloak Packet] Removing " + size + " blocks..."); + + // Now hide the blocks within area + World worldObj = player.worldObj; + for (int y = minY; y <= maxY; y++) + for (int x = minX; x <= maxX; x++) + for(int z = minZ; z <= maxZ; z++) + if (worldObj.getBlockId(x, y, z) != 0) + worldObj.setBlock(x, y, z, (tier == 1) ? WarpDriveConfig.i.gasID : 0, 5, 4); + + //System.out.println("[Cloak Packet] Removing entity..."); + // Hide any entities inside area + AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ); + List<Entity> list = worldObj.getEntitiesWithinAABBExcludingEntity(player, aabb); + for (Entity e : list) + { + worldObj.removeEntity(e); + ((WorldClient)worldObj).removeEntityFromWorld(e.entityId); + } + } + else + { // reveal the area + player.worldObj.markBlockRangeForRenderUpdate(minX, minY, minZ, maxX, maxY, maxZ); + + // Make some graphics + int numLasers = 25 + player.worldObj.rand.nextInt(300); + + for (int i = 0; i < numLasers; i++) + { + int randX1 = minX + player.worldObj.rand.nextInt(maxX - minX); + int randX2 = minX + player.worldObj.rand.nextInt(maxX - minX); + + int randY1 = minY + player.worldObj.rand.nextInt(maxY - minY); + int randY2 = minY + player.worldObj.rand.nextInt(maxY - minY); + + int randZ1 = minZ + player.worldObj.rand.nextInt(maxZ - minZ); + int randZ2 = minZ + player.worldObj.rand.nextInt(maxZ - minZ); + + float r = 0, g = 0, b = 0; + + switch (player.worldObj.rand.nextInt(6)) + { + case 0: + r = 1.0f; + g = b = 0; + break; + case 1: + r = b = 0; + g = 1.0f; + break; + case 2: + r = g = 0; + b = 1.0f; + break; + case 3: + r = b = 0.5f; + g = 0; + break; + case 4: + r = g = 1.0f; + b = 0; + break; + case 5: + r = 1.0f; + b = 0.5f; + g = 0f; + } + WarpDrive.proxy.renderBeam(player.worldObj, new Vector3(randX1, randY1, randZ1), new Vector3(randX2, randY2, randZ2), r, g, b, 10, 100); + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + public void handleLaserTargeting(Packet250CustomPayload packet, EntityPlayer player) + { + DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); - if (te != null) - { - System.out.println("TE is NULL"); + try + { + int x = inputStream.readInt(); + int y = inputStream.readInt(); + int z = inputStream.readInt(); + float yaw = inputStream.readFloat(); + float pitch = inputStream.readFloat(); + System.out.println("Got target packet: (" + x + "; " + y + "; " + z + ") | yaw: " + yaw + " | pitch: " + pitch); + TileEntity te = player.worldObj.getBlockTileEntity(x, y, z); - if (te instanceof TileEntityLaser) - { - TileEntityLaser l = (TileEntityLaser)te; - l.yaw = yaw; - l.pitch = pitch; - l.delayTicks = 0; - l.isEmitting = true; - } - } - } - catch (Exception e) - { - e.printStackTrace(); - } - } + if (te != null) + { + System.out.println("TE is NULL"); - public void handleFreqUpdate(Packet250CustomPayload packet, EntityPlayer player) - { - DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); + if (te instanceof TileEntityLaser) + { + TileEntityLaser l = (TileEntityLaser)te; + l.yaw = yaw; + l.pitch = pitch; + l.delayTicks = 0; + l.isEmitting = true; + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } - try - { - int x = inputStream.readInt(); - int y = inputStream.readInt(); - int z = inputStream.readInt(); - int freq = inputStream.readInt(); - //System.out.println("Got freq packet: (" + x + "; " + y + "; " + z + ") | freq: " + freq); - TileEntity te = player.worldObj.getBlockTileEntity(x, y, z); + public void handleFreqUpdate(Packet250CustomPayload packet, EntityPlayer player) + { + DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); - if (te != null) - { - if (te instanceof TileEntityMonitor) - { - ((TileEntityMonitor)te).setFrequency(freq); - } - else if (te instanceof TileEntityCamera) - { - ((TileEntityCamera)te).setFrequency(freq); - WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(freq, new ChunkPosition(x, y, z), player.worldObj).setType(0)); - } - else if (te instanceof TileEntityLaser) - { - ((TileEntityLaser)te).camFreq = freq; - WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(freq, new ChunkPosition(x, y, z), player.worldObj).setType(1)); - } - } - } - catch (Exception e) - { - e.printStackTrace(); - } - } + try + { + int x = inputStream.readInt(); + int y = inputStream.readInt(); + int z = inputStream.readInt(); + int freq = inputStream.readInt(); + //System.out.println("Got freq packet: (" + x + "; " + y + "; " + z + ") | freq: " + freq); + TileEntity te = player.worldObj.getBlockTileEntity(x, y, z); - private void handleBeam(Packet250CustomPayload packet, EntityPlayer player) - { - DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); - int dimID; - Vector3 source, target; - double sx, sy, sz; - double tx, ty, tz; - float r, g, b; - int age; - int energy; - World worldObj = player.worldObj; + if (te != null) + { + if (te instanceof TileEntityMonitor) + { + ((TileEntityMonitor)te).setFrequency(freq); + } + else if (te instanceof TileEntityCamera) + { + ((TileEntityCamera)te).setFrequency(freq); + WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(freq, new ChunkPosition(x, y, z), player.worldObj).setType(0)); + } + else if (te instanceof TileEntityLaser) + { + ((TileEntityLaser)te).camFreq = freq; + WarpDrive.instance.cams.updateInRegistry(new CamRegistryItem(freq, new ChunkPosition(x, y, z), player.worldObj).setType(1)); + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } - try - { - // Read source vector - sx = inputStream.readDouble(); - sy = inputStream.readDouble(); - sz = inputStream.readDouble(); - source = new Vector3(sx, sy, sz); - // Read target vector - tx = inputStream.readDouble(); - ty = inputStream.readDouble(); - tz = inputStream.readDouble(); - target = new Vector3(tx, ty, tz); - // Read r, g, b of laser - r = inputStream.readFloat(); - g = inputStream.readFloat(); - b = inputStream.readFloat(); - // Read age - age = inputStream.readByte(); - // Read energy value - energy = inputStream.readInt(); + private void handleBeam(Packet250CustomPayload packet, EntityPlayer player) + { + DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); + int dimID; + Vector3 source, target; + double sx, sy, sz; + double tx, ty, tz; + float r, g, b; + int age; + int energy; + World worldObj = player.worldObj; - // Render beam - /*System.out.println("sx: " + sx + " sy: " + sy + " sz: " + sz); - System.out.println("tx: " + sx + " ty: " + sy + " tz: " + sz); + try + { + // Read source vector + sx = inputStream.readDouble(); + sy = inputStream.readDouble(); + sz = inputStream.readDouble(); + source = new Vector3(sx, sy, sz); + // Read target vector + tx = inputStream.readDouble(); + ty = inputStream.readDouble(); + tz = inputStream.readDouble(); + target = new Vector3(tx, ty, tz); + // Read r, g, b of laser + r = inputStream.readFloat(); + g = inputStream.readFloat(); + b = inputStream.readFloat(); + // Read age + age = inputStream.readByte(); + // Read energy value + energy = inputStream.readInt(); - System.out.println("source: " + source); - System.out.println("target: " + target); - System.out.println("r: " + r); - System.out.println("g: " + g); - System.out.println("b " + b); - System.out.println("age: " + age); - System.out.println("energy: " + energy);*/ + // Render beam + /*System.out.println("sx: " + sx + " sy: " + sy + " sz: " + sz); + System.out.println("tx: " + sx + " ty: " + sy + " tz: " + sz); - // To avoid NPE at logging in - if (worldObj == null) - { - System.out.println("WorldObj is null"); - return; - } + System.out.println("source: " + source); + System.out.println("target: " + target); + System.out.println("r: " + r); + System.out.println("g: " + g); + System.out.println("b " + b); + System.out.println("age: " + age); + System.out.println("energy: " + energy);*/ - WarpDrive.proxy.renderBeam(worldObj, source.clone(), target.clone(), r, g, b, age, energy); - } - catch (IOException e) - { - e.printStackTrace(); - return; - } - } + // To avoid NPE at logging in + if (worldObj == null) + { + System.out.println("WorldObj is null"); + return; + } + + WarpDrive.proxy.renderBeam(worldObj, source.clone(), target.clone(), r, g, b, age, energy); + } + catch (IOException e) + { + e.printStackTrace(); + return; + } + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/SpaceEventHandler.java b/src/cr0s/WarpDrive/SpaceEventHandler.java index b34ba19d..d761ca10 100644 --- a/src/cr0s/WarpDrive/SpaceEventHandler.java +++ b/src/cr0s/WarpDrive/SpaceEventHandler.java @@ -1,6 +1,7 @@ package cr0s.WarpDrive; import java.util.HashMap; +import java.util.List; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; @@ -19,10 +20,16 @@ import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; public class SpaceEventHandler { private HashMap<String, Integer> vacuumPlayers; - + private HashMap<String, Integer> cloakPlayersTimers; + private long lastTimer = 0; + + private final int CLOAK_CHECK_TIMEOUT_SEC = 5; + public SpaceEventHandler() { vacuumPlayers = new HashMap<String, Integer>(); + cloakPlayersTimers = new HashMap<String, Integer>(); + this.lastTimer = 0; } @ForgeSubscribe @@ -43,8 +50,10 @@ public class SpaceEventHandler entity.attackEntityFrom(DamageSource.outOfWorld, 9000); return; } + if (entity instanceof EntityPlayerMP) + updatePlayerCloakState(entity); - // Обновление происходит в космическом или гипер пространстве + // If player in vaccum, check and start consuming air cells if (entity.worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID || entity.worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID) { boolean inVacuum = isEntityInVacuum(entity); @@ -87,7 +96,7 @@ public class SpaceEventHandler entity.attackEntityFrom(DamageSource.drown, 1); } - // Отправить назад на Землю + // If player falling down, teleport on earth if (entity.posY < -10.0D) { ((EntityPlayerMP)entity).mcServer.getConfigurationManager().transferPlayerToDimension(((EntityPlayerMP) entity), 0, new SpaceTeleporter(DimensionManager.getWorld(WarpDrive.instance.spaceDimID), 0, MathHelper.floor_double(entity.posX), 250, MathHelper.floor_double(entity.posZ))); @@ -103,6 +112,57 @@ public class SpaceEventHandler } } + private void updatePlayerCloakState(EntityLivingBase entity) + { + // Make sure for elapsed time is second after last update + if (System.currentTimeMillis() - this.lastTimer > 1000) + lastTimer = System.currentTimeMillis(); + else + return; + + try { + EntityPlayerMP p = (EntityPlayerMP)entity; + Integer cloakTicks = this.cloakPlayersTimers.get(p.username); + + if (cloakTicks == null) + { + this.cloakPlayersTimers.remove(p.username); + this.cloakPlayersTimers.put(p.username, 0); + + return; + } + + if (cloakTicks >= CLOAK_CHECK_TIMEOUT_SEC) + { + this.cloakPlayersTimers.remove(p.username); + this.cloakPlayersTimers.put(p.username, 0); + + List<CloakedArea> cloaks = WarpDrive.instance.cloaks.getCloaksForPoint(p.worldObj.provider.dimensionId, MathHelper.floor_double(p.posX), MathHelper.floor_double(p.posY), MathHelper.floor_double(p.posZ), false); + if (cloaks.size() != 0) + { + //System.out.println("[Cloak] Player inside " + cloaks.size() + " cloaked areas"); + for (CloakedArea area : cloaks) + { + //System.out.println("[Cloak] Frequency: " + area.frequency + ". In: " + area.isPlayerInArea(p) + ", W: " + area.isPlayerWithinArea(p)); + if (!area.isPlayerInArea(p) && area.isPlayerWithinArea(p)) + { + WarpDrive.instance.cloaks.playerEnteringCloakedArea(area, p); + } + } + } else + { + //System.out.println("[Cloak] Player is not inside any cloak fields. Check, which field player may left..."); + WarpDrive.instance.cloaks.checkPlayerLeavedArea(p); + } + } + else + { + this.cloakPlayersTimers.remove(p.username); + this.cloakPlayersTimers.put(p.username, cloakTicks + 1); + } + } catch (Exception e) { e.printStackTrace(); } + } + private void setPlayerAirValue(EntityLivingBase entity, Integer air) { vacuumPlayers.remove(((EntityPlayerMP)entity).username); diff --git a/src/cr0s/WarpDrive/TileEntityAirGenerator.java b/src/cr0s/WarpDrive/TileEntityAirGenerator.java index 5243dbce..a821a975 100644 --- a/src/cr0s/WarpDrive/TileEntityAirGenerator.java +++ b/src/cr0s/WarpDrive/TileEntityAirGenerator.java @@ -18,7 +18,7 @@ public class TileEntityAirGenerator extends TileEntity implements IEnergySink private int currentEnergyValue = 0; private int cooldownTicks = 0; - private final float AIR_POLLUTION_INTERVAL = 10; + private final float AIR_POLLUTION_INTERVAL = 4; // seconds private final int START_CONCENTRATION_VALUE = 15; @@ -44,7 +44,7 @@ public class TileEntityAirGenerator extends TileEntity implements IEnergySink if (addedToEnergyNet && currentEnergyValue > EU_PER_AIRBLOCK) { - if (cooldownTicks++ > AIR_POLLUTION_INTERVAL) + if (cooldownTicks++ > AIR_POLLUTION_INTERVAL * 20) { cooldownTicks = 0; worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1, 2); // set enabled texture diff --git a/src/cr0s/WarpDrive/TileEntityCloakingDeviceCore.java b/src/cr0s/WarpDrive/TileEntityCloakingDeviceCore.java new file mode 100644 index 00000000..d2cec195 --- /dev/null +++ b/src/cr0s/WarpDrive/TileEntityCloakingDeviceCore.java @@ -0,0 +1,484 @@ +package cr0s.WarpDrive; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import dan200.computer.api.IComputerAccess; +import dan200.computer.api.ILuaContext; +import dan200.computer.api.IPeripheral; +import net.minecraftforge.common.ForgeDirection; +import ic2.api.energy.event.EnergyTileLoadEvent; +import ic2.api.energy.event.EnergyTileUnloadEvent; +import ic2.api.energy.tile.IEnergySink; +import ic2.api.energy.tile.IEnergyTile; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.network.packet.Packet250CustomPayload; +import net.minecraft.server.MinecraftServer; +import net.minecraft.src.ModLoader; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.DamageSource; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; +import net.minecraftforge.common.MinecraftForge; +import net.minecraft.entity.player.EntityPlayerMP; + +public class TileEntityCloakingDeviceCore extends TileEntity implements IEnergySink, + IPeripheral { + public boolean addedToEnergyNet = false; + + private final int MAX_ENERGY_VALUE = 500000000; // 500kk eU + private int currentEnergyValue = 0; + + private String[] methodsArray = { "setFieldTier", // 0 setFieldTier(1 or 2) + "isAssemblyValid", // 1 - returns true or false + "getEnergyLevel", // 2 + "enableCloakingField", // 3 enables field if assembled right + "disableCloakingField", // 4 disables cloaking field + "setFieldFrequency" // 5 setFieldFrequency(int) + }; + + public boolean isEnabled = false; + public byte tier = 1; // cloaking field tier, 1 or 2 + public int frequency = 0; + + // Spatial cloaking field parameters + public int front, back, up, down, left, right; + public int minX = 0, minY = 0, minZ = 0, maxX = 0, maxY = 0, maxZ = 0; + + private int updateTicks = 0; + private int laserDrawingTicks = 0; + + @Override + public void updateEntity() { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { + return; + } + + if (!addedToEnergyNet && !this.tileEntityInvalid) { + MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this)); + addedToEnergyNet = true; + } + + if (--this.updateTicks <= 0) { + //System.out.println("[CloakDev] Updating cloaking state..."); + this.updateTicks = ((this.tier == 1) ? 20 : (tier == 2) ? 10 : 20) * WarpDriveConfig.i.CD_FIELD_REFRESH_INTERVAL_SECONDS; // resetting timer + + if (validateAssembly() && isEnabled) { + // Consume power for sustaining cloaking field + countBlocksAndConsumeEnergy(); + + if (currentEnergyValue >= 0) { + if (!WarpDrive.instance.cloaks.isAreaExists(this.frequency)) { + WarpDrive.instance.cloaks.addCloakedAreaWorld(worldObj, minX, minY, minZ, maxX, maxY, maxZ, frequency, tier); + worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1, 2); + worldObj.playSoundEffect(xCoord + 0.5f, yCoord + 0.5f, zCoord + 0.5f, "warpdrive:cloak", 4F, 1F); + + // Enable coils + setCoilsState(true); + } else { + // Refresh the field + CloakedArea area = WarpDrive.instance.cloaks.getCloakedArea(frequency); + if (area != null) + area.sendCloakPacketToPlayersEx(false); // recloak field + } + } else { + System.out.println("[CloakDev] Low power, cloak field collapsing..."); + currentEnergyValue = 0; + setCoilsState(false); + disableCloakingField(); + } + } else if (!validateAssembly() && isEnabled) { + System.out.println("[CloakDev] Device lost coils, field collapsing"); + currentEnergyValue = 0; + setCoilsState(false); + disableCloakingField(); + } + } + + if (laserDrawingTicks++ > 100) { + laserDrawingTicks = 0; + + if (isEnabled) + drawLasers(); + } + } + + public void setCoilsState(boolean enabled) { + final int START_LENGTH = 2; // Step length from core block to main coils + + // Directions to check (all six directions: left, right, up, down, front, back) + byte[] dx = { 1, -1, 0, 0, 0, 0 }; + byte[] dy = { 0, 0, -1, 1, 0, 0 }; + byte[] dz = { 0, 0, 0, 0, -1, 1 }; + + for (int i = 0; i < 6; i++) + searchCoilInDirectionAndSetState(dx[i], dy[i], dz[i], enabled); + } + + public void searchCoilInDirectionAndSetState(byte dx, byte dy, byte dz, boolean state) { + for (int i = 0; i < WarpDriveConfig.i.CD_MAX_CLOAKING_FIELD_SIDE; i++) { + if (worldObj.getBlockId(xCoord + i * dx, yCoord + i * dy, zCoord + i * dz) == WarpDriveConfig.i.cloakCoilID) + worldObj.setBlockMetadataWithNotify(xCoord + i * dx, yCoord + i * dy, zCoord + i * dz, (state) ? 1 : 0, 2); + } + } + + public void searchCoilInDirectionAndDrawLaser(byte dx, byte dy, byte dz) { + final int START_LENGTH = 2; + float r = 0.0f, g = 1.0f, b = 0; + if (this.tier == 1) { + r = 0.0f; g = 1.0f; + } else if (this.tier == 2) { + r = 1.0f; g = 0.0f; + } + + for (int i = START_LENGTH + 1; i < WarpDriveConfig.i.CD_MAX_CLOAKING_FIELD_SIDE; i++) { + if (worldObj.getBlockId(xCoord + i * dx, yCoord + i * dy, zCoord + i * dz) == WarpDriveConfig.i.cloakCoilID) + sendLaserPacket(new Vector3(this).add(0.5), new Vector3(xCoord + i * dx, yCoord + i * dy, zCoord + i * dz).add(0.5), r, g, b, 110, 0, 100); + } + } + + public void drawLasers() { + final int START_LENGTH = 2; + float r = 0.0f, g = 1.0f, b = 0; + if (this.tier == 1) { + r = 0.0f; g = 1.0f; + } else if (this.tier == 2) { + r = 1.0f; g = 0.0f; + } + + // Directions to check (all six directions: left, right, up, down, front, back) + byte[] dx = { 1, -1, 0, 0, 0, 0 }; + byte[] dy = { 0, 0, -1, 1, 0, 0 }; + byte[] dz = { 0, 0, 0, 0, -1, 1 }; + + for (int k = 0; k < 6; k++) + searchCoilInDirectionAndDrawLaser(dx[k], dy[k], dz[k]); + + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 6; j++) { + switch (worldObj.rand.nextInt(6)) { + case 0: + r = 1.0f; + g = b = 0; + break; + case 1: + r = b = 0; + g = 1.0f; + break; + case 2: + r = g = 0; + b = 1.0f; + break; + case 3: + r = b = 0.5f; + g = 0; + break; + case 4: + r = g = 1.0f; + b = 0; + break; + case 5: + r = 1.0f; + b = 0.5f; + g = 0f; + } + + sendLaserPacket(new Vector3(xCoord + START_LENGTH * dx[i], yCoord + START_LENGTH * dy[i], zCoord + START_LENGTH * dz[i]).add(0.5), new Vector3(xCoord + START_LENGTH * dx[j], yCoord + START_LENGTH * dy[j], zCoord + START_LENGTH * dz[j]).add(0.5), r, g, b, 110, 0, 100); + } + } + } + + public void disableCloakingField() { + this.isEnabled = false; + + if (WarpDrive.instance.cloaks.isAreaExists(this.frequency)) + WarpDrive.instance.cloaks.removeCloakedArea(this.frequency); + + worldObj.playSoundEffect(xCoord + 0.5f, yCoord + 0.5f, zCoord + 0.5f, "warpdrive:decloak", 4F, 1F); + worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 2); + } + public void countBlocksAndConsumeEnergy() { + int blocksCount = 0; + for (int y = minY; y <= maxY; y++) + for (int x = minX; x <= maxX; x++) + for(int z = minZ; z <= maxZ; z++) + if (worldObj.getBlockId(x, y, z) != 0) + blocksCount++; + int energyToConsume = blocksCount * ((this.tier == 1) ? WarpDriveConfig.i.CD_ENERGY_PER_BLOCK_TIER1 : WarpDriveConfig.i.CD_ENERGY_PER_BLOCK_TIER2); + + //System.out.println("[CloakDev] Consuming " + energyToConsume + " eU for " + blocksCount + " blocks"); + this.currentEnergyValue -= energyToConsume; + } + + public void sendLaserPacket(Vector3 source, Vector3 dest, float r, float g, float b, int age, int energy, int radius) { + Side side = FMLCommonHandler.instance().getEffectiveSide(); + + if (side == Side.SERVER) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(8); + DataOutputStream outputStream = new DataOutputStream(bos); + + try { + // Write source vector + outputStream.writeDouble(source.x); + outputStream.writeDouble(source.y); + outputStream.writeDouble(source.z); + // Write target vector + outputStream.writeDouble(dest.x); + outputStream.writeDouble(dest.y); + outputStream.writeDouble(dest.z); + // Write r, g, b of laser + outputStream.writeFloat(r); + outputStream.writeFloat(g); + outputStream.writeFloat(b); + // Write age + outputStream.writeByte(age); + // Write energy value + outputStream.writeInt(energy); + } catch (Exception ex) { + ex.printStackTrace(); + } + + Packet250CustomPayload packet = new Packet250CustomPayload(); + packet.channel = "WarpDriveBeam"; + packet.data = bos.toByteArray(); + packet.length = bos.size(); + + // Send packet to all players within cloaked area + List<Entity> list = worldObj.getEntitiesWithinAABB(EntityPlayerMP.class, AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ)); + for (Entity e : list) { + if (e != null && e instanceof EntityPlayer) { + ((EntityPlayerMP)e).playerNetServerHandler.sendPacketToPlayer(packet); + } + } + } + } + + @Override + public void readFromNBT(NBTTagCompound tag) { + super.readFromNBT(tag); + this.currentEnergyValue = tag.getInteger("energy"); + this.tier = tag.getByte("tier"); + this.frequency = tag.getInteger("frequency"); + this.isEnabled = tag.getBoolean("enabled"); + } + + @Override + public void writeToNBT(NBTTagCompound tag) { + super.writeToNBT(tag); + tag.setInteger("energy", this.getCurrentEnergyValue()); + tag.setByte("tier", this.tier); + tag.setInteger("frequency", this.frequency); + tag.setBoolean("enabled", this.isEnabled); + } + + public int searchCoilInDirection(byte dx, byte dy, byte dz) { + for (int i = 3; i < WarpDriveConfig.i.CD_MAX_CLOAKING_FIELD_SIDE; i++) { + if (worldObj.getBlockId(xCoord + i * dx, yCoord + i * dy, zCoord + i * dz) == WarpDriveConfig.i.cloakCoilID) + return i; + } + + return 0; + } + public boolean validateAssembly() { + final int START_LENGTH = 2; // Step length from core block to main coils + + // Directions to check (all six directions: left, right, up, down, front, back) + byte[] dx = { 1, -1, 0, 0, 0, 0 }; + byte[] dy = { 0, 0, -1, 1, 0, 0 }; + byte[] dz = { 0, 0, 0, 0, -1, 1 }; + + for (int i = 0; i < 6; i++) + if (worldObj.getBlockId(xCoord + START_LENGTH * dx[i], yCoord + START_LENGTH * dy[i], zCoord + START_LENGTH * dz[i]) != WarpDriveConfig.i.cloakCoilID) + return false; + + // Check cloaking field parameters defining coils + this.left = searchCoilInDirection((byte)1, (byte)0, (byte)0) + WarpDriveConfig.i.CD_COIL_CAPTURE_BLOCKS; + if (this.left == WarpDriveConfig.i.CD_COIL_CAPTURE_BLOCKS) return false; + this.right = searchCoilInDirection((byte)-1, (byte)0, (byte)0) + WarpDriveConfig.i.CD_COIL_CAPTURE_BLOCKS; + if (this.right == WarpDriveConfig.i.CD_COIL_CAPTURE_BLOCKS) return false; + + this.up = searchCoilInDirection((byte)0, (byte)1, (byte)0) + WarpDriveConfig.i.CD_COIL_CAPTURE_BLOCKS; + if (this.up == WarpDriveConfig.i.CD_COIL_CAPTURE_BLOCKS) return false; + this.down = searchCoilInDirection((byte)0, (byte)-1, (byte)0) + WarpDriveConfig.i.CD_COIL_CAPTURE_BLOCKS; + if (this.down == WarpDriveConfig.i.CD_COIL_CAPTURE_BLOCKS) return false; + + this.front = searchCoilInDirection((byte)0, (byte)0, (byte)1) + WarpDriveConfig.i.CD_COIL_CAPTURE_BLOCKS; + if (this.front == WarpDriveConfig.i.CD_COIL_CAPTURE_BLOCKS) return false; + this.back = searchCoilInDirection((byte)0, (byte)0, (byte)-1) + WarpDriveConfig.i.CD_COIL_CAPTURE_BLOCKS; + if (this.back == WarpDriveConfig.i.CD_COIL_CAPTURE_BLOCKS) return false; + + int x1 = 0, x2 = 0, z1 = 0, z2 = 0; + + + z1 = zCoord - this.back; + z2 = zCoord + this.front; + x1 = xCoord - this.right; + x2 = xCoord + this.left; + + if (x1 < x2) { + this.minX = x1;this. maxX = x2; + } + else { + this.minX = x2; this.maxX = x1; + } + + if (z1 < z2) { + this.minZ = z1; this.maxZ = z2; + } + else { + this.minZ = z2; this.maxZ = z1; + } + + this.minY = yCoord - this.down; + this.maxY = yCoord + this.up; + + return true; + } + + // CC + // IPeripheral methods implementation + @Override + public String getType() { + return "cloakingdevicecore"; + } + + @Override + public String[] getMethodNames() { + return methodsArray; + } + + @Override + public Object[] callMethod(IComputerAccess computer, ILuaContext context, + int method, Object[] arguments) throws Exception { + switch (method) { + case 0: // setFieldTier(1 or 2) + if (arguments.length == 1) { + this.tier = ((Double)arguments[0]).byteValue(); + } + + break; + case 1: // isAssemblyValid() + return new Object[] { (boolean)validateAssembly() }; + + case 2: // getEnergyLevel() + return new Object[] { currentEnergyValue }; + + case 3: // enableCloakingField() + this.isEnabled = true; + break; + + case 4: // disableCloakingField() + disableCloakingField(); + setCoilsState(false); + break; + + case 5: // setFieldFrequency(int) + if (arguments.length == 1) { + if (isEnabled) + disableCloakingField(); + + if (WarpDrive.instance.cloaks.isAreaExists(((Double)arguments[0]).intValue())) + return new Object[] { (Boolean)false }; + + this.frequency = ((Double)arguments[0]).intValue(); + return new Object[] { (Boolean)true }; + } + break; + } + + return null; + } + + @Override + public boolean canAttachToSide(int side) { + return true; + } + + @Override + public void attach(IComputerAccess computer) { + } + + @Override + public void detach(IComputerAccess computer) { + } + + // IEnergySink methods implementation + @Override + public double demandedEnergyUnits() { + return (MAX_ENERGY_VALUE - currentEnergyValue); + } + + @Override + public double injectEnergyUnits(ForgeDirection directionFrom, double amount) { + double leftover = 0; + currentEnergyValue += Math.round(amount); + + if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) { + leftover = (getCurrentEnergyValue() - MAX_ENERGY_VALUE); + currentEnergyValue = MAX_ENERGY_VALUE; + } + + return leftover; + } + + @Override + public int getMaxSafeInput() { + return Integer.MAX_VALUE; + } + + @Override + public boolean acceptsEnergyFrom(TileEntity emitter, + ForgeDirection direction) { + return true; + } + + /** + * @return the currentEnergyValue + */ + public int getCurrentEnergyValue() { + return currentEnergyValue; + } + + public int collectAllEnergy() { + int energy = currentEnergyValue; + currentEnergyValue = 0; + return energy; + } + + @Override + public void onChunkUnload() { + if (addedToEnergyNet) { + MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); + addedToEnergyNet = false; + } + } + + @Override + public void invalidate() { + if (addedToEnergyNet) { + MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); + addedToEnergyNet = false; + } + + super.invalidate(); + } + } diff --git a/src/cr0s/WarpDrive/TileEntityLaser.java b/src/cr0s/WarpDrive/TileEntityLaser.java index f37590cd..af56e514 100644 --- a/src/cr0s/WarpDrive/TileEntityLaser.java +++ b/src/cr0s/WarpDrive/TileEntityLaser.java @@ -34,9 +34,6 @@ import net.minecraftforge.common.MinecraftForge; public class TileEntityLaser extends TileEntity implements IPeripheral { - private final int MAX_BOOSTERS_NUMBER = 10; - private final int MAX_LASER_ENERGY = 4000000; - private int dx, dz, dy; public float yaw, pitch; // laser direction @@ -68,7 +65,7 @@ public class TileEntityLaser extends TileEntity implements IPeripheral public void updateEntity() { // Frequency is not set - if (frequency == -1) + if (frequency <= 0) { return; } @@ -88,11 +85,11 @@ public class TileEntityLaser extends TileEntity implements IPeripheral } } - if (isEmitting && ++delayTicks > 20 * 3) + if (isEmitting && (frequency != 1420 && ++delayTicks > WarpDriveConfig.i.LE_EMIT_DELAY_TICKS) || ((frequency == 1420) && ++delayTicks > WarpDriveConfig.i.LE_EMIT_SCAN_DELAY_TICKS)) { delayTicks = 0; isEmitting = false; - emitBeam(Math.min(this.collectEnergyFromBoosters() + MathHelper.floor_double(energyFromOtherBeams * 0.60D), MAX_LASER_ENERGY)); + emitBeam(Math.min(this.collectEnergyFromBoosters() + MathHelper.floor_double(energyFromOtherBeams * WarpDriveConfig.i.LE_COLLECT_ENERGY_MULTIPLIER), WarpDriveConfig.i.LE_MAX_LASER_ENERGY)); energyFromOtherBeams = 0; } } @@ -102,11 +99,11 @@ public class TileEntityLaser extends TileEntity implements IPeripheral if (isEmitting) { energyFromOtherBeams += amount; - System.out.println("[EL] Added energy: " + amount); + System.out.println("[LE] Added energy: " + amount); } else { - System.out.println("[EL] Ignored energy: " + amount); + System.out.println("[LE] Ignored energy: " + amount); } } @@ -116,7 +113,7 @@ public class TileEntityLaser extends TileEntity implements IPeripheral if (findFirstBooster() != null) { - for (int shift = 1; shift <= MAX_BOOSTERS_NUMBER; shift++) + for (int shift = 1; shift <= WarpDriveConfig.i.LE_MAX_BOOSTERS_NUMBER; shift++) { int newX = xCoord + (dx * shift); int newY = yCoord + (dy * shift); @@ -141,7 +138,7 @@ public class TileEntityLaser extends TileEntity implements IPeripheral private void emitBeam(int energy) { // Beam power calculations - int beamLengthBlocks = energy / 5000; + int beamLengthBlocks = energy / WarpDriveConfig.i.LE_BEAM_LENGTH_PER_ENERGY_DIVIDER; System.out.println("Energy: " + energy + " | beamLengthBlocks: " + beamLengthBlocks); if (energy == 0 || beamLengthBlocks < 1) @@ -204,16 +201,16 @@ public class TileEntityLaser extends TileEntity implements IPeripheral { if (distanceToEntity <= beamLengthBlocks) { - ((EntityLivingBase)e).setFire(100); - ((EntityLivingBase)e).attackEntityFrom(DamageSource.inFire, energy / 10000); + ((EntityLivingBase)e).setFire(WarpDriveConfig.i.LE_ENTITY_HIT_SET_ON_FIRE_TIME); + ((EntityLivingBase)e).attackEntityFrom(DamageSource.inFire, energy / WarpDriveConfig.i.LE_ENTITY_HIT_DAMAGE_PER_ENERGY_DIVIDER); - if (energy > 1000000) + if (energy > WarpDriveConfig.i.LE_ENTITY_HIT_EXPLOSION_LASER_ENERGY) { worldObj.newExplosion(null, e.posX, e.posY, e.posZ, 4F, true, true); } // consume energy - energy -= 10000 + (10 * distanceToEntity); + energy -= WarpDriveConfig.i.LE_ENTITY_HIT_DAMAGE_PER_ENERGY_DIVIDER + (10 * distanceToEntity); endPoint = new Vector3(entityHit.hitVec); break; } @@ -268,7 +265,7 @@ public class TileEntityLaser extends TileEntity implements IPeripheral endPoint = new Vector3(hit.hitVec); } - energy -= 70000 + (resistance * 1000) + (distance * 10); + energy -= WarpDriveConfig.i.LE_BLOCK_HIT_CONSUME_ENERGY + (resistance * WarpDriveConfig.i.LE_BLOCK_HIT_CONSUME_ENERGY_PER_BLOCK_RESISTANCE) + (distance * WarpDriveConfig.i.LE_BLOCK_HIT_CONSUME_ENERGY_PER_DISTANCE); endPoint = new Vector3(hit.hitVec); if (energy <= 0) diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index 9f48c6f4..d827b998 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -64,15 +64,8 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG "offset" //5 }; - private final int SCAN_DELAY = 20 * 5; private int delayTicksScan = 0; - - private final int MINE_DELAY = 10; private int delayTicksMine = 0; - - private final int EU_PER_LAYER_SPACE = 500; - private final int EU_PER_LAYER_EARTH = 5000; - private int currentMode = 0; // 0 - scan next layer, 1 - collect valuables private int currentLayer; @@ -105,19 +98,19 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG if (currentMode == 0) { - if (++delayTicksScan > SCAN_DELAY) + if (++delayTicksScan > WarpDriveConfig.i.ML_SCAN_DELAY) { delayTicksScan = 0; valuablesInLayer.clear(); valuableIndex = 0; - if (!collectEnergyPacketFromBooster(isOnEarth ? EU_PER_LAYER_EARTH : EU_PER_LAYER_SPACE, true)) + if (!collectEnergyPacketFromBooster(isOnEarth ? WarpDriveConfig.i.ML_EU_PER_LAYER_EARTH : WarpDriveConfig.i.ML_EU_PER_LAYER_SPACE, true)) return; while (currentLayer > 0) { scanLayer(); if (valuablesInLayer.size() > 0) { - if (!collectEnergyPacketFromBooster(isOnEarth ? EU_PER_LAYER_EARTH : EU_PER_LAYER_SPACE, false)) + if (!collectEnergyPacketFromBooster(isOnEarth ? WarpDriveConfig.i.ML_EU_PER_LAYER_EARTH : WarpDriveConfig.i.ML_EU_PER_LAYER_SPACE, false)) return; sendLaserPacket(minerVector, new Vector3(xCoord, currentLayer, zCoord).add(0.5), 0, 0, 1, 20, 0, 50); worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:hilaser", 4F, 1F); @@ -137,7 +130,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG } else { - if (++delayTicksMine > MINE_DELAY) + if (++delayTicksMine > WarpDriveConfig.i.ML_MINE_DELAY) { delayTicksMine = 0; @@ -152,7 +145,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG if (!canDig(blockID)) return; - sendLaserPacket(minerVector, new Vector3(valuable.intX(), valuable.intY(), valuable.intZ()).add(0.5), 1, 1, 0, 2 * MINE_DELAY, 0, 50); + sendLaserPacket(minerVector, new Vector3(valuable.intX(), valuable.intY(), valuable.intZ()).add(0.5), 1, 1, 0, 2 * WarpDriveConfig.i.ML_MINE_DELAY, 0, 50); worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F); harvestBlock(valuable); } diff --git a/src/cr0s/WarpDrive/TileEntityParticleBooster.java b/src/cr0s/WarpDrive/TileEntityParticleBooster.java index 98074bec..74cc7f32 100644 --- a/src/cr0s/WarpDrive/TileEntityParticleBooster.java +++ b/src/cr0s/WarpDrive/TileEntityParticleBooster.java @@ -26,7 +26,6 @@ public class TileEntityParticleBooster extends TileEntity implements IEnergySink { public boolean addedToEnergyNet = false; - private final int MAX_ENERGY_VALUE = 100000; // eU private int currentEnergyValue = 0; int ticks = 0; @@ -48,7 +47,7 @@ public class TileEntityParticleBooster extends TileEntity implements IEnergySink if (++ticks > 40) { ticks = 0; - currentEnergyValue = Math.min(currentEnergyValue, MAX_ENERGY_VALUE); + currentEnergyValue = Math.min(currentEnergyValue, WarpDriveConfig.i.PB_MAX_ENERGY_VALUE); worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, currentEnergyValue / 10000, 2); } } @@ -71,7 +70,7 @@ public class TileEntityParticleBooster extends TileEntity implements IEnergySink @Override public double demandedEnergyUnits() { - return (MAX_ENERGY_VALUE - currentEnergyValue); + return (WarpDriveConfig.i.PB_MAX_ENERGY_VALUE - currentEnergyValue); } @Override @@ -80,10 +79,10 @@ public class TileEntityParticleBooster extends TileEntity implements IEnergySink double leftover = 0; currentEnergyValue += Math.round(amount); - if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) + if (getCurrentEnergyValue() > WarpDriveConfig.i.PB_MAX_ENERGY_VALUE) { - leftover = (getCurrentEnergyValue() - MAX_ENERGY_VALUE); - currentEnergyValue = MAX_ENERGY_VALUE; + leftover = (getCurrentEnergyValue() - WarpDriveConfig.i.PB_MAX_ENERGY_VALUE); + currentEnergyValue = WarpDriveConfig.i.PB_MAX_ENERGY_VALUE; } return leftover; diff --git a/src/cr0s/WarpDrive/TileEntityProtocol.java b/src/cr0s/WarpDrive/TileEntityProtocol.java index f1b1a6df..437789f9 100644 --- a/src/cr0s/WarpDrive/TileEntityProtocol.java +++ b/src/cr0s/WarpDrive/TileEntityProtocol.java @@ -591,7 +591,7 @@ public class TileEntityProtocol extends TileEntity implements IPeripheral return new Object[] { (Integer)core.zCoord }; - case 13: + case 13: // get_energy_value if (core != null) { return new Object[] { (Integer)((TileEntityReactor)core).currentEnergyValue }; @@ -639,7 +639,7 @@ public class TileEntityProtocol extends TileEntity implements IPeripheral case 19: // set_core_frequency if (arguments.length == 1 && (core != null && core instanceof TileEntityReactor)) { - ((TileEntityReactor)core).coreFrequency = ((String)arguments[0]); + ((TileEntityReactor)core).coreFrequency = ((String)arguments[0]).replace("/", "").replace(".", "").replace("\\", "."); } break; diff --git a/src/cr0s/WarpDrive/TileEntityRadar.java b/src/cr0s/WarpDrive/TileEntityRadar.java index 5a1ae375..c4d5ca1d 100644 --- a/src/cr0s/WarpDrive/TileEntityRadar.java +++ b/src/cr0s/WarpDrive/TileEntityRadar.java @@ -26,7 +26,6 @@ public class TileEntityRadar extends TileEntity implements IPeripheral, IEnergyS { public boolean addedToEnergyNet = false; - private final int MAX_ENERGY_VALUE = 100 * (1000 * 1000); // 100 000 000 Eu private int currentEnergyValue = 0; private String[] methodsArray = @@ -197,7 +196,7 @@ public class TileEntityRadar extends TileEntity implements IPeripheral, IEnergyS @Override public double demandedEnergyUnits() { - return (MAX_ENERGY_VALUE - currentEnergyValue); + return (WarpDriveConfig.i.WR_MAX_ENERGY_VALUE - currentEnergyValue); } @Override @@ -206,10 +205,10 @@ public class TileEntityRadar extends TileEntity implements IPeripheral, IEnergyS double leftover = 0; currentEnergyValue += Math.round(amount); - if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) + if (getCurrentEnergyValue() > WarpDriveConfig.i.WR_MAX_ENERGY_VALUE) { - leftover = (getCurrentEnergyValue() - MAX_ENERGY_VALUE); - currentEnergyValue = MAX_ENERGY_VALUE; + leftover = (getCurrentEnergyValue() - WarpDriveConfig.i.WR_MAX_ENERGY_VALUE); + currentEnergyValue = WarpDriveConfig.i.WR_MAX_ENERGY_VALUE; } return leftover; diff --git a/src/cr0s/WarpDrive/TileEntityReactor.java b/src/cr0s/WarpDrive/TileEntityReactor.java index 29cb02d7..4875175e 100644 --- a/src/cr0s/WarpDrive/TileEntityReactor.java +++ b/src/cr0s/WarpDrive/TileEntityReactor.java @@ -1,7 +1,5 @@ package cr0s.WarpDrive; -import cpw.mods.fml.common.FMLCommonHandler; -import net.minecraftforge.common.ForgeDirection; import ic2.api.energy.event.EnergyTileLoadEvent; import ic2.api.energy.event.EnergyTileUnloadEvent; import ic2.api.energy.tile.IEnergySink; @@ -23,7 +21,9 @@ import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.MathHelper; import net.minecraft.world.WorldServer; import net.minecraftforge.common.DimensionManager; +import net.minecraftforge.common.ForgeDirection; import net.minecraftforge.common.MinecraftForge; +import cpw.mods.fml.common.FMLCommonHandler; /** * @author Cr0s @@ -58,35 +58,22 @@ public class TileEntityReactor extends TileEntity implements IEnergySink int currentMode = 0; int currentEnergyValue = 0; - int maxEnergyValue = 100000000; - private final int ENERGY_PER_BLOCK_MODE1 = 10; // eU - private final int ENERGY_PER_DISTANCE_MODE1 = 100; // eU - private final int ENERGY_PER_BLOCK_MODE2 = 1000; // eU - private final int ENERGY_PER_DISTANCE_MODE2 = 1000; // eU - private final int ENERGY_PER_ENTITY_TO_SPACE = 1000000; // eU private final byte MODE_BASIC_JUMP = 1; // 0-128 private final byte MODE_LONG_JUMP = 2; // 0-12800 private final byte MODE_BEACON_JUMP = 4; // Jump ship by beacon private final byte MODE_HYPERSPACE = 5; // Jump to Hyperspace private final byte MODE_TELEPORT = -1; private final byte MODE_GATE_JUMP = 6; // Jump via jumpgate - private final int MAX_JUMP_DISTANCE = 128; // Maximum jump length value - private final int MAX_SHIP_VOLUME_ON_SURFACE = 15000; // Maximum ship mass to jump on earth (15k blocks) - private final int MIN_SHIP_VOLUME_FOR_HYPERSPACE = 500; // Minimum ship volume value for - public final int MAX_SHIP_SIDE = 100; int cooldownTime = 0; - private final int COOLDOWN_INTERVAL_SECONDS = 4; public int randomCooldownAddition = 0; - private final int CORES_REGISTRY_UPDATE_INTERVAL_SECONDS = 10; private int registryUpdateTicks = 0; public String coreFrequency = "default"; public int isolationBlocksCount = 0; public int isolationUpdateTicks = 0; - private final int ISOLATION_UPDATE_INTARVAL_SECONDS = 10; public String coreState = ""; public TileEntityProtocol controller; @@ -103,7 +90,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink } // Update warp core in cores registry - if (++registryUpdateTicks > CORES_REGISTRY_UPDATE_INTERVAL_SECONDS * 20) + if (++registryUpdateTicks > WarpDriveConfig.i.WC_CORES_REGISTRY_UPDATE_INTERVAL_SECONDS * 20) { registryUpdateTicks = 0; WarpDrive.instance.registry.updateInRegistry(this); @@ -114,7 +101,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink return; } - if (++isolationUpdateTicks > ISOLATION_UPDATE_INTARVAL_SECONDS * 20) + if (++isolationUpdateTicks > WarpDriveConfig.i.WC_ISOLATION_UPDATE_INTARVAL_SECONDS * 20) { isolationUpdateTicks = 0; updateIsolationState(); @@ -190,7 +177,6 @@ public class TileEntityReactor extends TileEntity implements IEnergySink // Set up activated animation if (worldObj.getBlockMetadata(xCoord, yCoord, zCoord) == 0) { - // TODO: check for "warpcore turns into dirt" bug worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1, 1 + 2); // Set block state to "active" makePlayersOnShipDrunk(); } @@ -202,7 +188,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink } // Awaiting cooldown time - if (/*currentMode != MODE_BASIC_JUMP && */cooldownTime++ < ((COOLDOWN_INTERVAL_SECONDS) * 20) + randomCooldownAddition) + if (/*currentMode != MODE_BASIC_JUMP && */cooldownTime++ < ((WarpDriveConfig.i.WC_COOLDOWN_INTERVAL_SECONDS) * 20) + randomCooldownAddition) { return; } @@ -222,6 +208,13 @@ public class TileEntityReactor extends TileEntity implements IEnergySink return; } + if (WarpDrive.instance.cloaks.isInCloak(worldObj.provider.dimensionId, xCoord, yCoord, zCoord, false)) + { + this.controller.setJumpFlag(false); + messageToAllPlayersOnShip("Wap-Core is inside cloaking field. Can't jump. Disable cloaking field to jump!"); + return; + } + System.out.println("[W-C] Jumping!"); doJump(); controller.setJumpFlag(false); @@ -365,7 +358,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink public void summonPlayer(EntityPlayerMP player, int x, int y, int z) { - if (this.currentEnergyValue - this.ENERGY_PER_ENTITY_TO_SPACE >= 0) + if (this.currentEnergyValue - WarpDriveConfig.i.WC_ENERGY_PER_ENTITY_TO_SPACE >= 0) { player.setPositionAndUpdate(x, y, z); @@ -374,12 +367,15 @@ public class TileEntityReactor extends TileEntity implements IEnergySink player.mcServer.getConfigurationManager().transferPlayerToDimension(player, this.worldObj.provider.dimensionId, new SpaceTeleporter(DimensionManager.getWorld(this.worldObj.provider.dimensionId), 0, MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ))); } - this.currentEnergyValue -= this.ENERGY_PER_ENTITY_TO_SPACE; + this.currentEnergyValue -= WarpDriveConfig.i.WC_ENERGY_PER_ENTITY_TO_SPACE; } } public boolean prepareToJump() { + if (controller == null) + return false; + this.direction = controller.getDirection(); this.shipFront = controller.getFront(); this.shipRight = controller.getRight(); @@ -387,7 +383,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink this.shipBack = controller.getBack(); this.shipLeft = controller.getLeft(); this.shipDown = controller.getDown(); - this.distance = Math.min(this.MAX_JUMP_DISTANCE, controller.getDistance()); + this.distance = Math.min(WarpDriveConfig.i.WC_MAX_JUMP_DISTANCE, controller.getDistance()); return calculateSpatialShipParameters(); } @@ -475,7 +471,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink } // Ship side is too big - if (shipLength > MAX_SHIP_SIDE || shipWidth > MAX_SHIP_SIDE || shipHeight > MAX_SHIP_SIDE) + if (shipLength > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || shipWidth > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || shipHeight > WarpDriveConfig.i.WC_MAX_SHIP_SIDE) { this.controller.setJumpFlag(false); return false; @@ -483,7 +479,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink this.shipVolume = getRealShipVolume(); - if (shipVolume > MAX_SHIP_VOLUME_ON_SURFACE && worldObj.provider.dimensionId == 0) + if (shipVolume > WarpDriveConfig.i.WC_MAX_JUMP_DISTANCE && worldObj.provider.dimensionId == 0) { this.controller.setJumpFlag(false); return false; @@ -785,9 +781,9 @@ public class TileEntityReactor extends TileEntity implements IEnergySink if (t != null && !isShipInJumpgate(t)) { - if (shipVolume < MIN_SHIP_VOLUME_FOR_HYPERSPACE) + if (shipVolume < WarpDriveConfig.i.WC_MIN_SHIP_VOLUME_FOR_HYPERSPACE) { - this.messageToAllPlayersOnShip("Ship is too small (" + shipVolume + "/" + MIN_SHIP_VOLUME_FOR_HYPERSPACE + "). Insufficient ship mass to open hyperspace portal."); + this.messageToAllPlayersOnShip("Ship is too small (" + shipVolume + "/" + WarpDriveConfig.i.WC_MIN_SHIP_VOLUME_FOR_HYPERSPACE + "). Insufficient ship mass to open hyperspace portal."); this.controller.setJumpFlag(false); return; } @@ -802,6 +798,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink if (this.currentEnergyValue - calculateRequiredEnergy(shipVolume, distance) < 0) { System.out.println("[WP-TE] Insufficient energy to jump"); + messageToAllPlayersOnShip("Insufficient energy to jump!"); this.controller.setJumpFlag(false); return; } @@ -870,12 +867,12 @@ public class TileEntityReactor extends TileEntity implements IEnergySink for (Object o : list) { - if (currentEnergyValue - ENERGY_PER_ENTITY_TO_SPACE < 0) + if (currentEnergyValue - WarpDriveConfig.i.WC_ENERGY_PER_ENTITY_TO_SPACE < 0) { return; } - currentEnergyValue -= ENERGY_PER_ENTITY_TO_SPACE; + currentEnergyValue -= WarpDriveConfig.i.WC_ENERGY_PER_ENTITY_TO_SPACE; Entity entity = (Entity) o; int x = MathHelper.floor_double(entity.posX); int z = MathHelper.floor_double(entity.posZ); @@ -1009,19 +1006,19 @@ public class TileEntityReactor extends TileEntity implements IEnergySink switch (currentMode) { case MODE_BASIC_JUMP: - energyValue = (ENERGY_PER_BLOCK_MODE1 * shipVolume) + (ENERGY_PER_DISTANCE_MODE1 * jumpDistance); + energyValue = (WarpDriveConfig.i.WC_ENERGY_PER_BLOCK_MODE1 * shipVolume) + (WarpDriveConfig.i.WC_ENERGY_PER_DISTANCE_MODE1 * jumpDistance); break; case MODE_LONG_JUMP: - energyValue = (ENERGY_PER_BLOCK_MODE2 * shipVolume) + (ENERGY_PER_DISTANCE_MODE2 * jumpDistance); + energyValue = (WarpDriveConfig.i.WC_ENERGY_PER_BLOCK_MODE2 * shipVolume) + (WarpDriveConfig.i.WC_ENERGY_PER_DISTANCE_MODE2 * jumpDistance); break; case MODE_HYPERSPACE: - energyValue = this.maxEnergyValue / 10; // 10% of maximum + energyValue = WarpDriveConfig.i.WC_MAX_ENERGY_VALUE / 10; // 10% of maximum break; case MODE_BEACON_JUMP: - energyValue = this.maxEnergyValue / 2; // half of maximum + energyValue = WarpDriveConfig.i.WC_MAX_ENERGY_VALUE / 2; // half of maximum break; case MODE_GATE_JUMP: @@ -1104,7 +1101,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink return 0; } - return (maxEnergyValue - currentEnergyValue); + return (WarpDriveConfig.i.WC_MAX_ENERGY_VALUE - currentEnergyValue); } @Override @@ -1113,10 +1110,10 @@ public class TileEntityReactor extends TileEntity implements IEnergySink double leftover = 0; currentEnergyValue += Math.round(amount); - if (currentEnergyValue > maxEnergyValue) + if (currentEnergyValue > WarpDriveConfig.i.WC_MAX_ENERGY_VALUE) { - leftover = (currentEnergyValue - maxEnergyValue); - currentEnergyValue = maxEnergyValue; + leftover = (currentEnergyValue - WarpDriveConfig.i.WC_MAX_ENERGY_VALUE); + currentEnergyValue = WarpDriveConfig.i.WC_MAX_ENERGY_VALUE; } return leftover; diff --git a/src/cr0s/WarpDrive/TileEntityShipScanner.java b/src/cr0s/WarpDrive/TileEntityShipScanner.java new file mode 100644 index 00000000..c5087f40 --- /dev/null +++ b/src/cr0s/WarpDrive/TileEntityShipScanner.java @@ -0,0 +1,931 @@ +package cr0s.WarpDrive; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import dan200.computer.api.IComputerAccess; +import dan200.computer.api.ILuaContext; +import dan200.computer.api.IPeripheral; +import net.minecraftforge.common.ForgeDirection; +import ic2.api.energy.event.EnergyTileLoadEvent; +import ic2.api.energy.event.EnergyTileUnloadEvent; +import ic2.api.energy.tile.IEnergySink; +import ic2.api.energy.tile.IEnergyTile; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.network.packet.Packet250CustomPayload; +import net.minecraft.server.MinecraftServer; +import net.minecraft.src.ModLoader; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.DamageSource; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; +import net.minecraftforge.common.MinecraftForge; + +public class TileEntityShipScanner extends TileEntity implements IEnergySink, + IPeripheral { + public boolean addedToEnergyNet = false; + + private final int MAX_ENERGY_VALUE = 500000000; // 500kk eU + private int currentEnergyValue = 0; + + private int state = 0; // 0 - inactive, 1 - active + private int firstUncoveredY; + + private boolean isEnabled = false; + private TileEntityReactor core = null; + + int laserTicks = 0; + int scanTicks = 0; + int deployDelayTicks = 0; + + int warpCoreSearchTicks = 0; + + // Config + private final String SCHEMATICS_DIR = "/home/cros/mc_site/schematics/"; + private final int EU_PER_BLOCK_SCAN = 100; // eU per block of ship volume (including air) + private final int EU_PER_BLOCK_DEPLOY = 5000; + private final int BLOCK_TO_DEPLOY_PER_TICK = 1000; + private final int ALLOWED_DEPLOY_RADIUS = 50; // blocks + + private String[] methodsArray = { "scanShip", // 0 + "getSchematicFileName", // 1 + "getEnergyLevel", // 2 + "deployShipFromSchematic" // 3 deployShipFromSchematic(file, offsetX, offsetY, offsetZ) + }; + + private String schematicFileName; + + private JumpBlock[] blocksToDeploy; // JumpBlock class stores a basic information about block + private int currentDeployIndex; + private int blocksToDeployCount; + private boolean isDeploying = false; + + private int newX, newY, newZ; + + + @Override + public void updateEntity() { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { + return; + } + + if (!addedToEnergyNet && !this.tileEntityInvalid) { + MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this)); + addedToEnergyNet = true; + } + + if (++warpCoreSearchTicks > 20) { + core = searchWarpCore(); + warpCoreSearchTicks = 0; + } + + // Warp core is not found + if (!isDeploying && core == null) { + switchState(0); // disable scanner + return; + } + + if (state == 0) { // inactive + if (++laserTicks > 20) { + sendLaserPacket(new Vector3(this).add(0.5), new Vector3( + core.xCoord, core.yCoord, core.zCoord).add(0.5), 0f, + 1f, 0f, 40, 0, 100); + laserTicks = 0; + } + } else if (state == 1 && !isDeploying) { // active: scanning + if (++laserTicks > 5) { + laserTicks = 0; + + for (int i = 0; i < core.maxX - core.minX; i++) { + int x = core.minX + i; + int randomZ = core.minZ + worldObj.rand.nextInt(core.maxZ - core.minZ); + + worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F); + float r = 0.0f, g = 0.0f, b = 0.0f; + + switch (worldObj.rand.nextInt(6)) { + case 0: + r = 1.0f; + g = b = 0; + break; + + case 1: + r = b = 0; + g = 1.0f; + break; + + case 2: + r = g = 0; + b = 1.0f; + break; + + case 3: + r = b = 0.5f; + g = 0; + break; + + case 4: + r = g = 1.0f; + b = 0; + break; + + case 5: + r = 1.0f; + b = 0.5f; + g = 0f; + } + + sendLaserPacket(new Vector3(this).add(0.5), new Vector3(x, core.maxY, randomZ).add(0.5), r, g, b, 15, 0, 100); + } + } + + if (++scanTicks > 20 * (1 + core.shipVolume / 10)) { + switchState(0); + scanTicks = 0; + } + } if (state == 1 && isDeploying) { // active: deploying + if (++deployDelayTicks < 20) + return; + + deployDelayTicks = 0; + + int blocks = Math.min(BLOCK_TO_DEPLOY_PER_TICK, blocksToDeployCount - currentDeployIndex); + System.out.println("[ShipScanner] Deploying ship part: " + currentDeployIndex + "/" + blocksToDeployCount + " [remains: " + blocks + "]"); + + if (blocks == 0) { + isDeploying = false; + switchState(0); + return; + } + + for (int index = 0; index < blocks; index++) + { + if (currentDeployIndex >= blocksToDeployCount) + { + isDeploying = false; + switchState(0); + break; + } + + // Deploy single block + JumpBlock block = blocksToDeploy[currentDeployIndex]; + + if (block!= null && worldObj.isAirBlock(newX + block.x, newY + block.y, newZ + block.z)) + { + moveBlockSimple(block); + + if (worldObj.rand.nextInt(100) <= 10) { + worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F); + + sendLaserPacket(new Vector3(this).add(0.5), new Vector3( + newX + block.x, newY + block.y, newZ + block.z).add(0.5), 0f, + 1f, 0f, 15, 0, 100); + } + } + + currentDeployIndex++; + } + } + } + + private void switchState(int newState) { + this.state = newState; + worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, newState, 2); + } + + private TileEntityReactor searchWarpCore() { + TileEntityReactor result = null; + + // Search for warp cores above + for (int newY = yCoord + 1; newY <= 255; newY++) { + if (worldObj.getBlockId(xCoord, newY, zCoord) == WarpDriveConfig.i.coreID) { // found + // warp + // core + // above + result = (TileEntityReactor) worldObj.getBlockTileEntity( + xCoord, newY, zCoord); + + if (result != null) { + if (!result.prepareToJump()) { // If we can't refresh ship's + // spatial parameters + result = null; + } + } + + break; + } + } + + return result; + } + + public void sendLaserPacket(Vector3 source, Vector3 dest, float r, float g, + float b, int age, int energy, int radius) { + Side side = FMLCommonHandler.instance().getEffectiveSide(); + + if (side == Side.SERVER) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(8); + DataOutputStream outputStream = new DataOutputStream(bos); + + try { + // Write source vector + outputStream.writeDouble(source.x); + outputStream.writeDouble(source.y); + outputStream.writeDouble(source.z); + // Write target vector + outputStream.writeDouble(dest.x); + outputStream.writeDouble(dest.y); + outputStream.writeDouble(dest.z); + // Write r, g, b of laser + outputStream.writeFloat(r); + outputStream.writeFloat(g); + outputStream.writeFloat(b); + // Write age + outputStream.writeByte(age); + // Write energy value + outputStream.writeInt(energy); + } catch (Exception ex) { + ex.printStackTrace(); + } + + Packet250CustomPayload packet = new Packet250CustomPayload(); + packet.channel = "WarpDriveBeam"; + packet.data = bos.toByteArray(); + packet.length = bos.size(); + MinecraftServer + .getServer() + .getConfigurationManager() + .sendToAllNear(source.intX(), source.intY(), source.intZ(), + radius, worldObj.provider.dimensionId, packet); + ByteArrayOutputStream bos2 = new ByteArrayOutputStream(8); + DataOutputStream outputStream2 = new DataOutputStream(bos2); + + try { + // Write source vector + outputStream2.writeDouble(source.x); + outputStream2.writeDouble(source.y); + outputStream2.writeDouble(source.z); + // Write target vector + outputStream2.writeDouble(dest.x); + outputStream2.writeDouble(dest.y); + outputStream2.writeDouble(dest.z); + // Write r, g, b of laser + outputStream2.writeFloat(r); + outputStream2.writeFloat(g); + outputStream2.writeFloat(b); + // Write age + outputStream2.writeByte(age); + // Write energy value + outputStream2.writeInt(energy); + } catch (Exception ex) { + ex.printStackTrace(); + } + + Packet250CustomPayload packet2 = new Packet250CustomPayload(); + packet.channel = "WarpDriveBeam"; + packet.data = bos.toByteArray(); + packet.length = bos.size(); + MinecraftServer + .getServer() + .getConfigurationManager() + .sendToAllNear(dest.intX(), dest.intY(), dest.intZ(), + radius, worldObj.provider.dimensionId, packet); + } + } + + // Checks energy level + private boolean isEnoughEnergyForScan() { + if (core != null) { + return core.shipVolume * EU_PER_BLOCK_SCAN <= currentEnergyValue; + } + + return false; + } + + private void saveShipToSchematic(String fileName) { + NBTTagCompound schematic = new NBTTagCompound("Schematic"); + + short width = (short) Math.abs(core.maxX - core.minX); + short length = (short) Math.abs(core.maxZ - core.minZ); + short height = (short) (core.maxY - core.minY); + + width++; + height++; + length++; + + schematic.setShort("Width", width); + schematic.setShort("Length", length); + schematic.setShort("Height", height); + + System.out.println("[ShipScanner] Ship parameters: w: " + width + ", l: " + length + ", h:" + height); + + int size = width * length * height; + + // Consume energy + currentEnergyValue = Math.abs(currentEnergyValue - size * EU_PER_BLOCK_SCAN); + + System.out.println("[ShipScanner] Size: " + size); + + byte localBlocks[] = new byte[size]; + byte localMetadata[] = new byte[size]; + byte extraBlocks[] = new byte[size]; + byte extraBlocksNibble[] = new byte[(int) Math.ceil(size / 2.0)]; + boolean extra = false; + + NBTTagList tileEntitiesList = new NBTTagList(); + + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + for (int z = 0; z < length; z++) { + int blockID = worldObj.getBlockId(core.minX + x, core.minY + y, core.minZ + z); + + // Do not scan air, bedrock and specified forbidden blocks (like ore or Warp-Cores) + if (worldObj.isAirBlock(core.minX + x, core.minY + y, core.minZ + z) || blockID == Block.bedrock.blockID || WarpDriveConfig.i.scannerIgnoreBlocks.contains(blockID)) + blockID = 0; + + int blockMetadata = (byte) worldObj.getBlockMetadata(core.minX + x, core.minY + y, core.minZ + z); + localBlocks[x + (y * length + z) * width] = (byte) blockID; + localMetadata[x + (y * length + z) * width] = (byte) blockMetadata; + if ((extraBlocks[x + (y * length + z) * width] = (byte) (blockID >> 8)) > 0) { + extra = true; + } + + if (blockID != 0) { + TileEntity te = worldObj.getBlockTileEntity(core.minX + x, core.minY + y, core.minZ + z); + if (te != null && !(te instanceof IInventory)) + { + try { + NBTTagCompound tileTag = new NBTTagCompound(); + te.writeToNBT(tileTag); + + // Remove energy from energy storages + if (te instanceof IEnergyTile) { + if (tileTag.hasKey("energy")) + tileTag.setInteger("energy", 0); + } + + // Transform TE's coordinates from local axis to .schematic offset-axis + tileTag.setInteger("x", te.xCoord - core.minX); + tileTag.setInteger("y", te.yCoord - core.minY); + tileTag.setInteger("z", te.zCoord - core.minZ); + + tileEntitiesList.appendTag(tileTag); + } catch (Exception e) {} + } + } + } + } + } + + for (int i = 0; i < extraBlocksNibble.length; i++) { + if (i * 2 + 1 < extraBlocks.length) { + extraBlocksNibble[i] = (byte) ((extraBlocks[i * 2 + 0] << 4) | extraBlocks[i * 2 + 1]); + } else { + extraBlocksNibble[i] = (byte) (extraBlocks[i * 2 + 0] << 4); + } + } + + schematic.setString("Materials", "Alpha"); + schematic.setByteArray("Blocks", localBlocks); + schematic.setByteArray("Data", localMetadata); + + if (extra) + schematic.setByteArray("AddBlocks", extraBlocksNibble); + + schematic.setTag("Entities", new NBTTagList()); // don't save entities + schematic.setTag("TileEntities", tileEntitiesList); + + writeNBTToFile(fileName, schematic); + } + + private void writeNBTToFile(String fileName, NBTTagCompound nbttagcompound) { + System.out.println("[ShipScanner] Filename: " + fileName); + + try { + File file = new File(fileName); + if (!file.exists()) { + file.createNewFile(); + } + + FileOutputStream fileoutputstream = new FileOutputStream(file); + + CompressedStreamTools.writeCompressed(nbttagcompound, + fileoutputstream); + + fileoutputstream.close(); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + // Begins ship scan + private void scanShip() { + // Enable scanner + switchState(1); + + // Generate unique file name + do { + schematicFileName = (new StringBuilder().append(core.coreFrequency) + .append(System.currentTimeMillis()).append(".schematic")) + .toString(); + } while (new File(this.SCHEMATICS_DIR + schematicFileName).exists()); + + saveShipToSchematic(this.SCHEMATICS_DIR + schematicFileName); + } + + private NBTTagCompound readNBTFromFile(String fileName) { + try { + File file = new File(fileName); + if (!file.exists()) { + return null; + } + + FileInputStream fileinputstream = new FileInputStream(file); + NBTTagCompound nbttagcompound = CompressedStreamTools + .readCompressed(fileinputstream); + + fileinputstream.close(); + + return nbttagcompound; + } catch (Exception exception) { + exception.printStackTrace(); + } + + return null; + } + + private boolean isEnoughEnergyForDeploy(int size) { + return size * EU_PER_BLOCK_DEPLOY <= currentEnergyValue; + } + + // Returns result array for CC interface: [ code, "message" ] + private Object[] deployShip(String fileName, int offsetX, int offsetY, int offsetZ) { + NBTTagCompound schematic = readNBTFromFile(SCHEMATICS_DIR + fileName); + + if (schematic == null) { + System.out.println("[ShipScanner] Schematic is null!"); + return new Object[] { -1, "Unknow error. Schematic NBT is null" }; + } + + short width = schematic.getShort("Width"); + short height = schematic.getShort("Height"); + short length = schematic.getShort("Length"); + + int targetX = xCoord + offsetX; + int targetY = yCoord + offsetY; + int targetZ = zCoord + offsetZ; + + double d3 = xCoord - targetX; + double d4 = yCoord - targetY; + double d5 = zCoord - targetZ; + double distance = MathHelper.sqrt_double(d3 * d3 + d4 * d4 + d5 * d5); + + if (distance > ALLOWED_DEPLOY_RADIUS) + return new Object[] { 5, "Cannot deploy ship so far away from scanner." }; + + int size = width* height * length; + + System.out.println("[ShipScanner] Deploying ship: (size: " + size + ", h: " + height + ", w: " + width + ", l: " + length + ")"); + + // Check energy level + if (!isEnoughEnergyForDeploy(size)) { + System.out.println("[ShipScanner] Not enough energy! Need at least " + (Math.abs(size * EU_PER_BLOCK_DEPLOY - currentEnergyValue)) + " Eu"); + return new Object[] { 1, "Not enough energy! Need at least " + (Math.abs(size * EU_PER_BLOCK_DEPLOY - currentEnergyValue)) + " Eu" }; + } + + // Check specified area for occupation by blocks + // If specified area occupied, break deploying with error message + int occupiedBlockCount = 0; + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + for (int z = 0; z < length; z++) { + if (!worldObj.isAirBlock(targetX + x, targetY + y, targetZ + z)) + occupiedBlockCount++; + } + } + } + + if (occupiedBlockCount > 0) { + System.out.println("[ShipScanner] Deploying area occupied with " + occupiedBlockCount + " blocks. Can't deploy ship."); + return new Object[] { 2, "Deploying area occupied with " + occupiedBlockCount + " blocks. Can't deploy ship." }; + } + + // Consume energy + currentEnergyValue = Math.abs(currentEnergyValue - size * EU_PER_BLOCK_DEPLOY); + + // Set deployment vars + this.blocksToDeploy = new JumpBlock[size]; + this.isDeploying = true; + this.currentDeployIndex = 0; + this.blocksToDeployCount = size; + + this.newX = targetX; + this.newY = targetY; + this.newZ = targetZ; + + System.out.println("[ShipScanner] Target to deploy: (" + targetX + ", " + targetY + ", " + targetZ + ")"); + + // Read blocks and TileEntities from NBT to internal storage array + + System.out.println("[ShipScanner] Loading blocks..."); + byte localBlocks[] = schematic.getByteArray("Blocks"); + byte localMetadata[] = schematic.getByteArray("Data"); + + boolean extra = schematic.hasKey("Add") || schematic.hasKey("AddBlocks"); + byte extraBlocks[] = null; + byte extraBlocksNibble[] = null; + if (schematic.hasKey("AddBlocks")) { + extraBlocksNibble = schematic.getByteArray("AddBlocks"); + extraBlocks = new byte[extraBlocksNibble.length * 2]; + for (int i = 0; i < extraBlocksNibble.length; i++) { + extraBlocks[i * 2 + 0] = (byte) ((extraBlocksNibble[i] >> 4) & 0xF); + extraBlocks[i * 2 + 1] = (byte) (extraBlocksNibble[i] & 0xF); + } + } else if (schematic.hasKey("Add")) { + extraBlocks = schematic.getByteArray("Add"); + } + + // Load Tile Entities + System.out.println("[ShipScanner] Loading TileEntities..."); + NBTTagCompound[] tileEntities = new NBTTagCompound[size]; + NBTTagList tileEntitiesList = schematic.getTagList("TileEntities"); + + for (int i = 0; i < tileEntitiesList.tagCount(); i++) { + NBTTagCompound teTag = (NBTTagCompound) tileEntitiesList.tagAt(i); + int teX = teTag.getInteger("x"); + int teY = teTag.getInteger("y"); + int teZ = teTag.getInteger("z"); + + System.out.println("[ShipScanner] Loaded TE: " + teTag.getString("id")); + tileEntities[teX + (teY * length + teZ) * width] = teTag; + } + + // Create list of blocks to deploy + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + for (int z = 0; z < length; z++) { + JumpBlock jb = new JumpBlock(); + + jb.blockID = (localBlocks[x + (y * length + z) * width]) & 0xFF; + if (extra) + jb.blockID |= ((extraBlocks[x + (y * length + z) * width]) & 0xFF) << 8; + + jb.blockMeta = (localMetadata[x + (y * length + z) * width]) & 0xFF; + jb.blockNBT = tileEntities[x + (y * length + z) * width]; + + jb.x = x; + jb.y = y; + jb.z = z; + + if (jb.blockID != 0 && Block.blocksList[jb.blockID] != null) { + System.out.print("[ShipScanner] Saving block: " + Block.blocksList[jb.blockID].getUnlocalizedName() + ", TE: "); + if (tileEntities[x + (y * length + z) * width] == null) { + System.out.println("null!"); + } else + System.out.println(tileEntities[x + (y * length + z) * width].getString("id")); + } + blocksToDeploy[x + (y * length + z) * width] = jb; + } + } + } + + switchState(1); + System.out.println("[ShipScanner] Ship deployed."); + return new Object[] { 3, "Ship deployed." }; + } + + @Override + public void readFromNBT(NBTTagCompound tag) { + super.readFromNBT(tag); + this.currentEnergyValue = tag.getInteger("energy"); + } + + @Override + public void writeToNBT(NBTTagCompound tag) { + super.writeToNBT(tag); + tag.setInteger("energy", this.getCurrentEnergyValue()); + } + + // CC + // IPeripheral methods implementation + @Override + public String getType() { + return "shipscanner"; + } + + @Override + public String[] getMethodNames() { + return methodsArray; + } + + @Override + public Object[] callMethod(IComputerAccess computer, ILuaContext context, + int method, Object[] arguments) throws Exception { + switch (method) { + case 0: // scanShip() + // Already scanning? + if (this.state == 1) + return new Object[] { false, 0, "Already scanning" }; + + if (core != null && isEnoughEnergyForScan()) { + scanShip(); + } else if (core == null) { + return new Object[] { false, 1, "Warp-Core not found" }; + } else { + return new Object[] { false, 2, "Not enough energy!" }; + } + + break; + case 1: // getSchematicFileName() + if (state != 0 && !schematicFileName.isEmpty()) + return new Object[] { "Scanning in process. Please wait." }; + + return new Object[] { schematicFileName }; + + case 2: // getEnergyLevel() + return new Object[] { currentEnergyValue }; + + case 3: // deployShipFromSchematic(schematicFileName, offsetX, offsetY, offsetZ) + if (arguments.length == 4) { + String fileName = (String)arguments[0]; + int x = ((Double)arguments[1]).intValue(); + int y = ((Double)arguments[2]).intValue(); + int z = ((Double)arguments[3]).intValue(); + + if (!new File(SCHEMATICS_DIR + fileName).exists()) + return new Object[] { 0, "Specified .schematic file not found!" }; + else + { + System.out.println("[ShipScanner] Trying to deploy ship"); + return deployShip(fileName, x, y, z); + } + } else + return new Object[] { 4, ".schematic file name not specified or invalid arguments count!" }; + } + + return null; + } + + @Override + public boolean canAttachToSide(int side) { + return true; + } + + @Override + public void attach(IComputerAccess computer) { + } + + @Override + public void detach(IComputerAccess computer) { + } + + // IEnergySink methods implementation + @Override + public double demandedEnergyUnits() { + return (MAX_ENERGY_VALUE - currentEnergyValue); + } + + @Override + public double injectEnergyUnits(ForgeDirection directionFrom, double amount) { + double leftover = 0; + currentEnergyValue += Math.round(amount); + + if (getCurrentEnergyValue() > MAX_ENERGY_VALUE) { + leftover = (getCurrentEnergyValue() - MAX_ENERGY_VALUE); + currentEnergyValue = MAX_ENERGY_VALUE; + } + + return leftover; + } + + @Override + public int getMaxSafeInput() { + return Integer.MAX_VALUE; + } + + @Override + public boolean acceptsEnergyFrom(TileEntity emitter, + ForgeDirection direction) { + return true; + } + + /** + * @return the currentEnergyValue + */ + public int getCurrentEnergyValue() { + return currentEnergyValue; + } + + public int collectAllEnergy() { + int energy = currentEnergyValue; + currentEnergyValue = 0; + return energy; + } + + @Override + public void onChunkUnload() { + if (addedToEnergyNet) { + MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); + addedToEnergyNet = false; + } + } + + @Override + public void invalidate() { + if (addedToEnergyNet) { + MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)); + addedToEnergyNet = false; + } + + super.invalidate(); + } + + public boolean moveBlockSimple(JumpBlock shipBlock) + { + try + { + if (shipBlock == null) + { + return false; + } + + int oldX = shipBlock.x; + int oldY = shipBlock.y; + int oldZ = shipBlock.z; + + int blockID = shipBlock.blockID; + int blockMeta = shipBlock.blockMeta; + mySetBlock(worldObj, oldX + newX, oldY + newY, oldZ + newZ, blockID, blockMeta, 2); + + NBTTagCompound oldnbt = new NBTTagCompound(); + oldnbt = shipBlock.blockNBT; + if (oldnbt != null) { + TileEntity newTileEntity; + newTileEntity = TileEntity.createAndLoadEntity(oldnbt); + newTileEntity.worldObj = worldObj; + newTileEntity.validate(); + worldObj.setBlockTileEntity(oldX + newX, oldY + newY, oldZ + newZ, newTileEntity); + } + } + catch (Exception exception) + { + exception.printStackTrace(); + return false; + } + + return true; + } + + // Own implementation of setting blocks without light recalculation in optimization purposes + public boolean mySetBlock(World w, int x, int y, int z, int blockId, int blockMeta, int par6) + { + if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) + { + if (y < 0) + { + return false; + } + else if (y >= 256) + { + return false; + } + else + { + w.markBlockForUpdate(x, y, z); + Chunk chunk = w.getChunkFromChunkCoords(x >> 4, z >> 4); + return myChunkSBIDWMT(chunk, x & 15, y, z & 15, blockId, blockMeta); + } + } + else + { + return false; + } + } + + public boolean myChunkSBIDWMT(Chunk c, int x, int y, int z, int blockId, int blockMeta) + { + int j1 = z << 4 | x; + + if (y >= c.precipitationHeightMap[j1] - 1) + { + c.precipitationHeightMap[j1] = -999; + } + + //int k1 = c.heightMap[j1]; + int l1 = c.getBlockID(x, y, z); + int i2 = c.getBlockMetadata(x, y, z); + + if (l1 == blockId && i2 == blockMeta) + { + return false; + } + else + { + ExtendedBlockStorage[] storageArrays = c.getBlockStorageArray(); + ExtendedBlockStorage extendedblockstorage = storageArrays[y >> 4]; + + if (extendedblockstorage == null) + { + if (blockId == 0) + { + return false; + } + + extendedblockstorage = storageArrays[y >> 4] = new ExtendedBlockStorage(y >> 4 << 4, !c.worldObj.provider.hasNoSky); + } + + int j2 = c.xPosition * 16 + x; + int k2 = c.zPosition * 16 + z; + extendedblockstorage.setExtBlockID(x, y & 15, z, blockId); + + if (l1 != 0) + { + if (!c.worldObj.isRemote) + { + Block.blocksList[l1].breakBlock(c.worldObj, j2, y, k2, l1, i2); + } + else if (Block.blocksList[l1] != null && Block.blocksList[l1].hasTileEntity(i2)) + { + TileEntity te = worldObj.getBlockTileEntity(j2, y, k2); + + if (te != null && te.shouldRefresh(l1, blockId, i2, blockMeta, worldObj, j2, y, k2)) + { + c.worldObj.removeBlockTileEntity(j2, y, k2); + } + } + } + + if (extendedblockstorage.getExtBlockID(x, y & 15, z) != blockId) + { + return false; + } + else + { + extendedblockstorage.setExtBlockMetadata(x, y & 15, z, blockMeta); + // Removed light recalculations + /*if (flag) + { + c.generateSkylightMap(); + } + else + { + if (c.getBlockLightOpacity(par1, par2, par3) > 0) + { + if (par2 >= k1) + { + c.relightBlock(par1, par2 + 1, par3); + } + } + else if (par2 == k1 - 1) + { + c.relightBlock(par1, par2, par3); + } + + c.propagateSkylightOcclusion(par1, par3); + }*/ + TileEntity tileentity; + + if (blockId != 0) + { + if (Block.blocksList[blockId] != null && Block.blocksList[blockId].hasTileEntity(blockMeta)) + { + tileentity = c.getChunkBlockTileEntity(x, y, z); + + if (tileentity == null) + { + tileentity = Block.blocksList[blockId].createTileEntity(c.worldObj, blockMeta); + c.worldObj.setBlockTileEntity(j2, y, k2, tileentity); + } + + if (tileentity != null) + { + tileentity.updateContainingBlockInfo(); + tileentity.blockMetadata = blockMeta; + } + } + } + + c.isModified = true; + return true; + } + } + } +} diff --git a/src/cr0s/WarpDrive/WarpCoresRegistry.java b/src/cr0s/WarpDrive/WarpCoresRegistry.java index e0ffa18c..f4649451 100644 --- a/src/cr0s/WarpDrive/WarpCoresRegistry.java +++ b/src/cr0s/WarpDrive/WarpCoresRegistry.java @@ -6,8 +6,8 @@ import net.minecraft.entity.Entity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.MathHelper; -/** - * @authorCr0s +/** Registry of active Warp Cores in world + * @author Cr0s */ public class WarpCoresRegistry { @@ -143,7 +143,7 @@ public class WarpCoresRegistry double d5 = c.zCoord - core.zCoord; double distance = MathHelper.sqrt_double(d3 * d3 + d4 * d4 + d5 * d5); - if (distance <= (2 * core.MAX_SHIP_SIDE) - 1) + if (distance <= (2 * WarpDriveConfig.i.WC_MAX_SHIP_SIDE) - 1) { // Check for warpfields intersections core.prepareToJump(); // calculate spatial parameters diff --git a/src/cr0s/WarpDrive/WarpDrive.java b/src/cr0s/WarpDrive/WarpDrive.java index f8df7b6a..2628c648 100644 --- a/src/cr0s/WarpDrive/WarpDrive.java +++ b/src/cr0s/WarpDrive/WarpDrive.java @@ -34,265 +34,308 @@ import net.minecraftforge.common.ForgeChunkManager.LoadingCallback; import net.minecraftforge.common.ForgeChunkManager.Ticket; import net.minecraftforge.common.MinecraftForge; -@Mod(modid = "WarpDrive", name = "WarpDrive", version = "1.1.5_ZLO", dependencies="required-after:IC2; after:required-AppliedEnergistics; after:extracells; required-after:ComputerCraft; after:CCTurtle; after:gregtech_addon; after:AdvancedSolarPanel; after:AtomicScience; after:ICBM|Explosion; after:MFFS; after:GraviSuite") -@NetworkMod(clientSideRequired = true, serverSideRequired = true, channels = {"WarpDriveBeam", "WarpDriveFreq", "WarpDriveLaserT"}, packetHandler = PacketHandler.class) +@Mod(modid = "WarpDrive", name = "WarpDrive", version = "1.2.0_ZLO", dependencies="required-after:IC2; after:required-AppliedEnergistics; after:extracells; required-after:ComputerCraft; after:CCTurtle; after:gregtech_addon; after:AdvancedSolarPanel; after:AtomicScience; after:ICBM|Explosion; after:MFFS; after:GraviSuite") +@NetworkMod(clientSideRequired = true, serverSideRequired = true, channels = { + "WarpDriveBeam", + "WarpDriveFreq", + "WarpDriveLaserT", + "WarpDriveCloaks" }, packetHandler = PacketHandler.class) /** * @author Cr0s */ public class WarpDrive implements LoadingCallback { - // World limits - public final static int WORLD_LIMIT_BLOCKS = 100000; + // World limits + public final static int WORLD_LIMIT_BLOCKS = 100000; - public static Block warpCore; - public static Block protocolBlock; - public static Block radarBlock; - public static Block isolationBlock; - public static Block airgenBlock; - public static Block laserBlock; - public static Block laserCamBlock; - public static Block cameraBlock; - public static Block monitorBlock; - public static Block boosterBlock; - public static Block miningLaserBlock; - public static Block liftBlock; + public static Block warpCore; + public static Block protocolBlock; + public static Block radarBlock; + public static Block isolationBlock; + public static Block airgenBlock; + public static Block laserBlock; + public static Block laserCamBlock; + public static Block cameraBlock; + public static Block monitorBlock; + public static Block boosterBlock; + public static Block miningLaserBlock; + public static Block liftBlock; + public static Block scannerBlock; + public static Block cloakBlock; + public static Block cloakCoilBlock; - public static Block airBlock; - public static Block gasBlock; + public static Block airBlock; + public static Block gasBlock; - public static Block iridiumBlock; + public static Block iridiumBlock; - public static BiomeGenBase spaceBiome; - public World space; - private int spaceProviderID; - public int spaceDimID; - public SpaceWorldGenerator spaceWorldGenerator; - public HyperSpaceWorldGenerator hyperSpaceWorldGenerator; + public static BiomeGenBase spaceBiome; + public World space; + private int spaceProviderID; + public int spaceDimID; + public SpaceWorldGenerator spaceWorldGenerator; + public HyperSpaceWorldGenerator hyperSpaceWorldGenerator; - public World hyperSpace; - private int hyperSpaceProviderID; - public int hyperSpaceDimID; + public World hyperSpace; + private int hyperSpaceProviderID; + public int hyperSpaceDimID; - @Instance("WarpDrive") - public static WarpDrive instance; - @SidedProxy(clientSide = "cr0s.WarpDrive.ClientProxy", serverSide = "cr0s.WarpDrive.CommonProxy") - public static CommonProxy proxy; + @Instance("WarpDrive") + public static WarpDrive instance; + @SidedProxy(clientSide = "cr0s.WarpDrive.ClientProxy", serverSide = "cr0s.WarpDrive.CommonProxy") + public static CommonProxy proxy; - public WarpCoresRegistry registry; - public JumpGatesRegistry jumpGates; + public WarpCoresRegistry registry; + public JumpGatesRegistry jumpGates; + + public CloakManager cloaks; - public CamRegistry cams; - public boolean isOverlayEnabled = false; - public int overlayType = 0; + public CamRegistry cams; + public boolean isOverlayEnabled = false; + public int overlayType = 0; - @EventHandler - //@PreInit - public void preInit(FMLPreInitializationEvent event) - { - WarpDriveConfig.Init(new Configuration(event.getSuggestedConfigurationFile())); + @EventHandler + //@PreInit + public void preInit(FMLPreInitializationEvent event) + { + WarpDriveConfig.Init(new Configuration(event.getSuggestedConfigurationFile())); - if (FMLCommonHandler.instance().getSide().isClient()) - { - System.out.println("[WarpDrive] Registering sounds event handler..."); - MinecraftForge.EVENT_BUS.register(new SoundHandler()); - } - } + if (FMLCommonHandler.instance().getSide().isClient()) + { + System.out.println("[WarpDrive] Registering sounds event handler..."); + MinecraftForge.EVENT_BUS.register(new SoundHandler()); + } + } - @Init - public void load(FMLInitializationEvent event) - { + @Init + public void load(FMLInitializationEvent event) + { WarpDriveConfig.i.Init2(); - // WARP CORE - this.warpCore = new BlockReactor(WarpDriveConfig.i.coreID, 0, Material.rock) - .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Warp Core"); - LanguageRegistry.addName(warpCore, "Warp Core"); - GameRegistry.registerBlock(warpCore, "warpCore"); - GameRegistry.registerTileEntity(TileEntityReactor.class, "warpCore"); - // CORE CONTROLLER - this.protocolBlock = new BlockProtocol(WarpDriveConfig.i.controllerID, 0, Material.rock) - .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Warp Controller"); - LanguageRegistry.addName(protocolBlock, "Warp Controller"); - GameRegistry.registerBlock(protocolBlock, "protocolBlock"); - GameRegistry.registerTileEntity(TileEntityProtocol.class, "protocolBlock"); - // WARP RADAR - this.radarBlock = new BlockRadar(WarpDriveConfig.i.radarID, 0, Material.rock) - .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("W-Radar"); - LanguageRegistry.addName(radarBlock, "W-Radar"); - GameRegistry.registerBlock(radarBlock, "radarBlock"); - GameRegistry.registerTileEntity(TileEntityRadar.class, "radarBlock"); - // WARP ISOLATION - this.isolationBlock = new BlockWarpIsolation(WarpDriveConfig.i.isolationID, 0, Material.rock) - .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Warp-Field Isolation Block"); - LanguageRegistry.addName(isolationBlock, "Warp-Field Isolation Block"); - GameRegistry.registerBlock(isolationBlock, "isolationBlock"); - // AIR GENERATOR - this.airgenBlock = new BlockAirGenerator(WarpDriveConfig.i.airgenID, 0, Material.rock) - .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Air Generator"); - LanguageRegistry.addName(airgenBlock, "Air Generator"); - GameRegistry.registerBlock(airgenBlock, "airgenBlock"); - GameRegistry.registerTileEntity(TileEntityAirGenerator.class, "airgenBlock"); - // AIR BLOCK - this.airBlock = (new BlockAir(WarpDriveConfig.i.airID)).setHardness(0.0F).setUnlocalizedName("Air block"); - LanguageRegistry.addName(airBlock, "Air block"); - GameRegistry.registerBlock(airBlock, "airBlock"); - // GAS BLOCK - this.gasBlock = (new BlockGas(WarpDriveConfig.i.gasID)).setHardness(0.0F).setUnlocalizedName("Gas block"); - LanguageRegistry.addName(gasBlock, "Gas block"); - GameRegistry.registerBlock(gasBlock, "gasBlock"); - // LASER EMITTER - this.laserBlock = new BlockLaser(WarpDriveConfig.i.laserID, 0, Material.rock) - .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser Emitter"); - LanguageRegistry.addName(laserBlock, "Laser Emitter"); - GameRegistry.registerBlock(laserBlock, "laserBlock"); - GameRegistry.registerTileEntity(TileEntityLaser.class, "laserBlock"); - // LASER EMITTER WITH CAMERA - this.laserCamBlock = new BlockLaserCam(WarpDriveConfig.i.laserCamID, 0, Material.rock) - .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser Emitter + Camera"); - LanguageRegistry.addName(laserCamBlock, "Laser Emitter + Camera"); - GameRegistry.registerBlock(laserCamBlock, "laserCamBlock"); - // CAMERA - this.cameraBlock = new BlockCamera(WarpDriveConfig.i.camID, 0, Material.rock) - .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Camera block"); - LanguageRegistry.addName(cameraBlock, "Camera"); - GameRegistry.registerBlock(cameraBlock, "cameraBlock"); - GameRegistry.registerTileEntity(TileEntityCamera.class, "cameraBlock"); - // MONITOR - this.monitorBlock = new BlockMonitor(WarpDriveConfig.i.monitorID) - .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Monitor"); - LanguageRegistry.addName(monitorBlock, "Monitor"); - GameRegistry.registerBlock(monitorBlock, "monitorBlock"); - GameRegistry.registerTileEntity(TileEntityMonitor.class, "monitorBlock"); - // MINING LASER - this.miningLaserBlock = new BlockMiningLaser(WarpDriveConfig.i.miningLaserID, 0, Material.rock) - .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Mining Laser"); - LanguageRegistry.addName(miningLaserBlock, "Mining Laser"); - GameRegistry.registerBlock(miningLaserBlock, "miningLaserBlock"); - GameRegistry.registerTileEntity(TileEntityMiningLaser.class, "miningLaserBlock"); - // PARTICLE BOOSTER - this.boosterBlock = new BlockParticleBooster(WarpDriveConfig.i.particleBoosterID, 0, Material.rock) - .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Particle Booster"); - LanguageRegistry.addName(boosterBlock, "Particle Booster"); - GameRegistry.registerBlock(boosterBlock, "boosterBlock"); - GameRegistry.registerTileEntity(TileEntityParticleBooster.class, "boosterBlock"); - // RAY LIFT - this.liftBlock = new BlockLift(WarpDriveConfig.i.liftID, 0, Material.rock) - .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser lift"); - LanguageRegistry.addName(liftBlock, "Laser lift"); - GameRegistry.registerBlock(liftBlock, "liftBlock"); - GameRegistry.registerTileEntity(TileEntityLift.class, "liftBlock"); - // IRIDIUM BLOCK - this.iridiumBlock = new BlockIridium(WarpDriveConfig.i.iridiumID) - .setHardness(0.8F).setResistance(150 * 4).setStepSound(Block.soundMetalFootstep) - .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Block of Iridium"); - LanguageRegistry.addName(iridiumBlock, "Block of Iridium"); - GameRegistry.registerBlock(iridiumBlock, "iridiumBlock"); - proxy.registerEntities(); - ForgeChunkManager.setForcedChunkLoadingCallback(instance, instance); - spaceWorldGenerator = new SpaceWorldGenerator(); - GameRegistry.registerWorldGenerator(spaceWorldGenerator); - hyperSpaceWorldGenerator = new HyperSpaceWorldGenerator(); - GameRegistry.registerWorldGenerator(hyperSpaceWorldGenerator); - registerSpaceDimension(); - registerHyperSpaceDimension(); - MinecraftForge.EVENT_BUS.register(new SpaceEventHandler()); + // WARP CORE + this.warpCore = new BlockReactor(WarpDriveConfig.i.coreID, 0, Material.rock) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Warp Core"); + LanguageRegistry.addName(warpCore, "Warp Core"); + GameRegistry.registerBlock(warpCore, "warpCore"); + GameRegistry.registerTileEntity(TileEntityReactor.class, "warpCore"); + // CORE CONTROLLER + this.protocolBlock = new BlockProtocol(WarpDriveConfig.i.controllerID, 0, Material.rock) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Warp Controller"); + LanguageRegistry.addName(protocolBlock, "Warp Controller"); + GameRegistry.registerBlock(protocolBlock, "protocolBlock"); + GameRegistry.registerTileEntity(TileEntityProtocol.class, "protocolBlock"); + // WARP RADAR + this.radarBlock = new BlockRadar(WarpDriveConfig.i.radarID, 0, Material.rock) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("W-Radar"); + LanguageRegistry.addName(radarBlock, "W-Radar"); + GameRegistry.registerBlock(radarBlock, "radarBlock"); + GameRegistry.registerTileEntity(TileEntityRadar.class, "radarBlock"); + // WARP ISOLATION + this.isolationBlock = new BlockWarpIsolation(WarpDriveConfig.i.isolationID, 0, Material.rock) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Warp-Field Isolation Block"); + LanguageRegistry.addName(isolationBlock, "Warp-Field Isolation Block"); + GameRegistry.registerBlock(isolationBlock, "isolationBlock"); + // AIR GENERATOR + this.airgenBlock = new BlockAirGenerator(WarpDriveConfig.i.airgenID, 0, Material.rock) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Air Generator"); + LanguageRegistry.addName(airgenBlock, "Air Generator"); + GameRegistry.registerBlock(airgenBlock, "airgenBlock"); + GameRegistry.registerTileEntity(TileEntityAirGenerator.class, "airgenBlock"); + // AIR BLOCK + this.airBlock = (new BlockAir(WarpDriveConfig.i.airID)).setHardness(0.0F).setUnlocalizedName("Air block"); + LanguageRegistry.addName(airBlock, "Air block"); + GameRegistry.registerBlock(airBlock, "airBlock"); + // GAS BLOCK + this.gasBlock = (new BlockGas(WarpDriveConfig.i.gasID)).setHardness(0.0F).setUnlocalizedName("Gas block"); + LanguageRegistry.addName(gasBlock, "Gas block"); + GameRegistry.registerBlock(gasBlock, "gasBlock"); + // LASER EMITTER + this.laserBlock = new BlockLaser(WarpDriveConfig.i.laserID, 0, Material.rock) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser Emitter"); + LanguageRegistry.addName(laserBlock, "Laser Emitter"); + GameRegistry.registerBlock(laserBlock, "laserBlock"); + GameRegistry.registerTileEntity(TileEntityLaser.class, "laserBlock"); + // LASER EMITTER WITH CAMERA + this.laserCamBlock = new BlockLaserCam(WarpDriveConfig.i.laserCamID, 0, Material.rock) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser Emitter + Camera"); + LanguageRegistry.addName(laserCamBlock, "Laser Emitter + Camera"); + GameRegistry.registerBlock(laserCamBlock, "laserCamBlock"); + // CAMERA + this.cameraBlock = new BlockCamera(WarpDriveConfig.i.camID, 0, Material.rock) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Camera block"); + LanguageRegistry.addName(cameraBlock, "Camera"); + GameRegistry.registerBlock(cameraBlock, "cameraBlock"); + GameRegistry.registerTileEntity(TileEntityCamera.class, "cameraBlock"); + // MONITOR + this.monitorBlock = new BlockMonitor(WarpDriveConfig.i.monitorID) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Monitor"); + LanguageRegistry.addName(monitorBlock, "Monitor"); + GameRegistry.registerBlock(monitorBlock, "monitorBlock"); + GameRegistry.registerTileEntity(TileEntityMonitor.class, "monitorBlock"); + // MINING LASER + this.miningLaserBlock = new BlockMiningLaser(WarpDriveConfig.i.miningLaserID, 0, Material.rock) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Mining Laser"); + LanguageRegistry.addName(miningLaserBlock, "Mining Laser"); + GameRegistry.registerBlock(miningLaserBlock, "miningLaserBlock"); + GameRegistry.registerTileEntity(TileEntityMiningLaser.class, "miningLaserBlock"); + // PARTICLE BOOSTER + this.boosterBlock = new BlockParticleBooster(WarpDriveConfig.i.particleBoosterID, 0, Material.rock) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Particle Booster"); + LanguageRegistry.addName(boosterBlock, "Particle Booster"); + GameRegistry.registerBlock(boosterBlock, "boosterBlock"); + GameRegistry.registerTileEntity(TileEntityParticleBooster.class, "boosterBlock"); + // LASER LIFT + this.liftBlock = new BlockLift(WarpDriveConfig.i.liftID, 0, Material.rock) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Laser lift"); + LanguageRegistry.addName(liftBlock, "Laser lift"); + GameRegistry.registerBlock(liftBlock, "liftBlock"); + GameRegistry.registerTileEntity(TileEntityLift.class, "liftBlock"); + // IRIDIUM BLOCK + this.iridiumBlock = new BlockIridium(WarpDriveConfig.i.iridiumID) + .setHardness(0.8F).setResistance(150 * 4).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Block of Iridium"); + LanguageRegistry.addName(iridiumBlock, "Block of Iridium"); + GameRegistry.registerBlock(iridiumBlock, "iridiumBlock"); - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) - { - MinecraftForge.EVENT_BUS.register(new CameraOverlay(Minecraft.getMinecraft())); - } - } + // SHIP SCANNER + this.scannerBlock = new BlockShipScanner(WarpDriveConfig.i.shipScannerID, 0, Material.rock) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Ship Scanner"); - @PostInit - public void postInit(FMLPostInitializationEvent event) - { - space = DimensionManager.getWorld(spaceDimID); - hyperSpace = DimensionManager.getWorld(hyperSpaceDimID); - GameRegistry.addRecipe(new ItemStack(warpCore), "ici", "cmc", "ici", - 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit")); - GameRegistry.addRecipe(new ItemStack(protocolBlock), "iic", "imi", "cii", - 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit")); - GameRegistry.addRecipe(new ItemStack(radarBlock), "ifi", "imi", "imi", - 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'f', WarpDriveConfig.i.getIC2Item("frequencyTransmitter")); - GameRegistry.addRecipe(new ItemStack(isolationBlock), "iii", "idi", "iii", - 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'd', Block.blockDiamond); - GameRegistry.addRecipe(new ItemStack(airgenBlock), "lcl", "lml", "lll", - 'l', Block.leaves, 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit")); - GameRegistry.addRecipe(new ItemStack(laserBlock), "sss", "ama", "aaa", - 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'a', WarpDriveConfig.i.Compot, 's', WarpDriveConfig.i.getIC2Item("advancedCircuit")); - GameRegistry.addRecipe(new ItemStack(miningLaserBlock), "aaa", "ama", "ccc", - 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.Compot, 'm', WarpDriveConfig.i.getIC2Item("miner")); - GameRegistry.addRecipe(new ItemStack(boosterBlock), "afc", "ama", "cfa", - 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.Compot, 'f', WarpDriveConfig.i.getIC2Item("glassFiberCableItem"), 'm', WarpDriveConfig.i.getIC2Item("mfeUnit")); - GameRegistry.addRecipe(new ItemStack(liftBlock), "aca", "ama", "a#a", - 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.Compot, 'm', WarpDriveConfig.i.getIC2Item("magnetizer")); - /* - GameRegistry.addRecipe(new ItemStack(Item.enderPearl), "uuu", "uuu", "uuu", - 'u', WarpDriveConfig.i.getIC2Item("uraniumDrop")); - */ - GameRegistry.addRecipe(new ItemStack(iridiumBlock), "iii", "iii", "iii", - 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate")); - GameRegistry.addShapelessRecipe(new ItemStack(WarpDriveConfig.i.getIC2Item("iridiumPlate").getItem(), 9), new ItemStack(iridiumBlock)); - GameRegistry.addRecipe(new ItemStack(laserCamBlock), "imi", "cec", "#k#", - 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'e', laserBlock, 'k', cameraBlock); - GameRegistry.addRecipe(new ItemStack(cameraBlock), "cgc", "gmg", "cgc", - 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'g', Block.glass); - GameRegistry.addRecipe(new ItemStack(monitorBlock), "gcg", "gmg", "ggg", - 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'g', Block.glass); - registry = new WarpCoresRegistry(); + LanguageRegistry.addName(scannerBlock, "Ship Scanner"); + GameRegistry.registerBlock(scannerBlock, "scannerBlock"); + GameRegistry.registerTileEntity(TileEntityShipScanner.class, "scannerBlock"); - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) - { - jumpGates = new JumpGatesRegistry(); - } - else - { - cams = new CamRegistry(); - } - } + // CLOAKING DEVICE CORE + this.cloakBlock = new BlockCloakingDeviceCore(WarpDriveConfig.i.cloakCoreID, 0, Material.rock) + .setHardness(0.5F).setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone).setUnlocalizedName("Cloaking Device Core"); - private void registerSpaceDimension() - { - spaceBiome = (new BiomeSpace(23)).setColor(0).setDisableRain().setBiomeName("Space"); - this.spaceProviderID = 14; - DimensionManager.registerProviderType(this.spaceProviderID, SpaceProvider.class, true); - this.spaceDimID = DimensionManager.getNextFreeDimId(); - DimensionManager.registerDimension(this.spaceDimID, this.spaceProviderID); - } + LanguageRegistry.addName(cloakBlock, "Cloaking Device Core"); + GameRegistry.registerBlock(cloakBlock, "cloakBlock"); + GameRegistry.registerTileEntity(TileEntityCloakingDeviceCore.class, "cloakBlock"); - private void registerHyperSpaceDimension() - { - this.hyperSpaceProviderID = 15; - DimensionManager.registerProviderType(this.hyperSpaceProviderID, HyperSpaceProvider.class, true); - this.hyperSpaceDimID = DimensionManager.getNextFreeDimId(); - DimensionManager.registerDimension(this.hyperSpaceDimID, this.hyperSpaceProviderID); - } + // CLOAKING DEVICE COIL + this.cloakCoilBlock = new BlockCloakingCoil(WarpDriveConfig.i.cloakCoilID, 0, Material.rock) + .setHardness(0.5F) + .setStepSound(Block.soundMetalFootstep) + .setCreativeTab(CreativeTabs.tabRedstone) + .setUnlocalizedName("Cloaking Device Coil"); - @ServerStarting - public void serverLoad(FMLServerStartingEvent event) - { - event.registerServerCommand(new GenerateCommand()); - event.registerServerCommand(new SpaceTpCommand()); - event.registerServerCommand(new InvisibleCommand()); - } + LanguageRegistry.addName(cloakCoilBlock, "Cloaking Device Coil"); + GameRegistry.registerBlock(cloakCoilBlock, "cloakCoilBlock"); - @Override - public void ticketsLoaded(List<Ticket> tickets, World world) - { - for (Ticket ticket : tickets) - { - ForgeChunkManager.releaseTicket(ticket); - } - } + proxy.registerEntities(); + ForgeChunkManager.setForcedChunkLoadingCallback(instance, instance); + spaceWorldGenerator = new SpaceWorldGenerator(); + GameRegistry.registerWorldGenerator(spaceWorldGenerator); + hyperSpaceWorldGenerator = new HyperSpaceWorldGenerator(); + GameRegistry.registerWorldGenerator(hyperSpaceWorldGenerator); + registerSpaceDimension(); + registerHyperSpaceDimension(); + MinecraftForge.EVENT_BUS.register(new SpaceEventHandler()); + + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + MinecraftForge.EVENT_BUS.register(new CameraOverlay(Minecraft.getMinecraft())); + } + } + + @PostInit + public void postInit(FMLPostInitializationEvent event) + { + space = DimensionManager.getWorld(spaceDimID); + hyperSpace = DimensionManager.getWorld(hyperSpaceDimID); + GameRegistry.addRecipe(new ItemStack(warpCore), "ici", "cmc", "ici", + 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit")); + GameRegistry.addRecipe(new ItemStack(protocolBlock), "iic", "imi", "cii", + 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit")); + GameRegistry.addRecipe(new ItemStack(radarBlock), "ifi", "imi", "imi", + 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'f', WarpDriveConfig.i.getIC2Item("frequencyTransmitter")); + GameRegistry.addRecipe(new ItemStack(isolationBlock), "iii", "idi", "iii", + 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'd', Block.blockDiamond); + GameRegistry.addRecipe(new ItemStack(airgenBlock), "lcl", "lml", "lll", + 'l', Block.leaves, 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit")); + GameRegistry.addRecipe(new ItemStack(laserBlock), "sss", "ama", "aaa", + 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy"), 's', WarpDriveConfig.i.getIC2Item("advancedCircuit")); + GameRegistry.addRecipe(new ItemStack(miningLaserBlock), "aaa", "ama", "ccc", + 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy"), 'm', WarpDriveConfig.i.getIC2Item("miner")); + GameRegistry.addRecipe(new ItemStack(boosterBlock), "afc", "ama", "cfa", + 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy"), 'f', WarpDriveConfig.i.getIC2Item("glassFiberCableItem"), 'm', WarpDriveConfig.i.getIC2Item("mfeUnit")); + GameRegistry.addRecipe(new ItemStack(liftBlock), "aca", "ama", "a#a", + 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy"), 'm', WarpDriveConfig.i.getIC2Item("magnetizer")); + GameRegistry.addRecipe(new ItemStack(iridiumBlock), "iii", "iii", "iii", + 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate")); + GameRegistry.addShapelessRecipe(new ItemStack(WarpDriveConfig.i.getIC2Item("iridiumPlate").getItem(), 9), new ItemStack(iridiumBlock)); + + GameRegistry.addRecipe(new ItemStack(laserCamBlock), "imi", "cec", "#k#", + 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'e', laserBlock, 'k', cameraBlock); + GameRegistry.addRecipe(new ItemStack(cameraBlock), "cgc", "gmg", "cgc", + 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'g', Block.glass); + GameRegistry.addRecipe(new ItemStack(monitorBlock), "gcg", "gmg", "ggg", + 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'g', Block.glass); + GameRegistry.addRecipe(new ItemStack(scannerBlock), "sgs", "mma", "amm", + 'm', WarpDriveConfig.i.getIC2Item("advancedMachine"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy"), 's', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'g', Block.glass); + GameRegistry.addRecipe(new ItemStack(cloakBlock), "imi", "mcm", "imi", + 'i', iridiumBlock, 'c', cloakCoilBlock, 'm', WarpDriveConfig.i.getIC2Item("advancedMachine")); + GameRegistry.addRecipe(new ItemStack(cloakCoilBlock), "iai", "aca", "iai", + 'i', WarpDriveConfig.i.getIC2Item("iridiumPlate"), 'c', WarpDriveConfig.i.getIC2Item("advancedCircuit"), 'a', WarpDriveConfig.i.getIC2Item("advancedAlloy")); + registry = new WarpCoresRegistry(); + + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) + { + jumpGates = new JumpGatesRegistry(); + } + else + { + cams = new CamRegistry(); + } + } + + private void registerSpaceDimension() + { + spaceBiome = (new BiomeSpace(23)).setColor(0).setDisableRain().setBiomeName("Space"); + this.spaceProviderID = 14; + DimensionManager.registerProviderType(this.spaceProviderID, SpaceProvider.class, true); + this.spaceDimID = DimensionManager.getNextFreeDimId(); + DimensionManager.registerDimension(this.spaceDimID, this.spaceProviderID); + } + + private void registerHyperSpaceDimension() + { + this.hyperSpaceProviderID = 15; + DimensionManager.registerProviderType(this.hyperSpaceProviderID, HyperSpaceProvider.class, true); + this.hyperSpaceDimID = DimensionManager.getNextFreeDimId(); + DimensionManager.registerDimension(this.hyperSpaceDimID, this.hyperSpaceProviderID); + } + + @ServerStarting + public void serverLoad(FMLServerStartingEvent event) + { + cloaks = new CloakManager(); + MinecraftForge.EVENT_BUS.register(new CloakChunkWatcher()); + event.registerServerCommand(new GenerateCommand()); + event.registerServerCommand(new SpaceTpCommand()); + event.registerServerCommand(new InvisibleCommand()); + } + + @Override + public void ticketsLoaded(List<Ticket> tickets, World world) + { + for (Ticket ticket : tickets) + { + ForgeChunkManager.releaseTicket(ticket); + } + } } \ No newline at end of file diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 83a09a65..7b53887f 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -9,7 +9,6 @@ import java.util.Random; import java.lang.reflect.*; import cpw.mods.fml.common.Loader; import net.minecraftforge.common.Configuration; -import net.minecraftforge.oredict.OreDictionary; import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -19,20 +18,69 @@ public class WarpDriveConfig { public static WarpDriveConfig i; private Configuration config; - public int coreID, controllerID, radarID, isolationID, airID, airgenID, gasID, laserID, miningLaserID, particleBoosterID, liftID, laserCamID, camID, monitorID, iridiumID; + public int coreID, controllerID, radarID, isolationID, airID, airgenID, gasID, laserID, miningLaserID, particleBoosterID, liftID, laserCamID, camID, monitorID, iridiumID, shipScannerID, cloakCoreID, cloakCoilID; // public boolean isGregLoaded = false, isAELoaded = false, isAEExtraLoaded = false, isAdvSolPanelLoaded = false, isASLoaded = false, isICBMLoaded = false, isMFFSLoaded = false, isGraviSuiteLoaded = false; // public int[] IC2_Air; public int CC_Computer = 0, CC_peripheral = 0, CCT_Turtle = 0, CCT_Upgraded = 0, CCT_Advanced = 0, GT_Ores = 0, GT_Granite = 0, GT_Machine = 0, ASP = 0, AS_Turbine = 0, ICBM_Machine = 0, ICBM_Missile = 0, MFFS_Field = 0; - public ItemStack Compot; - public Set<Integer> SpaceHelmets, Jetpacks, MinerOres; + public Set<Integer> SpaceHelmets, Jetpacks, MinerOres, scannerIgnoreBlocks; private Class<?> AEBlocks; private Class<?> AEMaterials; private Class<?> AEItems; public Item AEExtraFDI; public ArrayList<int[]> CommonWorldGenOres; + // Mod config + // Warp Core + public int WC_MAX_ENERGY_VALUE = 100000000; + public int WC_ENERGY_PER_BLOCK_MODE1 = 10; // eU + public int WC_ENERGY_PER_DISTANCE_MODE1 = 100; // eU + public int WC_ENERGY_PER_BLOCK_MODE2 = 1000; // eU + public int WC_ENERGY_PER_DISTANCE_MODE2 = 1000; // eU + public int WC_ENERGY_PER_ENTITY_TO_SPACE = 1000000; // eU + public int WC_MAX_JUMP_DISTANCE = 128; // Maximum jump length value + public int WC_MAX_SHIP_VOLUME_ON_SURFACE = 15000; // Maximum ship mass to jump on earth (15k blocks) + public int WC_MIN_SHIP_VOLUME_FOR_HYPERSPACE = 500; // Minimum ship volume value for + public int WC_MAX_SHIP_SIDE = 100; + public int WC_COOLDOWN_INTERVAL_SECONDS = 4; + public int WC_CORES_REGISTRY_UPDATE_INTERVAL_SECONDS = 10; + public int WC_ISOLATION_UPDATE_INTARVAL_SECONDS = 10; + + // Warp Radar + public int WR_MAX_ENERGY_VALUE = 100000000; // 100kk eU + + // Particle Booster + public int PB_MAX_ENERGY_VALUE = 100000; + + // Mining Laser + public int ML_MAX_BOOSTERS_NUMBER = 1; + public int ML_SCAN_DELAY = 20 * 5; + public int ML_MINE_DELAY = 10; + public int ML_EU_PER_LAYER_SPACE = 500; + public int ML_EU_PER_LAYER_EARTH = 5000; + + // Laser Emitter + public int LE_MAX_BOOSTERS_NUMBER = 10; + public int LE_MAX_LASER_ENERGY = 4000000; + public int LE_EMIT_DELAY_TICKS = 20 * 3; + public int LE_EMIT_SCAN_DELAY_TICKS = 10; + public double LE_COLLECT_ENERGY_MULTIPLIER = 0.60D; + public int LE_BEAM_LENGTH_PER_ENERGY_DIVIDER = 5000; + public int LE_ENTITY_HIT_SET_ON_FIRE_TIME = 100; + public int LE_ENTITY_HIT_DAMAGE_PER_ENERGY_DIVIDER = 10000; + public int LE_ENTITY_HIT_EXPLOSION_LASER_ENERGY = 1000000; + public int LE_BLOCK_HIT_CONSUME_ENERGY = 70000; + public int LE_BLOCK_HIT_CONSUME_ENERGY_PER_BLOCK_RESISTANCE = 1000; + public int LE_BLOCK_HIT_CONSUME_ENERGY_PER_DISTANCE = 10; + + // Cloaking device core + public int CD_MAX_CLOAKING_FIELD_SIDE = 100; + public int CD_ENERGY_PER_BLOCK_TIER1 = 1000; + public int CD_ENERGY_PER_BLOCK_TIER2 = 5000; + public int CD_FIELD_REFRESH_INTERVAL_SECONDS = 10; + public int CD_COIL_CAPTURE_BLOCKS = 5; + private WarpDriveConfig() {} public ItemStack getIC2Item(String id) @@ -92,6 +140,61 @@ public class WarpDriveConfig i.config = config; } + public void loadWarpDriveConfig() + { + // Warp Core + WC_MAX_ENERGY_VALUE = config.get("WarpCore", "max_energy_value", 100000000).getInt(); + WC_ENERGY_PER_BLOCK_MODE1 = config.get("WarpCore", "energy_per_block_mode1", 10).getInt(); + WC_ENERGY_PER_DISTANCE_MODE1 = config.get("WarpCore", "energy_per_distance_mode1", 100).getInt(); + WC_ENERGY_PER_DISTANCE_MODE2 = config.get("WarpCore", "energy_per_distance_mode2", 1000).getInt(); + WC_ENERGY_PER_BLOCK_MODE2 = config.get("WarpCore", "energy_per_block_mode2", 1000).getInt(); + WC_ENERGY_PER_ENTITY_TO_SPACE = config.get("WarpCore", "energy_ped_entity_to_space", 1000000).getInt(); + WC_MAX_JUMP_DISTANCE = config.get("WarpCore", "max_jump_distance", 128).getInt(); + WC_MAX_SHIP_VOLUME_ON_SURFACE = config.get("WarpCore", "max_ship_volume_on_surface", 15000).getInt(); // Maximum ship mass to jump on earth (15k blocks) + WC_MIN_SHIP_VOLUME_FOR_HYPERSPACE = config.get("WarpCore", "min_ship_volume_for_hyperspace", 500).getInt(); ; // Minimum ship volume value for hyper space + WC_MAX_SHIP_SIDE = config.get("WarpCore", "max_ship_side", 100).getInt(); + + WC_COOLDOWN_INTERVAL_SECONDS = config.get("WarpCore", "cooldown_interval_seconds", 4).getInt(); + WC_CORES_REGISTRY_UPDATE_INTERVAL_SECONDS = config.get("WarpCore", "cores_registry_update_interval", 10).getInt(); + WC_ISOLATION_UPDATE_INTARVAL_SECONDS = config.get("WarpCore", "isolation_update_interval", 10).getInt(); + + // Warp Radar + WR_MAX_ENERGY_VALUE = config.get("WarpRadar", "max_energy_value", 100000000).getInt(); + + // Particle Booster + PB_MAX_ENERGY_VALUE = config.get("ParticleBooster", "max_energy_value", 100000).getInt(); + + // Mining Laser + ML_MAX_BOOSTERS_NUMBER = config.get("MiningLaser", "max_boosters_number", 1).getInt(); + ML_SCAN_DELAY = 20 * config.get("MiningLaser", "scan_delay_seconds", 5).getInt(); + ML_MINE_DELAY = config.get("MiningLaser", "mine_delay_ticks", 10).getInt(); + ML_EU_PER_LAYER_SPACE = config.get("MiningLaser", "eu_per_layer_space", 500).getInt(); + ML_EU_PER_LAYER_EARTH = config.get("MiningLaser", "eu_per_layer_earth", 5000).getInt(); + + // Laser Emitter + LE_MAX_BOOSTERS_NUMBER = config.get("LaserEmitter", "max_boosters_number", 10).getInt(); + LE_MAX_LASER_ENERGY = config.get("LaserEmitter", "max_laser_energy", 4000000).getInt(); + LE_EMIT_DELAY_TICKS = config.get("LaserEmitter", "emit_delay_ticks", 60).getInt(); + LE_EMIT_SCAN_DELAY_TICKS = config.get("LaserEmitter", "emit_scan_delay_ticks", 10).getInt(); + + // Laser Emitter tweaks + LE_COLLECT_ENERGY_MULTIPLIER = config.get("LaserEmitterTweaks", "collect_energy_multiplier", 0.6D).getDouble(0.6D); + LE_BEAM_LENGTH_PER_ENERGY_DIVIDER = config.get("LaserEmitterTweaks", "beam_length_per_energy_divider", 5000).getInt(); + LE_ENTITY_HIT_SET_ON_FIRE_TIME = config.get("LaserEmitterTweaks", "entity_hit_set_on_fire_time", 100).getInt(); + LE_ENTITY_HIT_DAMAGE_PER_ENERGY_DIVIDER = config.get("LaserEmitterTweaks", "entity_hit_damage_per_energy_divider", 10000).getInt(); + LE_ENTITY_HIT_EXPLOSION_LASER_ENERGY = config.get("LaserEmitterTweaks", "entity_hit_explosion_laser_energy", 1000000).getInt(); + LE_BLOCK_HIT_CONSUME_ENERGY = config.get("LaserEmitterTweaks", "block_hit_consume_energy", 70000).getInt(); + LE_BLOCK_HIT_CONSUME_ENERGY_PER_BLOCK_RESISTANCE = config.get("LaserEmitterTweaks", "block_hit_consume_energy_per_block_resistance", 1000).getInt(); + LE_BLOCK_HIT_CONSUME_ENERGY_PER_DISTANCE = config.get("LaserEmitterTweaks", "block_hit_consume_energy_per_distance", 10).getInt(); + + // Cloaking device core + CD_MAX_CLOAKING_FIELD_SIDE = config.get("CloakingDevice", "max_cloaking_field_side", 100).getInt(); + CD_ENERGY_PER_BLOCK_TIER1 = config.get("CloakingDevice", "energy_per_block_tier1", 125).getInt(); + CD_ENERGY_PER_BLOCK_TIER2 = config.get("CloakingDevice", "energy_per_block_tier2", 500).getInt(); + CD_FIELD_REFRESH_INTERVAL_SECONDS = config.get("CloakingDevice", "field_refresh_interval_seconds", 3).getInt(); + CD_COIL_CAPTURE_BLOCKS = config.get("CloakingDevice", "coil_capture_blocks", 5).getInt(); + } + public void Init2() { CommonWorldGenOres = new ArrayList<int[]>(); @@ -106,6 +209,7 @@ public class WarpDriveConfig SpaceHelmets = new HashSet<Integer>(); Jetpacks = new HashSet<Integer>(); MinerOres = new HashSet<Integer>(); + scannerIgnoreBlocks = new HashSet<Integer>(); config.load(); coreID = config.getBlock("core", 500).getInt(); controllerID = config.getBlock("controller", 501).getInt(); @@ -122,7 +226,9 @@ public class WarpDriveConfig camID = config.getBlock("camera", 513).getInt(); monitorID = config.getBlock("monitor", 514).getInt(); iridiumID = config.getBlock("iridium", 515).getInt(); - config.save(); + shipScannerID = config.getBlock("shipscanner", 516).getInt(); + cloakCoreID = config.getBlock("cloakcore", 517).getInt(); + cloakCoilID = config.getBlock("cloakcoil", 518).getInt(); LoadIC2(); LoadCC(); isGregLoaded = Loader.isModLoaded("gregtech_addon"); @@ -162,6 +268,23 @@ public class WarpDriveConfig MinerOres.add(Block.web.blockID); MinerOres.add(Block.fence.blockID); MinerOres.add(Block.torchWood.blockID); + + // Ignore WarpDrive blocks (which potentially will be duplicated by cheaters using ship scan/deploy) + scannerIgnoreBlocks.add(coreID); + scannerIgnoreBlocks.add(controllerID); + scannerIgnoreBlocks.add(iridiumID); + + scannerIgnoreBlocks.add(Items.getItem("mfsUnit").itemID); + scannerIgnoreBlocks.add(Items.getItem("mfeUnit").itemID); + scannerIgnoreBlocks.add(Items.getItem("cesuUnit").itemID); + scannerIgnoreBlocks.add(Items.getItem("batBox").itemID); + + // Do not scan ores and valuables + for (int[] t : CommonWorldGenOres) // each element of this set is pair [id, meta] + scannerIgnoreBlocks.add(t[0]); // we adding ID only + + loadWarpDriveConfig(); + config.save(); } private void LoadIC2() @@ -170,15 +293,12 @@ public class WarpDriveConfig SpaceHelmets.add(Items.getItem("hazmatHelmet").itemID); SpaceHelmets.add(Items.getItem("quantumHelmet").itemID); Jetpacks.add(Items.getItem("jetpack").itemID); -System.out.println("ZLO1 " + Items.getItem("jetpack").itemID); Jetpacks.add(Items.getItem("electricJetpack").itemID); -System.out.println("ZLO1 " + Items.getItem("electricJetpack").itemID); IC2_Air = new int[] {Items.getItem("airCell").itemID, Items.getItem("airCell").getItemDamage()}; CommonWorldGenOres.add(new int[] {Items.getItem("uraniumOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); CommonWorldGenOres.add(new int[] {Items.getItem("copperOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); CommonWorldGenOres.add(new int[] {Items.getItem("tinOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); MinerOres.add(Items.getItem("rubberWood").itemID); - Compot = Items.getItem("advancedAlloy"); AEExtraFDI = Items.getItem("FluidCell").getItem(); } @@ -211,14 +331,6 @@ System.out.println("ZLO1 " + Items.getItem("electricJetpack").itemID); GT_Granite = t[5]; // 0 - black, 1 - black cobble, 8 - red, 9 - red cobble MinerOres.add(GT_Ores); MinerOres.add(GT_Granite); -/* - ArrayList<ItemStack> t1 = new ArrayList<ItemStack>(); - t1.addAll(OreDictionary.getOres("craftingPlateSteel")); - if (t1.size() >= 3) - Compot = t1.get(2); - else - System.out.println("WarpDriveConfig Error getting craftingPlateSteel " + t1.size()); -*/ } catch (Exception e) { @@ -251,7 +363,7 @@ System.out.println("ZLO1 " + Items.getItem("electricJetpack").itemID); { Class<?> z = Class.forName("extracells.ItemEnum"); Object z1 = z.getEnumConstants()[6]; - AEExtraFDI = (Item)z1.getClass().getDeclaredMethod("getItemEntry").invoke(z1); + AEExtraFDI = (Item)z1.getClass().getDeclaredMethod("getItemInstance").invoke(z1); } catch (Exception e) { @@ -283,6 +395,11 @@ System.out.println("ZLO1 " + Items.getItem("electricJetpack").itemID); { try { +/* + Class<?> z = Class.forName("atomicscience.AtomicScience"); + CommonWorldGenOres.add(new int[] {((Block)z.getField("blockUraniumOre").get(null)).blockID, 0}); + AS_Turbine = ((Block)z.getField("blockElectricTurbine").get(null)).blockID; +*/ Class<?> z = Class.forName("atomicscience.ZhuYaoAS"); CommonWorldGenOres.add(new int[] {((Block)z.getField("bHeOre").get(null)).blockID, 0}); AS_Turbine = ((Block)z.getField("bWoLun").get(null)).blockID; @@ -290,6 +407,7 @@ System.out.println("ZLO1 " + Items.getItem("electricJetpack").itemID); catch (Exception e) { System.out.println("WarpDriveConfig Error loading AS classes"); + e.printStackTrace(); isASLoaded = false; } } diff --git a/src/cr0s/WarpDriveCore/WCClassTransformer.java b/src/cr0s/WarpDriveCore/WCClassTransformer.java index 8032b7e4..9d3b368c 100644 --- a/src/cr0s/WarpDriveCore/WCClassTransformer.java +++ b/src/cr0s/WarpDriveCore/WCClassTransformer.java @@ -24,49 +24,60 @@ public class WCClassTransformer implements net.minecraft.launchwrapper.IClassTra public WCClassTransformer() { - // Obfuscated Notch methods - nodemap.put("worldClass", "abv"); - nodemap.put("playerMP", "ju"); - nodemap.put("netLoginHandler", "jx"); - nodemap.put("confManagerClass", "hm"); + nodemap.put("worldClass", "abw"); + nodemap.put("playerMP", "jv"); + nodemap.put("netLoginHandler", "jy"); + nodemap.put("confManagerClass", "hn"); nodemap.put("createPlayerMethod", "a"); nodemap.put("createPlayerDesc", (new StringBuilder()).append("(Ljava/lang/String;)L").append((String)nodemap.get("playerMP")).append(";").toString()); nodemap.put("respawnPlayerMethod", "a"); nodemap.put("respawnPlayerDesc", (new StringBuilder()).append("(L").append((String)nodemap.get("playerMP")).append(";IZ)L").append((String)nodemap.get("playerMP")).append(";").toString()); - nodemap.put("itemInWorldManagerClass", "jv"); + nodemap.put("itemInWorldManagerClass", "jw"); nodemap.put("attemptLoginMethodBukkit", "attemptLogin"); nodemap.put("attemptLoginDescBukkit", (new StringBuilder()).append("(L").append((String)nodemap.get("netLoginHandler")).append(";Ljava/lang/String;Ljava/lang/String;)L").append((String)nodemap.get("playerMP")).append(";").toString()); - nodemap.put("playerControllerClass", "bcz"); - nodemap.put("playerClient", "bdf"); - nodemap.put("netClientHandler", "bct"); + nodemap.put("playerControllerClass", "bdc"); + nodemap.put("playerClient", "bdi"); + nodemap.put("netClientHandler", "bcw"); nodemap.put("createClientPlayerMethod", "a"); nodemap.put("createClientPlayerDesc", (new StringBuilder()).append("(L").append((String)nodemap.get("worldClass")).append(";)L").append((String)nodemap.get("playerClient")).append(";").toString()); - nodemap.put("entityLivingClass", "oe"); + nodemap.put("entityLivingClass", "of"); nodemap.put("moveEntityMethod", "e"); nodemap.put("moveEntityDesc", "(FF)V"); - nodemap.put("entityItemClass", "sr"); + nodemap.put("entityItemClass", "ss"); nodemap.put("onUpdateMethod", "l_"); nodemap.put("onUpdateDesc", "()V"); - nodemap.put("entityRendererClass", "bfb"); + nodemap.put("entityRendererClass", "bfe"); nodemap.put("updateLightmapMethod", "h"); nodemap.put("updateLightmapDesc", "(F)V"); - nodemap.put("player", "ue"); - nodemap.put("containerPlayer", "vu"); - nodemap.put("invPlayerClass", "uc"); - nodemap.put("minecraft", "ats"); - nodemap.put("session", "aup"); - nodemap.put("guiPlayer", "axs"); - nodemap.put("thePlayer", "g"); + nodemap.put("player", "uf"); + nodemap.put("containerPlayer", "vv"); + nodemap.put("invPlayerClass", "ud"); + nodemap.put("minecraft", "atv"); + nodemap.put("session", "aus"); + nodemap.put("guiPlayer", "axv"); + nodemap.put("thePlayer", "h"); nodemap.put("displayGui", "a"); - nodemap.put("guiScreen", "avv"); + nodemap.put("guiScreen", "awe"); nodemap.put("displayGuiDesc", (new StringBuilder()).append("(L").append((String)nodemap.get("guiScreen")).append(";)V").toString()); nodemap.put("runTick", "k"); nodemap.put("runTickDesc", "()V"); nodemap.put("clickMiddleMouseButton", "W"); nodemap.put("clickMiddleMouseButtonDesc", "()V"); - nodemap.put("itemRendererClass", "bfg"); + nodemap.put("itemRendererClass", "bfj"); nodemap.put("renderOverlaysMethod", "b"); nodemap.put("renderOverlaysDesc", "(F)V"); + nodemap.put("updateFogColorMethod", "i"); + nodemap.put("updateFogColorDesc", "(F)V"); + nodemap.put("getFogColorMethod", "f"); + nodemap.put("getSkyColorMethod", "a"); + nodemap.put("vecClass", "atc"); + nodemap.put("entityClass", "nn"); + nodemap.put("getFogColorDesc", (new StringBuilder()).append("(F)L").append((String)nodemap.get("vecClass")).append(";").toString()); + nodemap.put("getSkyColorDesc", (new StringBuilder()).append("(L").append((String)nodemap.get("entityClass")).append(";F)L").append((String)nodemap.get("vecClass")).append(";").toString()); + nodemap.put("guiSleepClass", "avm"); + nodemap.put("wakeEntityMethod", "g"); + nodemap.put("wakeEntityDesc", "()V"); + nodemap.put("orientCameraDesc", (new StringBuilder()).append("(L").append((String)nodemap.get("minecraft")).append(";L").append((String)nodemap.get("entityLivingClass")).append(";)V").toString()); } @Override diff --git a/src/cr0s/WarpDriveCore/WCDummyContainer.java b/src/cr0s/WarpDriveCore/WCDummyContainer.java index deb2b4a8..dc55b13f 100644 --- a/src/cr0s/WarpDriveCore/WCDummyContainer.java +++ b/src/cr0s/WarpDriveCore/WCDummyContainer.java @@ -21,7 +21,7 @@ public class WCDummyContainer extends DummyModContainer ModMetadata meta = getMetadata(); meta.modId = "WarpDriveCore"; meta.name = "WarpDriveCore"; - meta.version = "1.0.0.0"; + meta.version = "1.0.0.1"; meta.credits = "Cr0s"; meta.authorList = Arrays.asList("cr0s"); meta.description = ""; diff --git a/src/cr0s/WarpDriveCore/WCFMLLoadingPlugin.java b/src/cr0s/WarpDriveCore/WCFMLLoadingPlugin.java index 4b5ef165..f58ce428 100644 --- a/src/cr0s/WarpDriveCore/WCFMLLoadingPlugin.java +++ b/src/cr0s/WarpDriveCore/WCFMLLoadingPlugin.java @@ -7,7 +7,7 @@ import cpw.mods.fml.relauncher.IFMLCallHook; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; -@MCVersion(value = "1.6.2") +@MCVersion(value = "1.6.4") public class WCFMLLoadingPlugin implements IFMLLoadingPlugin, IFMLCallHook { public static File location; From f546f3b4b2cf5db2ea898b14965991bd79c11ef3 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Fri, 14 Feb 2014 02:07:23 +0400 Subject: [PATCH 21/56] Assets & fix --- src/assets/warpdrive/sound/cloak.ogg | Bin 0 -> 90448 bytes src/assets/warpdrive/sound/decloak.ogg | Bin 0 -> 83617 bytes .../textures/blocks/cloakCoilSide.png | Bin 0 -> 704 bytes .../textures/blocks/cloakCoilSideActive.png | Bin 0 -> 1018 bytes .../blocks/cloakCoilSideActive.png.mcmeta | 5 + .../textures/blocks/cloakingCoreActive.png | Bin 0 -> 2030 bytes .../blocks/cloakingCoreActive.png.mcmeta | 5 + .../textures/blocks/cloakingCoreInactive.png | Bin 0 -> 428 bytes .../textures/blocks/shipScannerSide.png | Bin 0 -> 427 bytes .../textures/blocks/shipScannerUp.png | Bin 0 -> 359 bytes src/cr0s/WarpDrive/BlockProtocol.java | 176 +++++++++--------- 11 files changed, 100 insertions(+), 86 deletions(-) create mode 100644 src/assets/warpdrive/sound/cloak.ogg create mode 100644 src/assets/warpdrive/sound/decloak.ogg create mode 100644 src/assets/warpdrive/textures/blocks/cloakCoilSide.png create mode 100644 src/assets/warpdrive/textures/blocks/cloakCoilSideActive.png create mode 100644 src/assets/warpdrive/textures/blocks/cloakCoilSideActive.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/cloakingCoreActive.png create mode 100644 src/assets/warpdrive/textures/blocks/cloakingCoreActive.png.mcmeta create mode 100644 src/assets/warpdrive/textures/blocks/cloakingCoreInactive.png create mode 100644 src/assets/warpdrive/textures/blocks/shipScannerSide.png create mode 100644 src/assets/warpdrive/textures/blocks/shipScannerUp.png diff --git a/src/assets/warpdrive/sound/cloak.ogg b/src/assets/warpdrive/sound/cloak.ogg new file mode 100644 index 0000000000000000000000000000000000000000..49f4c0ec9bcf4c5b5183c802e20d4365bd38bac1 GIT binary patch literal 90448 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 ZdgjaR&7b{Hy3Kmvo!`e06iG}>{D0hUW{v;= literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/sound/decloak.ogg b/src/assets/warpdrive/sound/decloak.ogg new file mode 100644 index 0000000000000000000000000000000000000000..448fcf11a36e5f97c0fc13f6d8f391059d8b3623 GIT binary patch literal 83617 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�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 literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/cloakCoilSide.png b/src/assets/warpdrive/textures/blocks/cloakCoilSide.png new file mode 100644 index 0000000000000000000000000000000000000000..035a97219ac1e27aaf07822ffaf95bdb35591dd8 GIT binary patch literal 704 zcmV;x0zdtUP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv0D}NX z03=P1Nt6Hp010qNS#tmY3ljhU3ljkVnw%H_000McNliru-U0{@BOuieyyO4?02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00JmUL_t(I%cYY+Z(KzXgukBd znYVAl+9nWW89{^)+_)gY|NkA_azWrYHfX)O@4cDs=3tUPkh+wrN>#U#Uw`{O`3%_I z-5txa5D@^Mc%Ele6?bR2<70fvBZ8}|tCxXa;vL00YZy<*Gns%H<vfVdP!DXbyq<!n zNvsoM1LBD!u(#6%AA+V6x4}2_L=FQJGL>$Hk^}9^{o2XN(dyup5*_=>l+uJvVVWA_ zyz#i5=<7?dMWL5O0JXvG?uu?g9T(1R!rpHVo}>!7Zs->1RJfaGR&k0CWNXAOnfn3P z<ngqz_CV&29S%D*6GD(J7}v>eO=1lmWW&}OEf?Zc_$L>d8$;lS>sKtrvG)&yCJVAJ z)V1JSa30CJPik*`y)U>NNZTmO4qE4+jlMb`mJ24+;LUZV4rR1KE6Pcen^h^30?yOX z*`i}M&>VycMHf~r*ms8=J}Q46&uBWu3aU;ICE5nZ0aR|km?`F@3$BT56L}Eq{`5>n zWi{vRex~M*BPXg?On2Dpm9&ZM3xEF`j7+LRiGusU-prM4G$spVGu~}S&_)|4f+W1+ z?SiGF>U?{>=PaF)i7{c1=gwFPsZP_CEeqf8lCf_{SCC5N3e}iSFhqIya6zU<#j!u0 z4WUp@LcAK3nE312d0w5BPWqW5g(wN0l>35*@Z|(r3-aSnKPSM)OQt)B@X?d}KM{G+ mB4h*}L8}$JzPb6FH}fBH(L<$U)T1~60000<MNUMnLSTZfWHuTA literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/cloakCoilSideActive.png b/src/assets/warpdrive/textures/blocks/cloakCoilSideActive.png new file mode 100644 index 0000000000000000000000000000000000000000..7b8c1c3b72aec9b3bac6bc3030477b869236c630 GIT binary patch literal 1018 zcmV<W0|oqvP)<h;3K|Lk000e1NJLTq000mG002-30ssI2pUGlc00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc00(qQO+^RZ0tgQy zAk`1N<NyEw8FWQhbVF}#ZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b02*{fSaefw zW^{L9a%BKeVQFr3E>1;MAa*k@H7+qQF!XYv0009qNkl<ZSVz^C(N2^x5QYC2F#%Tg zf{*|b@B)L1psupfXIM3ncx7S&#tWZ;SMdQbBwqVUc&1-_+W+4*NDPT4C(U%unVGiJ z{=411o!uLuJAU>0@Y(Z&qo=~7Cx^o1cq*sHqsa^V_a7g~DRiHwTVGzTf0}H*c`%;s zjb{(n-X4r+`|I!a)=myLzIL5(I@vy(Zgl6Dfp4=-1A2g;AMXRHW0Wh0o?puTezGn6 z_^=~%7gtC_b8$s{t{{;DP(vW9x@6}H^YowsfQ<@BqewDZ5DzqsF!nmnLAU91018$Q z<c;-|V{m*nylFVo4seAS<+M(q0v!7mWWVn^BW=3$Awc?sR;NhTQe6f_3rfLuqt&sn zlCZooS{~gMmNd#v)3EQZF0G92EG<iU^XomBUyIv(4`<V@Q@sk#!N=;J7&OkPM4WxO z;hdu&r$kwh($%X$k2OMPQMr_n+b^yKiZ;E`t3Ymwv~U&>VN$m)fvKH2y#vV6?t$uF zmEaU%cuD5M+njHkzE%+Aq7Fr<AQ0fY+&fmmgn?RPUQ5dXh!&KB{TJVZP7vJeJ>;;9 zt3Q1YfNmf%a=#Wfj#1rcyC#G`)enQ*5^0Va1KQAZSOG6+(}$=@F}xbCFvx-(!R*zX zZ6T*mFVo0eyL5TIX;BJ51M-rbJBO8ShG$^~bafBq#R(C)@I4R%Oot*(6`9x4asZ+Q zrC|Tp--q@*uK9hiuD%E6oCZB{XBeYd<*Me!5rdB2<(4Hs0T$G&fmFyuslc>X0m7W% z3f2i(Nd+Y)W*%9WjHtkRTCbsLC{mc~R1T<=yzQn11X<}#I}E~8=LVTT!A|Cj_#($` z^`=pWtFHhG&TAPE0z?a{!T#NQ&|=!@LezlR-}$AdzeDdm#0MgMBZR?wSp0tpwcZ0U z6(j<jgS;{JKXL*A(XZ0M9>=JLaE<~2)`Y+n=$+7`O91J66<RobDA-1c99|8LsDmqu zv=Q-A54d_D{i~V-kUD)B&8J%wsENW#(o7_;b>Sg#`IRWqr4A6`BB&+Ew{>u=cv~P< oWLDbc91txi1$*1S4?DZR0Ka(+^2x<+zyJUM07*qoM6N<$f}sDxm;e9( literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/cloakCoilSideActive.png.mcmeta b/src/assets/warpdrive/textures/blocks/cloakCoilSideActive.png.mcmeta new file mode 100644 index 00000000..0645f48c --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/cloakCoilSideActive.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 2 + } +} diff --git a/src/assets/warpdrive/textures/blocks/cloakingCoreActive.png b/src/assets/warpdrive/textures/blocks/cloakingCoreActive.png new file mode 100644 index 0000000000000000000000000000000000000000..48737a1cb3bf2c5f0ed83b757b06facd4d3dd3a5 GIT binary patch literal 2030 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 M07*qoM6N<$f|W(I#sB~S literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/cloakingCoreActive.png.mcmeta b/src/assets/warpdrive/textures/blocks/cloakingCoreActive.png.mcmeta new file mode 100644 index 00000000..0645f48c --- /dev/null +++ b/src/assets/warpdrive/textures/blocks/cloakingCoreActive.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 2 + } +} diff --git a/src/assets/warpdrive/textures/blocks/cloakingCoreInactive.png b/src/assets/warpdrive/textures/blocks/cloakingCoreInactive.png new file mode 100644 index 0000000000000000000000000000000000000000..e235c8638c60ec7535b1a47f6ae13345865c4bef GIT binary patch literal 428 zcmV;d0aN~oP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv03!e; z049^E?_B@@010qNS#tmY3ljhU3ljkVnw%H_000McNliru-U0{>C?!P|Ma}>K02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{009(9L_t(I%cYXRYJ)%!hX2vc zK_o=<Zj)CiwD12U3MD0lrZAG!gLP(mP**n^Z0LVkc9;2P=AWVGmsg8_$N)f^rchM? zaAy=n2*VH}f>s35w(eh5QP(w8wF5LwgZJanBkz*LyI0KKJ&t3T&87nwV*miOJxl^h z2dS97zdW<}IGskol4yHC#pMh<XfQ4q9-j95MaWVx0NCCu2ViF8+4?~8%z~Mr){cO| zd1i*al&isA2@^mN1P{+&MEn+(+`iS@7a{2<LqtAcE%+8P1KjKRp0R^(<}ZfX%e*?< zn`rz!7_;$Yb$3aEic4=-yb8XrSA3q&9a#kE`?CP3&jcbAMFAp$RfS9eKW*#WeN?}P W@sCa@zAW<q0000<MNUMnLSTY3Z>ClN literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/shipScannerSide.png b/src/assets/warpdrive/textures/blocks/shipScannerSide.png new file mode 100644 index 0000000000000000000000000000000000000000..f4a65ce944a1787f9485e213b9a1d42314199ad9 GIT binary patch literal 427 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85p>QK$!8;-MT+OLG}_)Usv|K?DAq}mSS^$m;;3*OI#yLobz*Y zQ}ap~oQqNuOHxx5$}>wc6x=<11Hv2m#DR*WK#GF%(@M${i&7Z^5;OBk^!!{y6v~YC zO!W*6489aC1gd)E>Eak-;Xid^G*^>@NL#vmU}V(2{L9V(B^!O-rlow}E_PKc$|+!X zrh3_f7Qe=*4~qX~&YAyjNU63sH!X2T-=e#9qPYSycGMYstC_aXIIDcukwW#m{~oxf z_^K~(QhJ`PxIyg{*T-eXBHzASuorbE`UYLu!nkbvb7`~3g00ImYB@NUyU!97k-D_} zz`e6_!j0lm|4py#XW1jopm@?@*#u`t=ShYsT$T$09=E<{`?HC$_|^q!D~$sh@)6$u z5BFbrWyAT5`>X-u-7Ny$LEYPOZW-mSdgT^8>7nY<qM46dy{1+(I#?zfAC=<G0{WK0 M)78&qol`;+01c>{>Hq)$ literal 0 HcmV?d00001 diff --git a/src/assets/warpdrive/textures/blocks/shipScannerUp.png b/src/assets/warpdrive/textures/blocks/shipScannerUp.png new file mode 100644 index 0000000000000000000000000000000000000000..0bc463acc6fe86216250f5c918766756ead93ac2 GIT binary patch literal 359 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)2~K9t<kJ{hm{RBAf*t zk;M!Q+`=Ht$S`Y;1W=H@#M9T6{T>sCxQtZfi@l40LXst}5hc#~xw)x%B@E6*sfi`2 zDGKG8B^e6tp1uL$jeO!jMdv+T978NlADz6ruh~GrmB0T`K)?lsK-XKjch*h$^FRIr zyN5}zLd&uPeqEsgMi!ke6L0$%9xs1(tLRht-n*6y_vA*0h`zTy5Y@d%;k415Vx4mj zr=`BFe!p_ntNRPy|8{;}C=>5DZy9HUh(oBLV93|Erxa&1o%wubTNj5?QHH=KO^3*7 zIj^-_bNCW^4oYlxDvfpLbu#N;`|G3ev1O*d&euyBBC;jh9!~JKTzQ%8=fzhWJr3x3 zZTidY|6-=?l&xjyo4N(8WnQaJpMU>%xc)~*udW1jj`xnGK(8@)y85}Sb4q9e056t^ A>;M1& literal 0 HcmV?d00001 diff --git a/src/cr0s/WarpDrive/BlockProtocol.java b/src/cr0s/WarpDrive/BlockProtocol.java index 84cda5d7..c64f912c 100644 --- a/src/cr0s/WarpDrive/BlockProtocol.java +++ b/src/cr0s/WarpDrive/BlockProtocol.java @@ -14,101 +14,105 @@ import net.minecraft.world.World; public class BlockProtocol extends BlockContainer { - private Icon[] iconBuffer; + private Icon[] iconBuffer; - private final int ICON_INACTIVE_SIDE = 0, ICON_BOTTOM = 1, ICON_TOP = 2, ICON_SIDE_ACTIVATED = 3; - //private final int ANIMATION_ - //private int currentTexture; + private final int ICON_INACTIVE_SIDE = 0, ICON_BOTTOM = 1, ICON_TOP = 2, ICON_SIDE_ACTIVATED = 3; + //private final int ANIMATION_ + //private int currentTexture; - public BlockProtocol(int id, int texture, Material material) - { - super(id, material); - } + public BlockProtocol(int id, int texture, Material material) + { + super(id, material); + } - @Override - @SideOnly(Side.CLIENT) - public void registerIcons(IconRegister par1IconRegister) - { - iconBuffer = new Icon[9]; - // Solid textures - iconBuffer[ICON_INACTIVE_SIDE] = par1IconRegister.registerIcon("warpdrive:contSideInactive"); - iconBuffer[ICON_BOTTOM] = par1IconRegister.registerIcon("warpdrive:contBottom"); - iconBuffer[ICON_TOP] = par1IconRegister.registerIcon("warpdrive:contTop"); - // Animated textures - iconBuffer[ICON_SIDE_ACTIVATED] = par1IconRegister.registerIcon("warpdrive:contSideActive1"); - iconBuffer[ICON_SIDE_ACTIVATED + 1] = par1IconRegister.registerIcon("warpdrive:contSideActive2"); - iconBuffer[ICON_SIDE_ACTIVATED + 2] = par1IconRegister.registerIcon("warpdrive:contSideActive3"); - iconBuffer[ICON_SIDE_ACTIVATED + 3] = par1IconRegister.registerIcon("warpdrive:contSideActive4"); - iconBuffer[ICON_SIDE_ACTIVATED + 4] = par1IconRegister.registerIcon("warpdrive:contSideActive5"); - iconBuffer[ICON_SIDE_ACTIVATED + 5] = par1IconRegister.registerIcon("warpdrive:contSideActive6"); - } + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IconRegister par1IconRegister) + { + iconBuffer = new Icon[9]; + // Solid textures + iconBuffer[ICON_INACTIVE_SIDE] = par1IconRegister.registerIcon("warpdrive:contSideInactive"); + iconBuffer[ICON_BOTTOM] = par1IconRegister.registerIcon("warpdrive:contBottom"); + iconBuffer[ICON_TOP] = par1IconRegister.registerIcon("warpdrive:contTop"); + // Animated textures + iconBuffer[ICON_SIDE_ACTIVATED] = par1IconRegister.registerIcon("warpdrive:contSideActive1"); + iconBuffer[ICON_SIDE_ACTIVATED + 1] = par1IconRegister.registerIcon("warpdrive:contSideActive2"); + iconBuffer[ICON_SIDE_ACTIVATED + 2] = par1IconRegister.registerIcon("warpdrive:contSideActive3"); + iconBuffer[ICON_SIDE_ACTIVATED + 3] = par1IconRegister.registerIcon("warpdrive:contSideActive4"); + iconBuffer[ICON_SIDE_ACTIVATED + 4] = par1IconRegister.registerIcon("warpdrive:contSideActive5"); + iconBuffer[ICON_SIDE_ACTIVATED + 5] = par1IconRegister.registerIcon("warpdrive:contSideActive6"); + } - @Override - public Icon getIcon(int side, int metadata) - { - if (side == 0) - { - return iconBuffer[ICON_BOTTOM]; - } - else if (side == 1) - { - return iconBuffer[ICON_TOP]; - } + @Override + public Icon getIcon(int side, int metadata) + { + if (side == 0) + { + return iconBuffer[ICON_BOTTOM]; + } + else if (side == 1) + { + return iconBuffer[ICON_TOP]; + } - if (metadata == 0) // Inactive state - { - return iconBuffer[ICON_INACTIVE_SIDE]; - } - else if (metadata > 0) // Activated, in metadata stored mode number - { - return iconBuffer[ICON_SIDE_ACTIVATED + metadata - 1]; - } + if (metadata == 0) // Inactive state + { + return iconBuffer[ICON_INACTIVE_SIDE]; + } + else if (metadata > 0) // Activated, in metadata stored mode number + { + if (ICON_SIDE_ACTIVATED + metadata - 1 < iconBuffer.length) + return iconBuffer[ICON_SIDE_ACTIVATED + metadata - 1]; + else + return iconBuffer[ICON_SIDE_ACTIVATED]; + } + else + return iconBuffer[ICON_SIDE_ACTIVATED]; + return null; + } - return null; - } + @Override + public TileEntity createNewTileEntity(World var1) + { + return new TileEntityProtocol(); + } - @Override - public TileEntity createNewTileEntity(World var1) - { - return new TileEntityProtocol(); - } + /** + * Returns the quantity of items to drop on block destruction. + */ + @Override + public int quantityDropped(Random par1Random) + { + return 1; + } - /** - * Returns the quantity of items to drop on block destruction. - */ - @Override - public int quantityDropped(Random par1Random) - { - return 1; - } + /** + * Returns the ID of the items to drop on destruction. + */ + @Override + public int idDropped(int par1, Random par2Random, int par3) + { + return this.blockID; + } + /** + * Called upon block activation (right click on the block.) + */ + @Override + public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) + { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + return false; + } - /** - * Returns the ID of the items to drop on destruction. - */ - @Override - public int idDropped(int par1, Random par2Random, int par3) - { - return this.blockID; - } - /** - * Called upon block activation (right click on the block.) - */ - @Override - public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) - { - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) - { - return false; - } + TileEntityProtocol controller = (TileEntityProtocol)par1World.getBlockTileEntity(par2, par3, par4); - TileEntityProtocol controller = (TileEntityProtocol)par1World.getBlockTileEntity(par2, par3, par4); + if (controller != null) + { + controller.attachPlayer(par5EntityPlayer); + par5EntityPlayer.addChatMessage("[WarpCtrlr] Attached players: " + controller.getAttachedPlayersList()); + } - if (controller != null) - { - controller.attachPlayer(par5EntityPlayer); - par5EntityPlayer.addChatMessage("[WarpCtrlr] Attached players: " + controller.getAttachedPlayersList()); - } - - return true; - } + return true; + } } \ No newline at end of file From 97d30da9982f346893b1642879424d8cbbe9060c Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Fri, 14 Feb 2014 02:23:11 +0400 Subject: [PATCH 22/56] fix fix & path for shematics --- src/cr0s/WarpDrive/BlockProtocol.java | 1 - src/cr0s/WarpDrive/TileEntityShipScanner.java | 13 +++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cr0s/WarpDrive/BlockProtocol.java b/src/cr0s/WarpDrive/BlockProtocol.java index c64f912c..e51563f6 100644 --- a/src/cr0s/WarpDrive/BlockProtocol.java +++ b/src/cr0s/WarpDrive/BlockProtocol.java @@ -68,7 +68,6 @@ public class BlockProtocol extends BlockContainer } else return iconBuffer[ICON_SIDE_ACTIVATED]; - return null; } @Override diff --git a/src/cr0s/WarpDrive/TileEntityShipScanner.java b/src/cr0s/WarpDrive/TileEntityShipScanner.java index c5087f40..1cbe3bff 100644 --- a/src/cr0s/WarpDrive/TileEntityShipScanner.java +++ b/src/cr0s/WarpDrive/TileEntityShipScanner.java @@ -59,7 +59,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, int warpCoreSearchTicks = 0; // Config - private final String SCHEMATICS_DIR = "/home/cros/mc_site/schematics/"; + private final String SCHEMATICS_DIR = "schematics"; private final int EU_PER_BLOCK_SCAN = 100; // eU per block of ship volume (including air) private final int EU_PER_BLOCK_DEPLOY = 5000; private final int BLOCK_TO_DEPLOY_PER_TICK = 1000; @@ -83,9 +83,8 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, @Override public void updateEntity() { - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) return; - } if (!addedToEnergyNet && !this.tileEntityInvalid) { MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this)); @@ -440,15 +439,17 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, private void scanShip() { // Enable scanner switchState(1); + File f = new File(SCHEMATICS_DIR); + if (!f.exists() || !f.isDirectory()) + f.mkdirs(); // Generate unique file name do { schematicFileName = (new StringBuilder().append(core.coreFrequency) .append(System.currentTimeMillis()).append(".schematic")) .toString(); - } while (new File(this.SCHEMATICS_DIR + schematicFileName).exists()); - - saveShipToSchematic(this.SCHEMATICS_DIR + schematicFileName); + } while (new File(SCHEMATICS_DIR + "/" + schematicFileName).exists()); + saveShipToSchematic(SCHEMATICS_DIR + "/" + schematicFileName); } private NBTTagCompound readNBTFromFile(String fileName) { From 3177775b7d5f5980056fadcf096c8d0e5b298314 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Sat, 15 Feb 2014 00:35:51 +0400 Subject: [PATCH 23/56] fix --- src/cr0s/WarpDrive/TileEntityReactor.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cr0s/WarpDrive/TileEntityReactor.java b/src/cr0s/WarpDrive/TileEntityReactor.java index 4875175e..73f6a8cb 100644 --- a/src/cr0s/WarpDrive/TileEntityReactor.java +++ b/src/cr0s/WarpDrive/TileEntityReactor.java @@ -201,6 +201,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink return; } +System.out.println("ZLO5"); if (WarpDrive.instance.registry.isWarpCoreIntersectsWithOthers(this)) { this.controller.setJumpFlag(false); @@ -208,6 +209,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink return; } +System.out.println("ZLO6"); if (WarpDrive.instance.cloaks.isInCloak(worldObj.provider.dimensionId, xCoord, yCoord, zCoord, false)) { this.controller.setJumpFlag(false); @@ -215,6 +217,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink return; } +System.out.println("ZLO7"); System.out.println("[W-C] Jumping!"); doJump(); controller.setJumpFlag(false); @@ -479,7 +482,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink this.shipVolume = getRealShipVolume(); - if (shipVolume > WarpDriveConfig.i.WC_MAX_JUMP_DISTANCE && worldObj.provider.dimensionId == 0) + if (shipVolume > WarpDriveConfig.i.WC_MAX_SHIP_VOLUME_ON_SURFACE && worldObj.provider.dimensionId == 0) { this.controller.setJumpFlag(false); return false; From 1453d2ac7cc940c4167eeb837e562da5861dd34a Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Sun, 23 Feb 2014 23:58:32 +0400 Subject: [PATCH 24/56] AE r14 --- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index d827b998..f0319b07 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -53,6 +53,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG private boolean isMining = false; private boolean isQuarry = false; private boolean useDeiterium = false; + private boolean AENetworkReady = false; private String[] methodsArray = { @@ -178,7 +179,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG if (stacks != null) for (ItemStack stack : stacks) { - if (grid != null) + if (grid != null && AENetworkReady) putInGrid(stack); else putInChest(findChest(), stack); @@ -237,7 +238,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG Block block = Block.blocksList[blockID]; if (block == null) return null; - if (useDeiterium && grid != null) + if (useDeiterium && grid != null && AENetworkReady) { IMEInventoryHandler cellArray = grid.getCellArray(); if (cellArray != null) @@ -694,4 +695,14 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG { return true; } + + public void setNetworkReady( boolean isReady ) + { + AENetworkReady = isReady; + } + + public boolean isMachineActive() + { + return true; + } } From 3bddbe428c91610cb3050fcb7f684658c267cde2 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Sun, 25 May 2014 23:03:48 +0400 Subject: [PATCH 25/56] lead fix --- src/cr0s/WarpDrive/WarpDriveConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 7b53887f..dcd3a13f 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -296,8 +296,8 @@ public class WarpDriveConfig Jetpacks.add(Items.getItem("electricJetpack").itemID); IC2_Air = new int[] {Items.getItem("airCell").itemID, Items.getItem("airCell").getItemDamage()}; CommonWorldGenOres.add(new int[] {Items.getItem("uraniumOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); - CommonWorldGenOres.add(new int[] {Items.getItem("copperOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); - CommonWorldGenOres.add(new int[] {Items.getItem("tinOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); + CommonWorldGenOres.add(new int[] {Items.getItem("copperOre").itemID, Items.getItem("copperOre").getItemDamage()}); + CommonWorldGenOres.add(new int[] {Items.getItem("tinOre").itemID, Items.getItem("tinOre").getItemDamage()}); MinerOres.add(Items.getItem("rubberWood").itemID); AEExtraFDI = Items.getItem("FluidCell").getItem(); } From 4a5489641d28fbafa6f6645df6a72de552a39d6e Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Thu, 12 Jun 2014 23:15:46 +0400 Subject: [PATCH 26/56] Real lead fix --- src/cr0s/WarpDrive/WarpDriveConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index dcd3a13f..af7164af 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -298,6 +298,7 @@ public class WarpDriveConfig CommonWorldGenOres.add(new int[] {Items.getItem("uraniumOre").itemID, Items.getItem("uraniumOre").getItemDamage()}); CommonWorldGenOres.add(new int[] {Items.getItem("copperOre").itemID, Items.getItem("copperOre").getItemDamage()}); CommonWorldGenOres.add(new int[] {Items.getItem("tinOre").itemID, Items.getItem("tinOre").getItemDamage()}); + CommonWorldGenOres.add(new int[] {Items.getItem("leadOre").itemID, Items.getItem("leadOre").getItemDamage()}); MinerOres.add(Items.getItem("rubberWood").itemID); AEExtraFDI = Items.getItem("FluidCell").getItem(); } From 33075f13c4ea56fc163bf5e4472f2cf3c3c04c33 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Mon, 16 Jun 2014 21:25:44 +0400 Subject: [PATCH 27/56] Miner fix --- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index f0319b07..d5e13b9a 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -133,15 +133,15 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG { if (++delayTicksMine > WarpDriveConfig.i.ML_MINE_DELAY) { - delayTicksMine = 0; - if (valuableIndex < valuablesInLayer.size()) { //System.out.println("[ML] Mining: " + (valuableIndex + 1) + "/" + valuablesInLayer.size()); Vector3 valuable = valuablesInLayer.get(valuableIndex++); // Mine valuable ore int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); - + if (blockID == 0) + return; + delayTicksMine = 0; // Skip if block is too hard or its empty block if (!canDig(blockID)) return; @@ -152,6 +152,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG } else { + delayTicksMine = 0; currentMode = 0; --currentLayer; } @@ -163,6 +164,8 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG private boolean canDig(int blockID) { + if (blockID == 0) + return false; if (Block.blocksList[blockID] != null) return ((blockID == WarpDriveConfig.i.GT_Granite || blockID == WarpDriveConfig.i.GT_Ores || blockID == WarpDriveConfig.i.iridiumID || Block.blocksList[blockID].blockResistance <= Block.obsidian.blockResistance) && blockID != WarpDriveConfig.i.MFFS_Field && blockID != Block.bedrock.blockID); else From e41c5383937ec15ad96b0832542d04213abe0d3d Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Sun, 6 Jul 2014 21:26:56 +0400 Subject: [PATCH 28/56] Perrer lasors --- src/cr0s/WarpDrive/TileEntityLaser.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityLaser.java b/src/cr0s/WarpDrive/TileEntityLaser.java index af56e514..2add2614 100644 --- a/src/cr0s/WarpDrive/TileEntityLaser.java +++ b/src/cr0s/WarpDrive/TileEntityLaser.java @@ -141,7 +141,7 @@ public class TileEntityLaser extends TileEntity implements IPeripheral int beamLengthBlocks = energy / WarpDriveConfig.i.LE_BEAM_LENGTH_PER_ENERGY_DIVIDER; System.out.println("Energy: " + energy + " | beamLengthBlocks: " + beamLengthBlocks); - if (energy == 0 || beamLengthBlocks < 1) + if (energy == 0 || beamLengthBlocks < 1 || frequency > 65000 || frequency <= 0) { return; } @@ -163,6 +163,8 @@ public class TileEntityLaser extends TileEntity implements IPeripheral Vector3 endPoint = reachPoint.clone(); playSoundCorrespondsEnergy(energy); + int distanceTravelled = 0; //distance travelled from beam emitter to previous hit if there were any + // This is scanning beam, do not deal damage to blocks if (frequency == 1420) { @@ -265,7 +267,8 @@ public class TileEntityLaser extends TileEntity implements IPeripheral endPoint = new Vector3(hit.hitVec); } - energy -= WarpDriveConfig.i.LE_BLOCK_HIT_CONSUME_ENERGY + (resistance * WarpDriveConfig.i.LE_BLOCK_HIT_CONSUME_ENERGY_PER_BLOCK_RESISTANCE) + (distance * WarpDriveConfig.i.LE_BLOCK_HIT_CONSUME_ENERGY_PER_DISTANCE); + energy -= WarpDriveConfig.i.LE_BLOCK_HIT_CONSUME_ENERGY + (resistance * WarpDriveConfig.i.LE_BLOCK_HIT_CONSUME_ENERGY_PER_BLOCK_RESISTANCE) + ( (distance - distanceTravelled) * WarpDriveConfig.i.LE_BLOCK_HIT_CONSUME_ENERGY_PER_DISTANCE); + distanceTravelled = distance; endPoint = new Vector3(hit.hitVec); if (energy <= 0) @@ -513,7 +516,7 @@ public class TileEntityLaser extends TileEntity implements IPeripheral private boolean parseFrequency(int freq) { - if (freq > 65000 || freq < 0) // Invalid frequency + if (freq > 65000 || freq <= 0) // Invalid frequency { r = 1; g = 0; @@ -521,7 +524,7 @@ public class TileEntityLaser extends TileEntity implements IPeripheral return false; } - if (freq > 0 && freq < 10000) // red + if (freq > 0 && freq <= 10000) // red { r = 1; g = 0; From 4b8a0c7b3b4cf0572247907d27982ab98cd5e166 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Mon, 7 Jul 2014 01:29:51 +0400 Subject: [PATCH 29/56] Fixes --- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 16 +++++----------- src/cr0s/WarpDrive/TileEntityShipScanner.java | 4 ++-- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index d5e13b9a..c9bc3d9c 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -133,24 +133,18 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG { if (++delayTicksMine > WarpDriveConfig.i.ML_MINE_DELAY) { - if (valuableIndex < valuablesInLayer.size()) + delayTicksMine = 0; + while(valuableIndex < valuablesInLayer.size()) { - //System.out.println("[ML] Mining: " + (valuableIndex + 1) + "/" + valuablesInLayer.size()); Vector3 valuable = valuablesInLayer.get(valuableIndex++); - // Mine valuable ore int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); - if (blockID == 0) - return; - delayTicksMine = 0; - // Skip if block is too hard or its empty block - if (!canDig(blockID)) - return; - + if (blockID == 0 || !canDig(blockID)) + continue; sendLaserPacket(minerVector, new Vector3(valuable.intX(), valuable.intY(), valuable.intZ()).add(0.5), 1, 1, 0, 2 * WarpDriveConfig.i.ML_MINE_DELAY, 0, 50); worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F); harvestBlock(valuable); } - else + if (valuableIndex >= valuablesInLayer.size()) { delayTicksMine = 0; currentMode = 0; diff --git a/src/cr0s/WarpDrive/TileEntityShipScanner.java b/src/cr0s/WarpDrive/TileEntityShipScanner.java index 1cbe3bff..b2e58d0a 100644 --- a/src/cr0s/WarpDrive/TileEntityShipScanner.java +++ b/src/cr0s/WarpDrive/TileEntityShipScanner.java @@ -479,7 +479,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, // Returns result array for CC interface: [ code, "message" ] private Object[] deployShip(String fileName, int offsetX, int offsetY, int offsetZ) { - NBTTagCompound schematic = readNBTFromFile(SCHEMATICS_DIR + fileName); + NBTTagCompound schematic = readNBTFromFile(SCHEMATICS_DIR + "/" + fileName); if (schematic == null) { System.out.println("[ShipScanner] Schematic is null!"); @@ -671,7 +671,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, int y = ((Double)arguments[2]).intValue(); int z = ((Double)arguments[3]).intValue(); - if (!new File(SCHEMATICS_DIR + fileName).exists()) + if (!new File(SCHEMATICS_DIR + "/" + fileName).exists()) return new Object[] { 0, "Specified .schematic file not found!" }; else { From f675815f224541d714c9bbdbcd09842c65a224e2 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Mon, 7 Jul 2014 20:12:03 +0400 Subject: [PATCH 30/56] CHROS UEBAN --- src/cr0s/WarpDrive/TileEntityShipScanner.java | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityShipScanner.java b/src/cr0s/WarpDrive/TileEntityShipScanner.java index b2e58d0a..8a497a2d 100644 --- a/src/cr0s/WarpDrive/TileEntityShipScanner.java +++ b/src/cr0s/WarpDrive/TileEntityShipScanner.java @@ -167,7 +167,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, deployDelayTicks = 0; int blocks = Math.min(BLOCK_TO_DEPLOY_PER_TICK, blocksToDeployCount - currentDeployIndex); - System.out.println("[ShipScanner] Deploying ship part: " + currentDeployIndex + "/" + blocksToDeployCount + " [remains: " + blocks + "]"); +// System.out.println("[ShipScanner] Deploying ship part: " + currentDeployIndex + "/" + blocksToDeployCount + " [remains: " + blocks + "]"); if (blocks == 0) { isDeploying = false; @@ -334,14 +334,14 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, schematic.setShort("Length", length); schematic.setShort("Height", height); - System.out.println("[ShipScanner] Ship parameters: w: " + width + ", l: " + length + ", h:" + height); +// System.out.println("[ShipScanner] Ship parameters: w: " + width + ", l: " + length + ", h:" + height); int size = width * length * height; // Consume energy currentEnergyValue = Math.abs(currentEnergyValue - size * EU_PER_BLOCK_SCAN); - System.out.println("[ShipScanner] Size: " + size); +// System.out.println("[ShipScanner] Size: " + size); byte localBlocks[] = new byte[size]; byte localMetadata[] = new byte[size]; @@ -416,7 +416,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, } private void writeNBTToFile(String fileName, NBTTagCompound nbttagcompound) { - System.out.println("[ShipScanner] Filename: " + fileName); +// System.out.println("[ShipScanner] Filename: " + fileName); try { File file = new File(fileName); @@ -482,7 +482,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, NBTTagCompound schematic = readNBTFromFile(SCHEMATICS_DIR + "/" + fileName); if (schematic == null) { - System.out.println("[ShipScanner] Schematic is null!"); +// System.out.println("[ShipScanner] Schematic is null!"); return new Object[] { -1, "Unknow error. Schematic NBT is null" }; } @@ -504,11 +504,11 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, int size = width* height * length; - System.out.println("[ShipScanner] Deploying ship: (size: " + size + ", h: " + height + ", w: " + width + ", l: " + length + ")"); +// System.out.println("[ShipScanner] Deploying ship: (size: " + size + ", h: " + height + ", w: " + width + ", l: " + length + ")"); // Check energy level if (!isEnoughEnergyForDeploy(size)) { - System.out.println("[ShipScanner] Not enough energy! Need at least " + (Math.abs(size * EU_PER_BLOCK_DEPLOY - currentEnergyValue)) + " Eu"); +// System.out.println("[ShipScanner] Not enough energy! Need at least " + (Math.abs(size * EU_PER_BLOCK_DEPLOY - currentEnergyValue)) + " Eu"); return new Object[] { 1, "Not enough energy! Need at least " + (Math.abs(size * EU_PER_BLOCK_DEPLOY - currentEnergyValue)) + " Eu" }; } @@ -525,7 +525,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, } if (occupiedBlockCount > 0) { - System.out.println("[ShipScanner] Deploying area occupied with " + occupiedBlockCount + " blocks. Can't deploy ship."); +// System.out.println("[ShipScanner] Deploying area occupied with " + occupiedBlockCount + " blocks. Can't deploy ship."); return new Object[] { 2, "Deploying area occupied with " + occupiedBlockCount + " blocks. Can't deploy ship." }; } @@ -542,11 +542,11 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, this.newY = targetY; this.newZ = targetZ; - System.out.println("[ShipScanner] Target to deploy: (" + targetX + ", " + targetY + ", " + targetZ + ")"); +// System.out.println("[ShipScanner] Target to deploy: (" + targetX + ", " + targetY + ", " + targetZ + ")"); // Read blocks and TileEntities from NBT to internal storage array - System.out.println("[ShipScanner] Loading blocks..."); +// System.out.println("[ShipScanner] Loading blocks..."); byte localBlocks[] = schematic.getByteArray("Blocks"); byte localMetadata[] = schematic.getByteArray("Data"); @@ -565,7 +565,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, } // Load Tile Entities - System.out.println("[ShipScanner] Loading TileEntities..."); +// System.out.println("[ShipScanner] Loading TileEntities..."); NBTTagCompound[] tileEntities = new NBTTagCompound[size]; NBTTagList tileEntitiesList = schematic.getTagList("TileEntities"); @@ -575,7 +575,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, int teY = teTag.getInteger("y"); int teZ = teTag.getInteger("z"); - System.out.println("[ShipScanner] Loaded TE: " + teTag.getString("id")); +// System.out.println("[ShipScanner] Loaded TE: " + teTag.getString("id")); tileEntities[teX + (teY * length + teZ) * width] = teTag; } @@ -595,7 +595,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, jb.x = x; jb.y = y; jb.z = z; - +/* if (jb.blockID != 0 && Block.blocksList[jb.blockID] != null) { System.out.print("[ShipScanner] Saving block: " + Block.blocksList[jb.blockID].getUnlocalizedName() + ", TE: "); if (tileEntities[x + (y * length + z) * width] == null) { @@ -603,13 +603,14 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, } else System.out.println(tileEntities[x + (y * length + z) * width].getString("id")); } +*/ blocksToDeploy[x + (y * length + z) * width] = jb; } } } switchState(1); - System.out.println("[ShipScanner] Ship deployed."); +// System.out.println("[ShipScanner] Ship deployed."); return new Object[] { 3, "Ship deployed." }; } @@ -675,7 +676,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, return new Object[] { 0, "Specified .schematic file not found!" }; else { - System.out.println("[ShipScanner] Trying to deploy ship"); +// System.out.println("[ShipScanner] Trying to deploy ship"); return deployShip(fileName, x, y, z); } } else From 2f9735c42873ba9ea32bab2cccf0a047f6d07d80 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Mon, 7 Jul 2014 22:14:34 +0400 Subject: [PATCH 31/56] Fix --- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index c9bc3d9c..1a9c8061 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -143,13 +143,11 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG sendLaserPacket(minerVector, new Vector3(valuable.intX(), valuable.intY(), valuable.intZ()).add(0.5), 1, 1, 0, 2 * WarpDriveConfig.i.ML_MINE_DELAY, 0, 50); worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F); harvestBlock(valuable); + return;//top lel, yes yes } - if (valuableIndex >= valuablesInLayer.size()) - { - delayTicksMine = 0; - currentMode = 0; - --currentLayer; - } + delayTicksMine = 0; + currentMode = 0; + --currentLayer; } } } From c082696af24bd94dfbac1654287c90190a808b27 Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Tue, 8 Jul 2014 05:33:50 +0400 Subject: [PATCH 32/56] miner fix & proposed future fixes Changed to "digging resistance" instead of "blast resistance" assuming this laser isn't a combat one. --- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index 1a9c8061..928538e6 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -159,7 +159,12 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG if (blockID == 0) return false; if (Block.blocksList[blockID] != null) - return ((blockID == WarpDriveConfig.i.GT_Granite || blockID == WarpDriveConfig.i.GT_Ores || blockID == WarpDriveConfig.i.iridiumID || Block.blocksList[blockID].blockResistance <= Block.obsidian.blockResistance) && blockID != WarpDriveConfig.i.MFFS_Field && blockID != Block.bedrock.blockID); + return ( (blockID == WarpDriveConfig.i.GT_Granite || + blockID == WarpDriveConfig.i.GT_Ores || + blockID == WarpDriveConfig.i.iridiumID || + Block.blocksList[blockID].blockHardness <= Block.obsidian.blockHardness) && + blockID !=WarpDriveConfig.i.MFFS_Field && + blockID != Block.bedrock.blockID ); //TODO maybe change to WarpDriveConfig.i.MinerOres instead? else return (blockID != WarpDriveConfig.i.MFFS_Field && blockID != Block.bedrock.blockID); } @@ -270,7 +275,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG { if (inventory == null || itemStackSource == null) { - return 0; + return 0; //TODO stop operation/raise error/etc instead of losing valuables silently (i.e. no chests and with AE problems) } int transferred = 0; From 229793faa3bb4e511c53bf7103b738bf0a6d64b4 Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Tue, 8 Jul 2014 05:54:36 +0400 Subject: [PATCH 33/56] minor --- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index 928538e6..f8babb47 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -47,8 +47,6 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG Boolean powerStatus = false; private IGridInterface grid; - private final int MAX_BOOSTERS_NUMBER = 1; - private int dx, dz, dy; private boolean isMining = false; private boolean isQuarry = false; @@ -275,7 +273,7 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG { if (inventory == null || itemStackSource == null) { - return 0; //TODO stop operation/raise error/etc instead of losing valuables silently (i.e. no chests and with AE problems) + return 0; //TODO stop operation/raise error/etc instead of losing valuables silently (i.e. no chests and with AE problems) } int transferred = 0; From b9f301446ce03204a6eb2ebe4e899b7b55c9e841 Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Tue, 8 Jul 2014 05:55:43 +0400 Subject: [PATCH 34/56] minor --- src/cr0s/WarpDrive/WarpDriveConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index af7164af..72b4414a 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -54,7 +54,7 @@ public class WarpDriveConfig public int PB_MAX_ENERGY_VALUE = 100000; // Mining Laser - public int ML_MAX_BOOSTERS_NUMBER = 1; + public int ML_MAX_BOOSTERS_NUMBER = 1; //unused public int ML_SCAN_DELAY = 20 * 5; public int ML_MINE_DELAY = 10; public int ML_EU_PER_LAYER_SPACE = 500; From a5b99b55e35bf49d8f91618586bf6c3a9f0c68bd Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Wed, 9 Jul 2014 07:48:19 +0400 Subject: [PATCH 35/56] removed unused setting --- src/cr0s/WarpDrive/WarpDriveConfig.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 72b4414a..311766d0 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -54,7 +54,6 @@ public class WarpDriveConfig public int PB_MAX_ENERGY_VALUE = 100000; // Mining Laser - public int ML_MAX_BOOSTERS_NUMBER = 1; //unused public int ML_SCAN_DELAY = 20 * 5; public int ML_MINE_DELAY = 10; public int ML_EU_PER_LAYER_SPACE = 500; From 88f12c3a4d6f1fa7dfeb06514d72a7dd32f5bfe8 Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Wed, 9 Jul 2014 07:54:18 +0400 Subject: [PATCH 36/56] miner fix --- src/cr0s/WarpDrive/TileEntityMiningLaser.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index f8babb47..6f44e201 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -129,10 +129,10 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG } else { - if (++delayTicksMine > WarpDriveConfig.i.ML_MINE_DELAY) + if (++delayTicksMine > WarpDriveConfig.i.ML_MINE_DELAY && isMining) { delayTicksMine = 0; - while(valuableIndex < valuablesInLayer.size()) + while(valuableIndex < valuablesInLayer.size() && isMining) { Vector3 valuable = valuablesInLayer.get(valuableIndex++); int blockID = worldObj.getBlockId(valuable.intX(), valuable.intY(), valuable.intZ()); @@ -157,12 +157,10 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG if (blockID == 0) return false; if (Block.blocksList[blockID] != null) - return ( (blockID == WarpDriveConfig.i.GT_Granite || - blockID == WarpDriveConfig.i.GT_Ores || - blockID == WarpDriveConfig.i.iridiumID || + return ( (WarpDriveConfig.i.MinerOres.contains(blockID) || Block.blocksList[blockID].blockHardness <= Block.obsidian.blockHardness) && blockID !=WarpDriveConfig.i.MFFS_Field && - blockID != Block.bedrock.blockID ); //TODO maybe change to WarpDriveConfig.i.MinerOres instead? + blockID != Block.bedrock.blockID ); else return (blockID != WarpDriveConfig.i.MFFS_Field && blockID != Block.bedrock.blockID); } @@ -273,7 +271,8 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG { if (inventory == null || itemStackSource == null) { - return 0; //TODO stop operation/raise error/etc instead of losing valuables silently (i.e. no chests and with AE problems) + isMining = false; //stopping operation + return 0; } int transferred = 0; From 3cb47ff6b21033d08adbd111b270b6bace223858 Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Sun, 13 Jul 2014 21:59:49 +0400 Subject: [PATCH 37/56] will prevent messing with ship's dimensions --- src/cr0s/WarpDrive/TileEntityReactor.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityReactor.java b/src/cr0s/WarpDrive/TileEntityReactor.java index 73f6a8cb..43aa1580 100644 --- a/src/cr0s/WarpDrive/TileEntityReactor.java +++ b/src/cr0s/WarpDrive/TileEntityReactor.java @@ -472,10 +472,11 @@ System.out.println("ZLO7"); this.shipSize = this.shipDown + this.shipUp; break; } - - // Ship side is too big - if (shipLength > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || shipWidth > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || shipHeight > WarpDriveConfig.i.WC_MAX_SHIP_SIDE) + + // Ship size is too big + if (this.shipSize + 1 > WarpDriveConfig.i.WC_MAX_SHIP_SIDE) { + messageToAllPlayersOnShip("Ship is too long. Cannot jump."); this.controller.setJumpFlag(false); return false; } From c3aa2e63844b88bd404990d88a8421be508e4a67 Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Sun, 13 Jul 2014 22:07:26 +0400 Subject: [PATCH 38/56] 100-meter ships are too short --- src/cr0s/WarpDrive/WarpDriveConfig.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index af7164af..cf62d56c 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -40,9 +40,9 @@ public class WarpDriveConfig public int WC_ENERGY_PER_DISTANCE_MODE2 = 1000; // eU public int WC_ENERGY_PER_ENTITY_TO_SPACE = 1000000; // eU public int WC_MAX_JUMP_DISTANCE = 128; // Maximum jump length value - public int WC_MAX_SHIP_VOLUME_ON_SURFACE = 15000; // Maximum ship mass to jump on earth (15k blocks) - public int WC_MIN_SHIP_VOLUME_FOR_HYPERSPACE = 500; // Minimum ship volume value for - public int WC_MAX_SHIP_SIDE = 100; + public int WC_MAX_SHIP_VOLUME_ON_SURFACE = 15000; // Maximum ship volume to jump on earth + public int WC_MIN_SHIP_VOLUME_FOR_HYPERSPACE = 500; // Minimum ship volume value for hyperspace travel + public int WC_MAX_SHIP_SIDE = 127; public int WC_COOLDOWN_INTERVAL_SECONDS = 4; public int WC_CORES_REGISTRY_UPDATE_INTERVAL_SECONDS = 10; public int WC_ISOLATION_UPDATE_INTARVAL_SECONDS = 10; From 6c3de58627df3b95d658dd368d1350679195a75f Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Mon, 14 Jul 2014 20:11:22 +0400 Subject: [PATCH 39/56] got rid of some CROSOCODE --- src/cr0s/WarpDrive/TileEntityReactor.java | 85 ++++------------------- 1 file changed, 12 insertions(+), 73 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityReactor.java b/src/cr0s/WarpDrive/TileEntityReactor.java index 43aa1580..6b29554f 100644 --- a/src/cr0s/WarpDrive/TileEntityReactor.java +++ b/src/cr0s/WarpDrive/TileEntityReactor.java @@ -53,8 +53,8 @@ public class TileEntityReactor extends TileEntity implements IEnergySink public int shipLeft, shipRight; public int shipUp, shipDown; public int shipHeight, shipWidth, shipLength; - int shipSize = 0; - int shipVolume; + int shipSize = 0; //ship length in the direction of a jump + int shipVolume = 0; //number of all blocks the ship consists of int currentMode = 0; int currentEnergyValue = 0; @@ -67,7 +67,6 @@ public class TileEntityReactor extends TileEntity implements IEnergySink private final byte MODE_GATE_JUMP = 6; // Jump via jumpgate int cooldownTime = 0; - public int randomCooldownAddition = 0; private int registryUpdateTicks = 0; public String coreFrequency = "default"; @@ -188,7 +187,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink } // Awaiting cooldown time - if (/*currentMode != MODE_BASIC_JUMP && */cooldownTime++ < ((WarpDriveConfig.i.WC_COOLDOWN_INTERVAL_SECONDS) * 20) + randomCooldownAddition) + if (/*currentMode != MODE_BASIC_JUMP && */cooldownTime++ < ((WarpDriveConfig.i.WC_COOLDOWN_INTERVAL_SECONDS) * 20) ) { return; } @@ -392,89 +391,29 @@ System.out.println("ZLO7"); public boolean calculateSpatialShipParameters() { - int x1 = 0, x2 = 0, z1 = 0, z2 = 0; - - if (Math.abs(dx) > 0) - { - if (dx == 1) - { - x1 = xCoord - shipBack; - x2 = xCoord + shipFront; - z1 = zCoord - shipLeft; - z2 = zCoord + shipRight; - } - else - { - x1 = xCoord - shipFront; - x2 = xCoord + shipBack; - z1 = zCoord - shipRight; - z2 = zCoord + shipLeft; - } - } - else if (Math.abs(dz) > 0) - { - if (dz == 1) - { - z1 = zCoord - shipBack; - z2 = zCoord + shipFront; - x1 = xCoord - shipRight; - x2 = xCoord + shipLeft; - } - else - { - z1 = zCoord - shipFront; - z2 = zCoord + shipBack; - x1 = xCoord - shipLeft; - x2 = xCoord + shipRight; - } - } - - if (x1 < x2) - { - minX = x1; - maxX = x2; - } - else - { - minX = x2; - maxX = x1; - } - - if (z1 < z2) - { - minZ = z1; - maxZ = z2; - } - else - { - minZ = z2; - maxZ = z1; - } - - minY = yCoord - shipDown; - maxY = yCoord + shipUp; - this.shipSize = 0; - + int sizeFrontBack = shipFront + shipBack; + int sizeRightLeft = shipRight + shipLeft; + int sizeUpDown = shipUp + shipDown; + switch (this.direction) { case 0: case 180: - this.shipSize = this.shipBack + this.shipFront; + this.shipSize = sizeFrontBack; break; case 90: case 270: - this.shipSize = this.shipLeft + shipRight; + this.shipSize = sizeRightLeft; break; case -1: case -2: - this.shipSize = this.shipDown + this.shipUp; + this.shipSize = sizeUpDown; break; - } - + } // Ship size is too big - if (this.shipSize + 1 > WarpDriveConfig.i.WC_MAX_SHIP_SIDE) + if (sizeFrontBack > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || sizeRightLeft > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || sizeUpDown > WarpDriveConfig.i.WC_MAX_SHIP_SIDE) { messageToAllPlayersOnShip("Ship is too long. Cannot jump."); this.controller.setJumpFlag(false); From c9d87b2b49347b82be4403fb87e9912479a49349 Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Mon, 14 Jul 2014 20:22:25 +0400 Subject: [PATCH 40/56] oops --- src/cr0s/WarpDrive/TileEntityReactor.java | 63 +++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/cr0s/WarpDrive/TileEntityReactor.java b/src/cr0s/WarpDrive/TileEntityReactor.java index 6b29554f..1b31bac8 100644 --- a/src/cr0s/WarpDrive/TileEntityReactor.java +++ b/src/cr0s/WarpDrive/TileEntityReactor.java @@ -391,6 +391,69 @@ System.out.println("ZLO7"); public boolean calculateSpatialShipParameters() { + int x1 = 0, x2 = 0, z1 = 0, z2 = 0; + + if (Math.abs(dx) > 0) + { + if (dx == 1) + { + x1 = xCoord - shipBack; + x2 = xCoord + shipFront; + z1 = zCoord - shipLeft; + z2 = zCoord + shipRight; + } + else + { + x1 = xCoord - shipFront; + x2 = xCoord + shipBack; + z1 = zCoord - shipRight; + z2 = zCoord + shipLeft; + } + } + else if (Math.abs(dz) > 0) + { + if (dz == 1) + { + z1 = zCoord - shipBack; + z2 = zCoord + shipFront; + x1 = xCoord - shipRight; + x2 = xCoord + shipLeft; + } + else + { + z1 = zCoord - shipFront; + z2 = zCoord + shipBack; + x1 = xCoord - shipLeft; + x2 = xCoord + shipRight; + } + } + + if (x1 < x2) + { + minX = x1; + maxX = x2; + } + else + { + minX = x2; + maxX = x1; + } + + if (z1 < z2) + { + minZ = z1; + maxZ = z2; + } + else + { + minZ = z2; + maxZ = z1; + } + + minY = yCoord - shipDown; + maxY = yCoord + shipUp; + this.shipSize = 0; + int sizeFrontBack = shipFront + shipBack; int sizeRightLeft = shipRight + shipLeft; int sizeUpDown = shipUp + shipDown; From fc85c3f79a522c1516ea52873b61b6542b753b0d Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Wed, 16 Jul 2014 16:40:34 +0400 Subject: [PATCH 41/56] dimensions check --- src/cr0s/WarpDrive/TileEntityProtocol.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityProtocol.java b/src/cr0s/WarpDrive/TileEntityProtocol.java index 437789f9..1d0396c9 100644 --- a/src/cr0s/WarpDrive/TileEntityProtocol.java +++ b/src/cr0s/WarpDrive/TileEntityProtocol.java @@ -479,7 +479,13 @@ public class TileEntityProtocol extends TileEntity implements IPeripheral case 0: // dim_getp () return new Integer[] { getFront(), getRight(), getUp() }; case 1: // dim_setp (front, right, up) - if (arguments.length != 3 || (((Double)arguments[0]).intValue() < 0 || ((Double)arguments[1]).intValue() < 0 || ((Double)arguments[2]).intValue() < 0)) + if ( arguments.length != 3 || + ( ( (Double)arguments[0] ).intValue() < 0 || + ( (Double)arguments[1] ).intValue() < 0 || + ( (Double)arguments[2] ).intValue() < 0 || + ( (Double)arguments[1] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || + ( (Double)arguments[2] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || + ( (Double)arguments[3] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE ) ) { return new Integer[] { -1 }; } @@ -494,7 +500,13 @@ public class TileEntityProtocol extends TileEntity implements IPeripheral case 2: // dim_getn () return new Integer[] { getBack(), getLeft(), getDown() }; case 3: // dim_setn (back, left, down) - if (arguments.length != 3 || (((Double)arguments[0]).intValue() < 0 || ((Double)arguments[1]).intValue() < 0 || ((Double)arguments[2]).intValue() < 0)) + if ( arguments.length != 3 || + ( ( (Double)arguments[0] ).intValue() < 0 || + ( (Double)arguments[1] ).intValue() < 0 || + ( (Double)arguments[2] ).intValue() < 0 || + ( (Double)arguments[1] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || + ( (Double)arguments[2] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || + ( (Double)arguments[3] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE ) ) { return new Integer[] { -1 }; } From 18924e01786a51271be47354798ba53faac03171 Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Wed, 16 Jul 2014 16:43:21 +0400 Subject: [PATCH 42/56] 200 meter ships --- src/cr0s/WarpDrive/WarpDriveConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index cf62d56c..30330acb 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -42,7 +42,7 @@ public class WarpDriveConfig public int WC_MAX_JUMP_DISTANCE = 128; // Maximum jump length value public int WC_MAX_SHIP_VOLUME_ON_SURFACE = 15000; // Maximum ship volume to jump on earth public int WC_MIN_SHIP_VOLUME_FOR_HYPERSPACE = 500; // Minimum ship volume value for hyperspace travel - public int WC_MAX_SHIP_SIDE = 127; + public int WC_MAX_SHIP_SIDE = 199; //miaximum ship length - 1 public int WC_COOLDOWN_INTERVAL_SECONDS = 4; public int WC_CORES_REGISTRY_UPDATE_INTERVAL_SECONDS = 10; public int WC_ISOLATION_UPDATE_INTARVAL_SECONDS = 10; From 3aae3d3096433e5f5999c8467fe1d1e947c1466e Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Wed, 16 Jul 2014 17:11:02 +0400 Subject: [PATCH 43/56] miner fix: glowstone --- src/cr0s/WarpDrive/WarpDriveConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 30330acb..cf7d3eee 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -268,6 +268,7 @@ public class WarpDriveConfig MinerOres.add(Block.web.blockID); MinerOres.add(Block.fence.blockID); MinerOres.add(Block.torchWood.blockID); + MinerOres.add(Block.glowStone.blockID); // Ignore WarpDrive blocks (which potentially will be duplicated by cheaters using ship scan/deploy) scannerIgnoreBlocks.add(coreID); From 8975092b24438bcf873b9b539d3aa426f561c24d Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Thu, 17 Jul 2014 15:46:58 +0400 Subject: [PATCH 44/56] ShipScanner fix Changed CC methods, moved block ID check from scanning to deployment --- src/cr0s/WarpDrive/TileEntityShipScanner.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityShipScanner.java b/src/cr0s/WarpDrive/TileEntityShipScanner.java index 8a497a2d..b1767de1 100644 --- a/src/cr0s/WarpDrive/TileEntityShipScanner.java +++ b/src/cr0s/WarpDrive/TileEntityShipScanner.java @@ -58,17 +58,17 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, int warpCoreSearchTicks = 0; - // Config + // Config //TODO add to WarpDriveConfig private final String SCHEMATICS_DIR = "schematics"; private final int EU_PER_BLOCK_SCAN = 100; // eU per block of ship volume (including air) private final int EU_PER_BLOCK_DEPLOY = 5000; private final int BLOCK_TO_DEPLOY_PER_TICK = 1000; private final int ALLOWED_DEPLOY_RADIUS = 50; // blocks - private String[] methodsArray = { "scanShip", // 0 - "getSchematicFileName", // 1 - "getEnergyLevel", // 2 - "deployShipFromSchematic" // 3 deployShipFromSchematic(file, offsetX, offsetY, offsetZ) + private String[] methodsArray = { "scan", // 0 + "fileName", // 1 + "energy", // 2 + "deploy" // 3 deploy(file, offsetX, offsetY, offsetZ) }; private String schematicFileName; @@ -187,7 +187,10 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, // Deploy single block JumpBlock block = blocksToDeploy[currentDeployIndex]; - if (block!= null && worldObj.isAirBlock(newX + block.x, newY + block.y, newZ + block.z)) + if (block != null && + block.blockID != Block.bedrock.blockID && + !WarpDriveConfig.i.scannerIgnoreBlocks.contains(block.blockID) && + worldObj.isAirBlock(newX + block.x, newY + block.y, newZ + block.z)) { moveBlockSimple(block); @@ -356,8 +359,8 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, for (int z = 0; z < length; z++) { int blockID = worldObj.getBlockId(core.minX + x, core.minY + y, core.minZ + z); - // Do not scan air, bedrock and specified forbidden blocks (like ore or Warp-Cores) - if (worldObj.isAirBlock(core.minX + x, core.minY + y, core.minZ + z) || blockID == Block.bedrock.blockID || WarpDriveConfig.i.scannerIgnoreBlocks.contains(blockID)) + // Do not scan air and bedrock + if ( worldObj.isAirBlock(core.minX + x, core.minY + y, core.minZ + z) || blockID == Block.bedrock.blockID ) blockID = 0; int blockMetadata = (byte) worldObj.getBlockMetadata(core.minX + x, core.minY + y, core.minZ + z); @@ -799,7 +802,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, // Own implementation of setting blocks without light recalculation in optimization purposes public boolean mySetBlock(World w, int x, int y, int z, int blockId, int blockMeta, int par6) { - if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) + if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) //FIXME magic numbers { if (y < 0) { From 0592aa20786d2f4f08cd9c9d57fc66015756dbd3 Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Thu, 17 Jul 2014 16:24:48 +0400 Subject: [PATCH 45/56] Update WarpDriveConfig.java --- src/cr0s/WarpDrive/WarpDriveConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 1567855b..db54aa79 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -23,7 +23,7 @@ public class WarpDriveConfig public boolean isGregLoaded = false, isAELoaded = false, isAEExtraLoaded = false, isAdvSolPanelLoaded = false, isASLoaded = false, isICBMLoaded = false, isMFFSLoaded = false, isGraviSuiteLoaded = false; // public int[] IC2_Air; - public int CC_Computer = 0, CC_peripheral = 0, CCT_Turtle = 0, CCT_Upgraded = 0, CCT_Advanced = 0, GT_Ores = 0, GT_Granite = 0, GT_Machine = 0, ASP = 0, AS_Turbine = 0, ICBM_Machine = 0, ICBM_Missile = 0, MFFS_Field = 0; + public int CC_Computer = 0, CC_peripheral = 0, CCT_Turtle = 0, CCT_Upgraded = 0, CCT_Advanced = 0, GT_Ores = 0, GT_Granite = 0, GT_Machine = 0, ASP = 0, AS_Turbine = 0, ICBM_Machine = 0, ICBM_Missile = 0, ICBM_Explosive = 0, MFFS_Field = 0; public Set<Integer> SpaceHelmets, Jetpacks, MinerOres, scannerIgnoreBlocks; private Class<?> AEBlocks; private Class<?> AEMaterials; @@ -422,6 +422,7 @@ public class WarpDriveConfig z = Class.forName("icbm.explosion.ICBMExplosion"); ICBM_Machine = ((Block)z.getField("blockMachine").get(null)).blockID; ICBM_Missile = ((Item)z.getField("itemMissile").get(null)).itemID; + ICBM_Explosive = ((Item)z.getField("blockExplosive").get(null)).itemID; } catch (Exception e) { From bf5a4d087a2cb4052d9a5523538464e459dd11ca Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Thu, 17 Jul 2014 16:32:39 +0400 Subject: [PATCH 46/56] blacklisted ICBM explosives --- src/cr0s/WarpDrive/WarpDriveConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index db54aa79..40fec12d 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -278,6 +278,7 @@ public class WarpDriveConfig scannerIgnoreBlocks.add(Items.getItem("mfeUnit").itemID); scannerIgnoreBlocks.add(Items.getItem("cesuUnit").itemID); scannerIgnoreBlocks.add(Items.getItem("batBox").itemID); + scannerIgnoreBlocks.add(ICBM_Explosive); // Do not scan ores and valuables for (int[] t : CommonWorldGenOres) // each element of this set is pair [id, meta] From d51b8b23f0d01ed1bcbc803ab196ca6749d0d0a9 Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Thu, 17 Jul 2014 17:00:37 +0400 Subject: [PATCH 47/56] small fix --- src/cr0s/WarpDrive/WarpDriveConfig.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 40fec12d..3e275e9a 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -278,7 +278,10 @@ public class WarpDriveConfig scannerIgnoreBlocks.add(Items.getItem("mfeUnit").itemID); scannerIgnoreBlocks.add(Items.getItem("cesuUnit").itemID); scannerIgnoreBlocks.add(Items.getItem("batBox").itemID); - scannerIgnoreBlocks.add(ICBM_Explosive); + if ( ICBM_Explosive > 0) + { + scannerIgnoreBlocks.add(ICBM_Explosive); + } // Do not scan ores and valuables for (int[] t : CommonWorldGenOres) // each element of this set is pair [id, meta] From 013d85453eff89f2efacf6f7955d1b575d28cce4 Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Sun, 20 Jul 2014 16:09:23 +0400 Subject: [PATCH 48/56] deployer fix Duplicated CC computers and turtles can make ComputerCraft unusable until the server restarts. --- src/cr0s/WarpDrive/WarpDriveConfig.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 3e275e9a..4f9156c6 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -279,11 +279,17 @@ public class WarpDriveConfig scannerIgnoreBlocks.add(Items.getItem("cesuUnit").itemID); scannerIgnoreBlocks.add(Items.getItem("batBox").itemID); if ( ICBM_Explosive > 0) - { scannerIgnoreBlocks.add(ICBM_Explosive); - } + if ( CC_Computer > 0) + scannerIgnoreBlocks.add(CC_Computer); + if ( CCT_Turtle > 0) + scannerIgnoreBlocks.add(CCT_Turtle); + if ( CCT_Upgraded > 0) + scannerIgnoreBlocks.add(CCT_Upgraded); + if ( CCT_Advanced > 0) + scannerIgnoreBlocks.add(CCT_Advanced); - // Do not scan ores and valuables + // Do not deploy ores and valuables for (int[] t : CommonWorldGenOres) // each element of this set is pair [id, meta] scannerIgnoreBlocks.add(t[0]); // we adding ID only From 44b5f242dc98d0d799105c19264f5dfb20757167 Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Sun, 20 Jul 2014 21:20:14 +0400 Subject: [PATCH 49/56] deployer fix --- src/cr0s/WarpDrive/WarpDriveConfig.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 4f9156c6..3d80390d 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -278,16 +278,6 @@ public class WarpDriveConfig scannerIgnoreBlocks.add(Items.getItem("mfeUnit").itemID); scannerIgnoreBlocks.add(Items.getItem("cesuUnit").itemID); scannerIgnoreBlocks.add(Items.getItem("batBox").itemID); - if ( ICBM_Explosive > 0) - scannerIgnoreBlocks.add(ICBM_Explosive); - if ( CC_Computer > 0) - scannerIgnoreBlocks.add(CC_Computer); - if ( CCT_Turtle > 0) - scannerIgnoreBlocks.add(CCT_Turtle); - if ( CCT_Upgraded > 0) - scannerIgnoreBlocks.add(CCT_Upgraded); - if ( CCT_Advanced > 0) - scannerIgnoreBlocks.add(CCT_Advanced); // Do not deploy ores and valuables for (int[] t : CommonWorldGenOres) // each element of this set is pair [id, meta] @@ -324,6 +314,10 @@ public class WarpDriveConfig CCT_Turtle = z.getField("turtleBlockID").getInt(null); CCT_Upgraded = z.getField("turtleUpgradedBlockID").getInt(null); CCT_Advanced = z.getField("turtleAdvancedBlockID").getInt(null); + scannerIgnoreBlocks.add(CC_Computer); + scannerIgnoreBlocks.add(CCT_Turtle); + scannerIgnoreBlocks.add(CCT_Upgraded); + scannerIgnoreBlocks.add(CCT_Advanced); } catch (Exception e) { @@ -433,6 +427,7 @@ public class WarpDriveConfig ICBM_Machine = ((Block)z.getField("blockMachine").get(null)).blockID; ICBM_Missile = ((Item)z.getField("itemMissile").get(null)).itemID; ICBM_Explosive = ((Item)z.getField("blockExplosive").get(null)).itemID; + scannerIgnoreBlocks.add(ICBM_Explosive); } catch (Exception e) { From 65cd2bbf2b157e9b8d49b5d57101b1ab54b538b9 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Sun, 20 Jul 2014 22:43:54 +0400 Subject: [PATCH 50/56] Mudilou1 --- src/cr0s/WarpDrive/WarpDriveConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index 3d80390d..ac8813c4 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -54,6 +54,7 @@ public class WarpDriveConfig public int PB_MAX_ENERGY_VALUE = 100000; // Mining Laser + public int ML_MAX_BOOSTERS_NUMBER = 1; public int ML_SCAN_DELAY = 20 * 5; public int ML_MINE_DELAY = 10; public int ML_EU_PER_LAYER_SPACE = 500; From c135e4669135442c65226b6d3d4f4ebdb05fc223 Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Sun, 20 Jul 2014 22:47:08 +0400 Subject: [PATCH 51/56] Mudilou2 --- src/cr0s/WarpDrive/TileEntityReactor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cr0s/WarpDrive/TileEntityReactor.java b/src/cr0s/WarpDrive/TileEntityReactor.java index 1b31bac8..24143f5c 100644 --- a/src/cr0s/WarpDrive/TileEntityReactor.java +++ b/src/cr0s/WarpDrive/TileEntityReactor.java @@ -67,6 +67,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink private final byte MODE_GATE_JUMP = 6; // Jump via jumpgate int cooldownTime = 0; + public int randomCooldownAddition = 0; private int registryUpdateTicks = 0; public String coreFrequency = "default"; @@ -187,7 +188,7 @@ public class TileEntityReactor extends TileEntity implements IEnergySink } // Awaiting cooldown time - if (/*currentMode != MODE_BASIC_JUMP && */cooldownTime++ < ((WarpDriveConfig.i.WC_COOLDOWN_INTERVAL_SECONDS) * 20) ) + if (/*currentMode != MODE_BASIC_JUMP && */cooldownTime++ < ((WarpDriveConfig.i.WC_COOLDOWN_INTERVAL_SECONDS) * 20) + randomCooldownAddition) { return; } From 21756cb26e6d0fbfb24722fa6578aab93965178d Mon Sep 17 00:00:00 2001 From: ZLOFENIX <admin@zlofenix.org> Date: Sun, 20 Jul 2014 23:02:20 +0400 Subject: [PATCH 52/56] Mudaque --- .../TileEntityCloakingDeviceCore.java | 4 --- src/cr0s/WarpDrive/TileEntityLaser.java | 21 ------------ src/cr0s/WarpDrive/TileEntityMiningLaser.java | 5 --- src/cr0s/WarpDrive/TileEntityProtocol.java | 15 +++------ src/cr0s/WarpDrive/TileEntityRadar.java | 2 -- src/cr0s/WarpDrive/TileEntityReactor.java | 33 ------------------- src/cr0s/WarpDrive/TileEntityShipScanner.java | 23 ------------- 7 files changed, 4 insertions(+), 99 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityCloakingDeviceCore.java b/src/cr0s/WarpDrive/TileEntityCloakingDeviceCore.java index d2cec195..cc4d8396 100644 --- a/src/cr0s/WarpDrive/TileEntityCloakingDeviceCore.java +++ b/src/cr0s/WarpDrive/TileEntityCloakingDeviceCore.java @@ -79,7 +79,6 @@ public class TileEntityCloakingDeviceCore extends TileEntity implements IEnergyS } if (--this.updateTicks <= 0) { - //System.out.println("[CloakDev] Updating cloaking state..."); this.updateTicks = ((this.tier == 1) ? 20 : (tier == 2) ? 10 : 20) * WarpDriveConfig.i.CD_FIELD_REFRESH_INTERVAL_SECONDS; // resetting timer if (validateAssembly() && isEnabled) { @@ -101,13 +100,11 @@ public class TileEntityCloakingDeviceCore extends TileEntity implements IEnergyS area.sendCloakPacketToPlayersEx(false); // recloak field } } else { - System.out.println("[CloakDev] Low power, cloak field collapsing..."); currentEnergyValue = 0; setCoilsState(false); disableCloakingField(); } } else if (!validateAssembly() && isEnabled) { - System.out.println("[CloakDev] Device lost coils, field collapsing"); currentEnergyValue = 0; setCoilsState(false); disableCloakingField(); @@ -225,7 +222,6 @@ public class TileEntityCloakingDeviceCore extends TileEntity implements IEnergyS blocksCount++; int energyToConsume = blocksCount * ((this.tier == 1) ? WarpDriveConfig.i.CD_ENERGY_PER_BLOCK_TIER1 : WarpDriveConfig.i.CD_ENERGY_PER_BLOCK_TIER2); - //System.out.println("[CloakDev] Consuming " + energyToConsume + " eU for " + blocksCount + " blocks"); this.currentEnergyValue -= energyToConsume; } diff --git a/src/cr0s/WarpDrive/TileEntityLaser.java b/src/cr0s/WarpDrive/TileEntityLaser.java index 2add2614..a8fb2d68 100644 --- a/src/cr0s/WarpDrive/TileEntityLaser.java +++ b/src/cr0s/WarpDrive/TileEntityLaser.java @@ -97,14 +97,7 @@ public class TileEntityLaser extends TileEntity implements IPeripheral public void addBeamEnergy(int amount) { if (isEmitting) - { energyFromOtherBeams += amount; - System.out.println("[LE] Added energy: " + amount); - } - else - { - System.out.println("[LE] Ignored energy: " + amount); - } } private int collectEnergyFromBoosters() @@ -139,7 +132,6 @@ public class TileEntityLaser extends TileEntity implements IPeripheral { // Beam power calculations int beamLengthBlocks = energy / WarpDriveConfig.i.LE_BEAM_LENGTH_PER_ENERGY_DIVIDER; - System.out.println("Energy: " + energy + " | beamLengthBlocks: " + beamLengthBlocks); if (energy == 0 || beamLengthBlocks < 1 || frequency > 65000 || frequency <= 0) { @@ -147,7 +139,6 @@ public class TileEntityLaser extends TileEntity implements IPeripheral } Vector3 beamVector = new Vector3(this).add(0.5); - System.out.println("beamVector: " + beamVector); float yawz = MathHelper.cos(-yaw * 0.017453292F - (float) Math.PI); float yawx = MathHelper.sin(-yaw * 0.017453292F - (float) Math.PI); float pitchhorizontal = -MathHelper.cos(-pitch * 0.017453292F); @@ -157,9 +148,6 @@ public class TileEntityLaser extends TileEntity implements IPeripheral Vector3 lookVector = new Vector3((double) directionx, (double) pitchvertical, (double) directionz); Vector3.translate(beamVector, lookVector); Vector3 reachPoint = beamVector.clone().translate(beamVector.clone(), beamVector.clone().scale(lookVector.clone(), beamLengthBlocks)); - System.out.println("Look vector: " + lookVector); - System.out.println("reachPoint: " + reachPoint); - System.out.println("translatedBeamVector: " + beamVector); Vector3 endPoint = reachPoint.clone(); playSoundCorrespondsEnergy(energy); @@ -185,15 +173,6 @@ public class TileEntityLaser extends TileEntity implements IPeripheral // FIXME entity ray-tracing MovingObjectPosition entityHit = raytraceEntities(beamVector.clone(), lookVector.clone(), true, beamLengthBlocks); - if (entityHit == null) - { - System.out.println("Entity hit is null."); - } - else - { - System.out.println("Entity hit: " + entityHit); - } - if (entityHit != null && entityHit.entityHit instanceof EntityLivingBase) { EntityLivingBase e = (EntityLivingBase)entityHit.entityHit; diff --git a/src/cr0s/WarpDrive/TileEntityMiningLaser.java b/src/cr0s/WarpDrive/TileEntityMiningLaser.java index 6f44e201..e62b2dfb 100644 --- a/src/cr0s/WarpDrive/TileEntityMiningLaser.java +++ b/src/cr0s/WarpDrive/TileEntityMiningLaser.java @@ -338,7 +338,6 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG private void scanLayer() { - //System.out.println("Scanning layer"); valuablesInLayer.clear(); int xmax, zmax, x1, x2, z1, z2; int xmin, zmin; @@ -371,9 +370,6 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG zmax = z1; } - //System.out.println("Layer: xmax: " + xmax + ", xmin: " + xmin); - //System.out.println("Layer: zmax: " + zmax + ", zmin: " + zmin); - // Search for valuable blocks for (int x = xmin; x <= xmax; x++) for (int z = zmin; z <= zmax; z++) @@ -391,7 +387,6 @@ public class TileEntityMiningLaser extends TileEntity implements IPeripheral, IG } valuableIndex = 0; - //System.out.println("[ML] Found " + valuablesInLayer.size() + " valuables"); } private boolean collectEnergyPacketFromBooster(int packet, boolean test) diff --git a/src/cr0s/WarpDrive/TileEntityProtocol.java b/src/cr0s/WarpDrive/TileEntityProtocol.java index 1d0396c9..cb4cf021 100644 --- a/src/cr0s/WarpDrive/TileEntityProtocol.java +++ b/src/cr0s/WarpDrive/TileEntityProtocol.java @@ -84,13 +84,11 @@ public class TileEntityProtocol extends TileEntity implements IPeripheral private void setJumpDistance(int distance) { - System.out.println("Setting jump distance: " + distance); this.distance = distance; } private void setMode(int mode) { - // System.out.println("Setting mode: " + mode); this.mode = mode; } @@ -109,7 +107,6 @@ public class TileEntityProtocol extends TileEntity implements IPeripheral dir = 270; } - System.out.println("Setting direction: " + dir); this.direction = dir; } @@ -433,7 +430,6 @@ public class TileEntityProtocol extends TileEntity implements IPeripheral */ public void setBeaconFrequency(String beaconFrequency) { - //System.out.println("Setting beacon freqency: " + beaconFrequency); this.beaconFrequency = beaconFrequency; } @@ -473,7 +469,6 @@ public class TileEntityProtocol extends TileEntity implements IPeripheral @Override public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception { - //System.out.println("[ProtoBlock] Method " + method + " " + methodsArray[method] + " called!"); switch (method) { case 0: // dim_getp () @@ -483,14 +478,13 @@ public class TileEntityProtocol extends TileEntity implements IPeripheral ( ( (Double)arguments[0] ).intValue() < 0 || ( (Double)arguments[1] ).intValue() < 0 || ( (Double)arguments[2] ).intValue() < 0 || + ( (Double)arguments[0] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || ( (Double)arguments[1] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || - ( (Double)arguments[2] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || - ( (Double)arguments[3] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE ) ) + ( (Double)arguments[2] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE ) ) { return new Integer[] { -1 }; } - System.out.println("Setting positive gabarits: f: " + ((Double)arguments[0]).intValue() + " r: " + ((Double)arguments[1]).intValue() + " u: " + ((Double)arguments[2]).intValue()); setFront(((Double)arguments[0]).intValue()); setRight(((Double)arguments[1]).intValue()); setUp(((Double)arguments[2]).intValue()); @@ -504,14 +498,13 @@ public class TileEntityProtocol extends TileEntity implements IPeripheral ( ( (Double)arguments[0] ).intValue() < 0 || ( (Double)arguments[1] ).intValue() < 0 || ( (Double)arguments[2] ).intValue() < 0 || + ( (Double)arguments[0] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || ( (Double)arguments[1] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || - ( (Double)arguments[2] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE || - ( (Double)arguments[3] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE ) ) + ( (Double)arguments[2] ).intValue() > WarpDriveConfig.i.WC_MAX_SHIP_SIDE ) ) { return new Integer[] { -1 }; } - System.out.println("Setting negative gabarits: b: " + ((Double)arguments[0]).intValue() + " l: " + ((Double)arguments[1]).intValue() + " d: " + ((Double)arguments[2]).intValue()); setBack(((Double)arguments[0]).intValue()); setLeft(((Double)arguments[1]).intValue()); setDown(((Double)arguments[2]).intValue()); diff --git a/src/cr0s/WarpDrive/TileEntityRadar.java b/src/cr0s/WarpDrive/TileEntityRadar.java index c4d5ca1d..2a6d6630 100644 --- a/src/cr0s/WarpDrive/TileEntityRadar.java +++ b/src/cr0s/WarpDrive/TileEntityRadar.java @@ -69,7 +69,6 @@ public class TileEntityRadar extends TileEntity implements IPeripheral, IEnergyS { if (cooldownTime++ > (20 * ((scanRadius / 1000) + 1))) { - //System.out.println("Scanning..."); WarpDrive.instance.registry.removeDeadCores(); results = WarpDrive.instance.registry.searchWarpCoresInRadius(xCoord, yCoord, zCoord, scanRadius); worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1, 1 + 2); @@ -138,7 +137,6 @@ public class TileEntityRadar extends TileEntity implements IPeripheral, IEnergyS else { results = null; - System.out.println("Radius: " + radius + " | Enough energy: " + isEnergyEnoughForScanRadiusW(radius)); return new Boolean[] { false }; } } diff --git a/src/cr0s/WarpDrive/TileEntityReactor.java b/src/cr0s/WarpDrive/TileEntityReactor.java index 24143f5c..f97f9c83 100644 --- a/src/cr0s/WarpDrive/TileEntityReactor.java +++ b/src/cr0s/WarpDrive/TileEntityReactor.java @@ -201,7 +201,6 @@ public class TileEntityReactor extends TileEntity implements IEnergySink return; } -System.out.println("ZLO5"); if (WarpDrive.instance.registry.isWarpCoreIntersectsWithOthers(this)) { this.controller.setJumpFlag(false); @@ -209,7 +208,6 @@ System.out.println("ZLO5"); return; } -System.out.println("ZLO6"); if (WarpDrive.instance.cloaks.isInCloak(worldObj.provider.dimensionId, xCoord, yCoord, zCoord, false)) { this.controller.setJumpFlag(false); @@ -217,8 +215,6 @@ System.out.println("ZLO6"); return; } -System.out.println("ZLO7"); - System.out.println("[W-C] Jumping!"); doJump(); controller.setJumpFlag(false); } @@ -243,7 +239,6 @@ System.out.println("ZLO7"); continue; } - System.out.println(msg); ((EntityPlayer)o).addChatMessage("[WarpCore] " + msg); } } @@ -499,7 +494,6 @@ System.out.println("ZLO7"); { if (currentEnergyValue - calculateRequiredEnergy(shipVolume, distance) < 0) { - System.out.println("[WP-TE] Insufficient energy to jump"); this.controller.setJumpFlag(false); return; } @@ -539,7 +533,6 @@ System.out.println("ZLO7"); { // Consume all energy currentEnergyValue -= calculateRequiredEnergy(shipVolume, distance); - System.out.println("[TE-WC] Moving ship to a beacon (" + beaconX + "; " + yCoord + "; " + beaconZ + ")"); EntityJump jump = new EntityJump(worldObj, xCoord, yCoord, zCoord, 1, 0, dx, dz, this); jump.maxX = maxX; jump.minX = minX; @@ -565,16 +558,11 @@ System.out.println("ZLO7"); worldObj.spawnEntityInWorld(jump); coreState = ""; } - else - { - System.out.println("[TE-WC] Beacon not found."); - } } private boolean isShipInJumpgate(JumpGate jg) { AxisAlignedBB aabb = jg.getGateAABB(); - System.out.println("Gate AABB: " + aabb); int numBlocks = 0; if (aabb.isVecInside(worldObj.getWorldVec3Pool().getVecFromPool(maxX - minX, maxY - minY, maxZ - minZ))) @@ -601,12 +589,9 @@ System.out.println("ZLO7"); if (numBlocks == 0) { - System.out.println("[GATE] Is 0 blocks inside gate."); return false; } - System.out.println("[GATE] Ship volume: " + shipVolume + ", blocks in gate: " + numBlocks + ". Percentage: " + ((shipVolume / numBlocks) * 100)); - // At least 80% of ship must be inside jumpgate if (shipVolume / numBlocks > 0.8F) { @@ -657,7 +642,6 @@ System.out.println("ZLO7"); { if (currentEnergyValue - calculateRequiredEnergy(shipVolume, distance) < 0) { - System.out.println("[WP-TE] Insufficient energy to jump"); this.controller.setJumpFlag(false); return; } @@ -717,12 +701,10 @@ System.out.println("ZLO7"); return; } - System.out.println("[GATE] Place found over " + (10 - numTries) + " tries."); } // Consume energy currentEnergyValue -= calculateRequiredEnergy(shipVolume, distance); - System.out.println("[TE-WC] Moving ship to a place around gate '" + jg.name + "' (" + destX + "; " + destY + "; " + destZ + ")"); EntityJump jump = new EntityJump(worldObj, xCoord, yCoord, zCoord, 1, 0, dx, dz, this); jump.maxX = maxX; jump.minX = minX; @@ -764,14 +746,12 @@ System.out.println("ZLO7"); return; } - System.out.println("[TE-WC] Performing gate jump..."); doGateJump(); return; } if (currentMode == this.MODE_BEACON_JUMP) { - System.out.println("[TE-WC] Performing beacon jump..."); doBeaconJump(); return; } @@ -799,23 +779,14 @@ System.out.println("ZLO7"); if (currentMode == this.MODE_BASIC_JUMP || currentMode == this.MODE_LONG_JUMP || currentMode == MODE_HYPERSPACE) { - System.out.println("[WP-TE] Energy: " + currentEnergyValue + " eU"); - System.out.println("[WP-TE] Need to jump: " + calculateRequiredEnergy(shipVolume, distance) + " eU"); - if (this.currentEnergyValue - calculateRequiredEnergy(shipVolume, distance) < 0) { - System.out.println("[WP-TE] Insufficient energy to jump"); messageToAllPlayersOnShip("Insufficient energy to jump!"); this.controller.setJumpFlag(false); return; } this.currentEnergyValue -= calculateRequiredEnergy(shipVolume, distance); - System.out.println((new StringBuilder()).append("Jump params: X ").append(minX).append(" -> ").append(maxX).append(" blocks").toString()); - System.out.println((new StringBuilder()).append("Jump params: Y ").append(minY).append(" -> ").append(maxY).append(" blocks").toString()); - System.out.println((new StringBuilder()).append("Jump params: Z ").append(minZ).append(" -> ").append(maxZ).append(" blocks").toString()); - - //System.out.println("[WC-TE] Distance: " + distance + "; shipSize: " + shipSize); if (this.currentMode == this.MODE_BASIC_JUMP) { distance += shipSize; @@ -829,7 +800,6 @@ System.out.println("ZLO7"); } } - System.out.println((new StringBuilder()).append("[JUMP] Totally moving ").append((new StringBuilder()).append(shipVolume).append(" blocks to length ").append(distance).append(" blocks, direction: ").append(direction).toString()).toString()); EntityJump jump = new EntityJump(worldObj, xCoord, yCoord, zCoord, distance, direction, dx, dz, this); jump.maxX = maxX; jump.minX = minX; @@ -850,7 +820,6 @@ System.out.println("ZLO7"); { jump.toHyperSpace = (worldObj.provider.dimensionId == WarpDrive.instance.spaceDimID); jump.fromHyperSpace = (worldObj.provider.dimensionId == WarpDrive.instance.hyperSpaceDimID); - System.out.println("[JUMP] From HS: " + jump.fromHyperSpace + " | To HS: " + jump.fromHyperSpace); } jump.xCoord = xCoord; @@ -941,7 +910,6 @@ System.out.println("ZLO7"); if (checkPlayerInventory(chest, player)) { - System.out.println("[P] Summoning " + player.username); summonPlayer(player, xCoord, yCoord + 2, zCoord); } } @@ -977,7 +945,6 @@ System.out.println("ZLO7"); if (keyLength < MIN_KEY_LENGTH) { - System.out.println("[ChestCode] Key is too short: " + keyLength + " < " + MIN_KEY_LENGTH); return false; } diff --git a/src/cr0s/WarpDrive/TileEntityShipScanner.java b/src/cr0s/WarpDrive/TileEntityShipScanner.java index b1767de1..428ba25b 100644 --- a/src/cr0s/WarpDrive/TileEntityShipScanner.java +++ b/src/cr0s/WarpDrive/TileEntityShipScanner.java @@ -167,7 +167,6 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, deployDelayTicks = 0; int blocks = Math.min(BLOCK_TO_DEPLOY_PER_TICK, blocksToDeployCount - currentDeployIndex); -// System.out.println("[ShipScanner] Deploying ship part: " + currentDeployIndex + "/" + blocksToDeployCount + " [remains: " + blocks + "]"); if (blocks == 0) { isDeploying = false; @@ -337,14 +336,12 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, schematic.setShort("Length", length); schematic.setShort("Height", height); -// System.out.println("[ShipScanner] Ship parameters: w: " + width + ", l: " + length + ", h:" + height); int size = width * length * height; // Consume energy currentEnergyValue = Math.abs(currentEnergyValue - size * EU_PER_BLOCK_SCAN); -// System.out.println("[ShipScanner] Size: " + size); byte localBlocks[] = new byte[size]; byte localMetadata[] = new byte[size]; @@ -419,7 +416,6 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, } private void writeNBTToFile(String fileName, NBTTagCompound nbttagcompound) { -// System.out.println("[ShipScanner] Filename: " + fileName); try { File file = new File(fileName); @@ -485,7 +481,6 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, NBTTagCompound schematic = readNBTFromFile(SCHEMATICS_DIR + "/" + fileName); if (schematic == null) { -// System.out.println("[ShipScanner] Schematic is null!"); return new Object[] { -1, "Unknow error. Schematic NBT is null" }; } @@ -507,11 +502,9 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, int size = width* height * length; -// System.out.println("[ShipScanner] Deploying ship: (size: " + size + ", h: " + height + ", w: " + width + ", l: " + length + ")"); // Check energy level if (!isEnoughEnergyForDeploy(size)) { -// System.out.println("[ShipScanner] Not enough energy! Need at least " + (Math.abs(size * EU_PER_BLOCK_DEPLOY - currentEnergyValue)) + " Eu"); return new Object[] { 1, "Not enough energy! Need at least " + (Math.abs(size * EU_PER_BLOCK_DEPLOY - currentEnergyValue)) + " Eu" }; } @@ -528,7 +521,6 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, } if (occupiedBlockCount > 0) { -// System.out.println("[ShipScanner] Deploying area occupied with " + occupiedBlockCount + " blocks. Can't deploy ship."); return new Object[] { 2, "Deploying area occupied with " + occupiedBlockCount + " blocks. Can't deploy ship." }; } @@ -545,11 +537,9 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, this.newY = targetY; this.newZ = targetZ; -// System.out.println("[ShipScanner] Target to deploy: (" + targetX + ", " + targetY + ", " + targetZ + ")"); // Read blocks and TileEntities from NBT to internal storage array -// System.out.println("[ShipScanner] Loading blocks..."); byte localBlocks[] = schematic.getByteArray("Blocks"); byte localMetadata[] = schematic.getByteArray("Data"); @@ -568,7 +558,6 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, } // Load Tile Entities -// System.out.println("[ShipScanner] Loading TileEntities..."); NBTTagCompound[] tileEntities = new NBTTagCompound[size]; NBTTagList tileEntitiesList = schematic.getTagList("TileEntities"); @@ -578,7 +567,6 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, int teY = teTag.getInteger("y"); int teZ = teTag.getInteger("z"); -// System.out.println("[ShipScanner] Loaded TE: " + teTag.getString("id")); tileEntities[teX + (teY * length + teZ) * width] = teTag; } @@ -598,22 +586,12 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, jb.x = x; jb.y = y; jb.z = z; -/* - if (jb.blockID != 0 && Block.blocksList[jb.blockID] != null) { - System.out.print("[ShipScanner] Saving block: " + Block.blocksList[jb.blockID].getUnlocalizedName() + ", TE: "); - if (tileEntities[x + (y * length + z) * width] == null) { - System.out.println("null!"); - } else - System.out.println(tileEntities[x + (y * length + z) * width].getString("id")); - } -*/ blocksToDeploy[x + (y * length + z) * width] = jb; } } } switchState(1); -// System.out.println("[ShipScanner] Ship deployed."); return new Object[] { 3, "Ship deployed." }; } @@ -679,7 +657,6 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, return new Object[] { 0, "Specified .schematic file not found!" }; else { -// System.out.println("[ShipScanner] Trying to deploy ship"); return deployShip(fileName, x, y, z); } } else From 7401f87b8b80302e71ea73898493a5bf5d63f8f1 Mon Sep 17 00:00:00 2001 From: drpepper240 <drpepper240@users.noreply.github.com> Date: Fri, 25 Jul 2014 21:34:29 +0400 Subject: [PATCH 53/56] scanning laser fix --- src/cr0s/WarpDrive/TileEntityLaser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cr0s/WarpDrive/TileEntityLaser.java b/src/cr0s/WarpDrive/TileEntityLaser.java index a8fb2d68..a94496d7 100644 --- a/src/cr0s/WarpDrive/TileEntityLaser.java +++ b/src/cr0s/WarpDrive/TileEntityLaser.java @@ -85,7 +85,7 @@ public class TileEntityLaser extends TileEntity implements IPeripheral } } - if (isEmitting && (frequency != 1420 && ++delayTicks > WarpDriveConfig.i.LE_EMIT_DELAY_TICKS) || ((frequency == 1420) && ++delayTicks > WarpDriveConfig.i.LE_EMIT_SCAN_DELAY_TICKS)) + if (isEmitting && ((frequency != 1420 && ++delayTicks > WarpDriveConfig.i.LE_EMIT_DELAY_TICKS) || ((frequency == 1420) && ++delayTicks > WarpDriveConfig.i.LE_EMIT_SCAN_DELAY_TICKS))) { delayTicks = 0; isEmitting = false; From e22dd05dacd7e6a4e751ad54e4ac3ca75436403b Mon Sep 17 00:00:00 2001 From: drPepper <skype:drpepper_mc> Date: Sat, 26 Jul 2014 16:25:29 +0400 Subject: [PATCH 54/56] scanning laser minor fix --- src/cr0s/WarpDrive/TileEntityLaser.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cr0s/WarpDrive/TileEntityLaser.java b/src/cr0s/WarpDrive/TileEntityLaser.java index a94496d7..e3fed5b1 100644 --- a/src/cr0s/WarpDrive/TileEntityLaser.java +++ b/src/cr0s/WarpDrive/TileEntityLaser.java @@ -160,7 +160,9 @@ public class TileEntityLaser extends TileEntity implements IPeripheral if (firstHit != null) { - sendLaserPacket(beamVector, new Vector3(firstHit), r, g, b, 50, energy, 200); + sendLaserPacket(beamVector, new Vector3(firstHit.hitVec), r, g, b, 50, energy, 200); + } else { + sendLaserPacket(beamVector, reachPoint, r, g, b, 50, energy, 200); } return; From 3c63085eefb6bc5405f3c412255c3131d83d38a8 Mon Sep 17 00:00:00 2001 From: drPepper <skype:drpepper_mc> Date: Sat, 26 Jul 2014 17:10:42 +0400 Subject: [PATCH 55/56] kostylee --- src/cr0s/WarpDrive/TileEntityLaser.java | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityLaser.java b/src/cr0s/WarpDrive/TileEntityLaser.java index e3fed5b1..f0973455 100644 --- a/src/cr0s/WarpDrive/TileEntityLaser.java +++ b/src/cr0s/WarpDrive/TileEntityLaser.java @@ -56,7 +56,13 @@ public class TileEntityLaser extends TileEntity implements IPeripheral public int delayTicks = 0; private int energyFromOtherBeams = 0; - private MovingObjectPosition firstHit; + private MovingObjectPosition firstHit = null; + private int hitX = 0; + private int hitY = 0; + private int hitZ = 0; + private int hitBlockId = 0; + private int hitBlockMeta = 0; + private float hitBlockResistance = 0; private int camUpdateTicks = 20; private int registryUpdateTicks = 20 * 10; @@ -65,7 +71,7 @@ public class TileEntityLaser extends TileEntity implements IPeripheral public void updateEntity() { // Frequency is not set - if (frequency <= 0) + if (frequency <= 0 || frequency > 65000) { return; } @@ -160,6 +166,12 @@ public class TileEntityLaser extends TileEntity implements IPeripheral if (firstHit != null) { + hitBlockId = worldObj.getBlockId(firstHit.blockX, firstHit.blockY, firstHit.blockZ); + hitBlockMeta = worldObj.getBlockMetadata(firstHit.blockX, firstHit.blockY, firstHit.blockZ); + hitBlockResistance = Block.blocksList[hitBlockId].blockResistance; + hitX = firstHit.blockX; + hitY = firstHit.blockY; + hitZ = firstHit.blockZ; sendLaserPacket(beamVector, new Vector3(firstHit.hitVec), r, g, b, 50, energy, 200); } else { sendLaserPacket(beamVector, reachPoint, r, g, b, 50, energy, 200); @@ -598,7 +610,7 @@ public class TileEntityLaser extends TileEntity implements IPeripheral { double dx = (Double)arguments[0]; double dy = (Double)arguments[1]; - double dz = (Double)arguments[2]; + double dz = -(Double)arguments[2]; //FIXME kostyl double targetX = xCoord + dx; double targetY = yCoord + dy; double targetZ = zCoord + dz; @@ -629,8 +641,7 @@ public class TileEntityLaser extends TileEntity implements IPeripheral int blockID = worldObj.getBlockId(firstHit.blockX, firstHit.blockY, firstHit.blockZ); int blockMeta = worldObj.getBlockMetadata(firstHit.blockX, firstHit.blockY, firstHit.blockZ); float blockResistance = Block.blocksList[blockID].blockResistance; - Object[] info = { firstHit.blockX, firstHit.blockY, firstHit.blockZ, blockID, blockMeta, (Float)blockResistance }; - firstHit = null; + Object[] info = { hitX, hitY, hitZ, hitBlockId, hitBlockMeta, (Float)hitBlockResistance }; return info; } else From b1e31a12182dcbddbdaa5f54b070f65ace98e3bb Mon Sep 17 00:00:00 2001 From: drPepper <skype:drpepper_mc> Date: Sat, 26 Jul 2014 18:55:58 +0400 Subject: [PATCH 56/56] nerfocircus --- src/cr0s/WarpDrive/TileEntityShipScanner.java | 4 ++-- src/cr0s/WarpDrive/WarpDriveConfig.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cr0s/WarpDrive/TileEntityShipScanner.java b/src/cr0s/WarpDrive/TileEntityShipScanner.java index 428ba25b..8a8096f0 100644 --- a/src/cr0s/WarpDrive/TileEntityShipScanner.java +++ b/src/cr0s/WarpDrive/TileEntityShipScanner.java @@ -473,7 +473,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, } private boolean isEnoughEnergyForDeploy(int size) { - return size * EU_PER_BLOCK_DEPLOY <= currentEnergyValue; + return MAX_ENERGY_VALUE <= currentEnergyValue; } // Returns result array for CC interface: [ code, "message" ] @@ -525,7 +525,7 @@ public class TileEntityShipScanner extends TileEntity implements IEnergySink, } // Consume energy - currentEnergyValue = Math.abs(currentEnergyValue - size * EU_PER_BLOCK_DEPLOY); + currentEnergyValue = 0; // Set deployment vars this.blocksToDeploy = new JumpBlock[size]; diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index ac8813c4..50f7d2fd 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -427,7 +427,7 @@ public class WarpDriveConfig z = Class.forName("icbm.explosion.ICBMExplosion"); ICBM_Machine = ((Block)z.getField("blockMachine").get(null)).blockID; ICBM_Missile = ((Item)z.getField("itemMissile").get(null)).itemID; - ICBM_Explosive = ((Item)z.getField("blockExplosive").get(null)).itemID; + ICBM_Explosive = ((Block)z.getField("blockExplosive").get(null)).blockID; scannerIgnoreBlocks.add(ICBM_Explosive); } catch (Exception e)