Added forcefield projector and upgrades (wip)

Implemented projector with fusion and various shapes/upgrades
Wip support for translation/rotation, dome, upgrades, camouflage,
damage effects
This commit is contained in:
LemADEC 2016-05-28 15:36:28 -04:00
parent a120fa3ab5
commit 45e0dcb8bf
21 changed files with 2260 additions and 69 deletions

View file

@ -5,6 +5,8 @@ import java.util.List;
import java.util.UUID;
import com.mojang.authlib.GameProfile;
import cr0s.warpdrive.block.forcefield.*;
import cr0s.warpdrive.item.*;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.command.ICommandSender;
@ -40,6 +42,7 @@ 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.registry.GameRegistry;
import cr0s.warpdrive.block.BlockAirGenerator;
import cr0s.warpdrive.block.BlockChunkLoader;
import cr0s.warpdrive.block.BlockLaser;
@ -110,14 +113,9 @@ import cr0s.warpdrive.data.StarMapRegistry;
import cr0s.warpdrive.event.ClientHandler;
import cr0s.warpdrive.event.LivingHandler;
import cr0s.warpdrive.event.WorldHandler;
import cr0s.warpdrive.item.ItemAirCanisterFull;
import cr0s.warpdrive.item.ItemComponent;
import cr0s.warpdrive.item.ItemHelmet;
import cr0s.warpdrive.item.ItemIC2reactorLaserFocus;
import cr0s.warpdrive.item.ItemUpgrade;
import cr0s.warpdrive.item.ItemTuningFork;
import cr0s.warpdrive.network.PacketHandler;
import cr0s.warpdrive.render.ClientCameraHandler;
import cr0s.warpdrive.render.RenderBlockForceField;
import cr0s.warpdrive.render.RenderBlockStandard;
import cr0s.warpdrive.render.RenderOverlayCamera;
import cr0s.warpdrive.world.BiomeSpace;
@ -165,6 +163,8 @@ public class WarpDrive implements LoadingCallback {
public static Block blockHighlyAdvancedMachine;
public static Block blockTransportBeacon;
public static Block blockChunkLoader;
public static Block blockForceField;
public static Block blockProjector;
public static BlockDecorative blockDecorative;
public static Block[] blockHulls_plain;
public static Block[] blockHulls_glass;
@ -175,6 +175,8 @@ public class WarpDrive implements LoadingCallback {
public static ItemComponent itemComponent;
public static ItemUpgrade itemUpgrade;
public static ItemTuningFork itemTuningRod;
public static ItemForceFieldShape itemForceFieldShape;
public static BlockForceFieldUpgrade blockForceFieldUpgrade;
public static final ArmorMaterial armorMaterial = EnumHelper.addArmorMaterial("WARP", 18, new int[] { 2, 6, 5, 2 }, 9);
public static ItemHelmet itemHelmet;
@ -188,8 +190,10 @@ public class WarpDrive implements LoadingCallback {
public static DamageWarm damageWarm;
public static BiomeGenBase spaceBiome;
public SpaceWorldGenerator spaceWorldGenerator;
public HyperSpaceWorldGenerator hyperSpaceWorldGenerator;
@SuppressWarnings("FieldCanBeLocal")
private SpaceWorldGenerator spaceWorldGenerator;
@SuppressWarnings("FieldCanBeLocal")
private HyperSpaceWorldGenerator hyperSpaceWorldGenerator;
public static Field fieldBlockHardness = null;
@ -206,7 +210,8 @@ public class WarpDrive implements LoadingCallback {
public static CloakManager cloaks;
public static CamerasRegistry cameras;
public static WarpDrivePeripheralHandler peripheralHandler = null;
@SuppressWarnings("FieldCanBeLocal")
private static WarpDrivePeripheralHandler peripheralHandler = null;
public static Logger logger;
@ -223,6 +228,9 @@ public class WarpDrive implements LoadingCallback {
RenderBlockStandard.renderId = RenderingRegistry.getNextAvailableRenderId();
RenderingRegistry.registerBlockHandler(RenderBlockStandard.instance);
RenderBlockForceField.renderId = RenderingRegistry.getNextAvailableRenderId();
RenderingRegistry.registerBlockHandler(RenderBlockForceField.instance);
}
}
@ -368,6 +376,7 @@ public class WarpDrive implements LoadingCallback {
GameRegistry.registerBlock(blockIC2reactorLaserMonitor, "blockIC2reactorLaserMonitor");
GameRegistry.registerTileEntity(TileEntityIC2reactorLaserMonitor.class, MODID + ":blockIC2reactorLaserMonitor");
}
// TRANSPORT BEACON
blockTransportBeacon = new BlockTransportBeacon();
@ -391,6 +400,29 @@ public class WarpDrive implements LoadingCallback {
GameRegistry.registerBlock(blockChunkLoader, "blockChunkLoader");
GameRegistry.registerTileEntity(TileEntityChunkLoader.class, MODID + ":blockChunkLoader");
for(byte tier = 1; tier <= 3; tier++) {
// FORCE FIELD
blockForceField = new BlockForceField(tier);
GameRegistry.registerBlock(blockForceField, "blockForceField" + tier);
GameRegistry.registerTileEntity(TileEntityForceField.class, MODID + ":blockForceField" + tier);
// FORCE FIELD PROJECTOR
blockProjector = new BlockProjector(tier);
GameRegistry.registerBlock(blockProjector, "blockProjector" + tier);
GameRegistry.registerTileEntity(TileEntityProjector.class, MODID + ":blockProjector" + tier);
/* TODO
// FORCE FIELD CORE
blockForceFieldCore = new BlockForceFieldCore(tier);
GameRegistry.registerBlock(blockProjector, "blockForceFieldCore" + tier);
GameRegistry.registerTileEntity(TileEntityForceFieldCore.class, MODID + ":blockForceFieldCore" + tier);
*/
}
/* TODO
// SECURITY STATION
blockSecurityStation = new BlockSecurityStation();
GameRegistry.registerBlock(blockSecurityStation, "blockSecurityStation");
GameRegistry.registerTileEntity(TileEntitySecurityStation.class, MODID + ":blockSecurityStation");
*/
// DECORATIVE
blockDecorative = new BlockDecorative();
GameRegistry.registerBlock(blockDecorative, ItemBlockDecorative.class, "blockDecorative");
@ -430,10 +462,19 @@ public class WarpDrive implements LoadingCallback {
GameRegistry.registerItem(itemUpgrade, "itemUpgrade");
}
// TOOL ITEMS
itemTuningRod = new ItemTuningFork();
GameRegistry.registerItem(itemTuningRod, "itemTuningRod");
// FORCEFIELD UPGRADES
itemForceFieldShape = new ItemForceFieldShape();
GameRegistry.registerItem(itemForceFieldShape, "itemForceFieldShape");
blockForceFieldUpgrade = new BlockForceFieldUpgrade();
GameRegistry.registerBlock(blockForceFieldUpgrade, ItemBlockForceFieldUpgrade.class, "blockForceFieldUpgrade");
GameRegistry.registerTileEntity(TileEntityForceFieldUpgrade.class, MODID + ":blockForceFieldUpgrade");
// DAMAGE SOURCES
damageAsphyxia = new DamageAsphyxia();
damageCold = new DamageCold();
damageLaser = new DamageLaser();

View file

@ -0,0 +1,12 @@
package cr0s.warpdrive.api;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
/**
* Created by LemADEC on 16/05/2016.
*/
public interface IEffector {
void onEntityCollided(World world, final int x, final int y, final int z, Entity entity);
}

View file

@ -0,0 +1,26 @@
package cr0s.warpdrive.api;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
/**
* Created by LemADEC on 16/05/2016.
*/
public interface IForceFieldUpgrade {
// Unique name for this upgrade category
String getUpgradeKey();
// Bonus give to this upgrade category (can be positive or negative)
int getUpgradeValue();
// Maximum speed of this upgrade in blocks per projector update
// 0.3 to 30 blocks per upgrade ?
float getMaxScanSpeed(final String upgradeKey, final int upgradeCount);
float getMaxPlaceSpeed(final String upgradeKey, final int upgradeCount);
// Energy impacts of this upgrade
float getStartupEnergyCost(final String upgradeKey, final int upgradeCount);
float getScanEnergyCost(final String upgradeKey, final int upgradeCount);
float getPlaceEnergyCost(final String upgradeKey, final int upgradeCount);
}

View file

@ -0,0 +1,18 @@
package cr0s.warpdrive.api;
import cr0s.warpdrive.data.ForceFieldSetup;
import cr0s.warpdrive.data.VectorI;
import java.util.Collection;
import java.util.Map;
public interface IShapeProvider {
/**
* Return a collection of coordinates to all blocks in a shape.
* Rotation will be applied afterward by callee.
* Warning: this is a threaded call, do NOT access world object during this call!
* Boolean is true when it's the perimeter, false when it's the interior
*/
Map<VectorI, Boolean> getVertexes(ForceFieldSetup forceFieldSetup);
}

View file

@ -0,0 +1,276 @@
package cr0s.warpdrive.block.forcefield;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IEffector;
import cr0s.warpdrive.api.IDamageReceiver;
import cr0s.warpdrive.block.BlockAbstractContainer;
import cr0s.warpdrive.block.hull.BlockHullGlass;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.ForceFieldSetup;
import cr0s.warpdrive.data.PermissionNode;
import cr0s.warpdrive.data.Vector3;
import cr0s.warpdrive.render.RenderBlockForceField;
import net.minecraft.block.Block;
import net.minecraft.block.BlockGlass;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.DamageSource;
import net.minecraft.util.IIcon;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import java.util.List;
import java.util.Random;
public class BlockForceField extends BlockAbstractContainer implements IDamageReceiver {
@SideOnly(Side.CLIENT)
private IIcon[] icons;
private int tier;
private static final float BOUNDING_TOLERANCE = 0.05F;
public BlockForceField(final int tier) {
super(Material.glass);
this.tier = tier;
setHardness(WarpDriveConfig.HULL_HARDNESS[tier - 1]);
setResistance(WarpDriveConfig.HULL_BLAST_RESISTANCE[tier - 1] * 5 / 3);
setStepSound(Block.soundTypeCloth);
setCreativeTab(WarpDrive.creativeTabWarpDrive);
setBlockName("warpdrive.forcefield.block" + tier);
setBlockTextureName("warpdrive:forcefield/forcefield");
}
@Override
public TileEntity createNewTileEntity(World world, int metadata) {
return new TileEntityForceField();
}
@Override
public ItemStack getPickBlock(MovingObjectPosition target, World world, int x, int y, int z, EntityPlayer entityPlayer) {
return null;
}
@Override
public int getMobilityFlag() {
return 2;
}
@Override
@SideOnly(Side.CLIENT)
public IIcon getIcon(int side, int metadata) {
return icons[metadata % 16];
}
@Override
public int quantityDropped(Random random) {
return 0;
}
@Override
public boolean isOpaqueCube() {
return false;
}
@Override
public boolean renderAsNormalBlock() {
return false;
}
@Override
protected boolean canSilkHarvest() {
return false;
}
@Override
@SideOnly(Side.CLIENT)
public void getSubBlocks(Item item, CreativeTabs creativeTab, List list) {
/* Hide in NEI
for (int i = 0; i < 16; ++i) {
list.add(new ItemStack(item, 1, i));
}
/**/
}
@Override
@SideOnly(Side.CLIENT)
public void registerBlockIcons(IIconRegister iconRegister) {
icons = new IIcon[16];
for (int i = 0; i < 16; ++i) {
icons[i] = iconRegister.registerIcon(getTextureName() + "_" + i);
}
}
@SideOnly(Side.CLIENT)
public int getRenderBlockPass() {
return 1;
}
@SideOnly(Side.CLIENT)
public int getRenderType() {
return RenderBlockForceField.renderId;
}
@Override
public boolean shouldSideBeRendered(IBlockAccess world, int x, int y, int z, int side) {
if (world.isAirBlock(x, y, z)) {
return true;
}
ForgeDirection direction = ForgeDirection.getOrientation(side).getOpposite();
Block sideBlock = world.getBlock(x, y, z);
if (sideBlock instanceof BlockGlass || sideBlock instanceof BlockHullGlass || sideBlock instanceof BlockForceField) {
return world.getBlockMetadata(x, y, z)
!= world.getBlockMetadata(x + direction.offsetX, y + direction.offsetY, z + direction.offsetZ);
}
return !world.isSideSolid(x, y, z, direction, false);
}
protected TileEntityProjector getProjector(World world, int x, int y, int z) {
TileEntity tileEntity = world.getTileEntity(x, y, z);
if (tileEntity instanceof TileEntityForceField) {
return ((TileEntityForceField) tileEntity).getProjector();
}
return null;
}
private ForceFieldSetup getForceFieldSetup(World world, int x, int y, int z) {
TileEntity tileEntity = world.getTileEntity(x, y, z);
if (tileEntity instanceof TileEntityForceField) {
return ((TileEntityForceField) tileEntity).getForceFieldSetup();
}
return null;
}
public void onBlockClicked(World world, int x, int y, int z, EntityPlayer entityPlayer) {
ForceFieldSetup forceFieldSetup = getForceFieldSetup(world, x, y, z);
if (forceFieldSetup != null) {
for (IEffector effector : forceFieldSetup.getEffectors()) {
effector.onEntityCollided(world, x, y, z, entityPlayer);
}
}
}
public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z) {
ForceFieldSetup forceFieldSetup = getForceFieldSetup(world, x, y, z);
if (forceFieldSetup != null) {
List<EntityPlayer> entities = world.getEntitiesWithinAABB(EntityPlayer.class, AxisAlignedBB.getBoundingBox(x, y, z, x + 1, y + 0.9D, z + 1));
for (EntityPlayer entityPlayer : entities) {
if (entityPlayer != null && entityPlayer.isSneaking()) {
if ( entityPlayer.capabilities.isCreativeMode
|| forceFieldSetup.isAccessGranted(entityPlayer, PermissionNode.SNEAK_THROUGH)) {
return null;
}
}
}
}
return AxisAlignedBB.getBoundingBox(
x + BOUNDING_TOLERANCE, y + BOUNDING_TOLERANCE, z + BOUNDING_TOLERANCE,
x + 1 - BOUNDING_TOLERANCE, y + 1 - BOUNDING_TOLERANCE, z + 1 - BOUNDING_TOLERANCE);
}
public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity) {
if (world.isRemote) {
return;
}
ForceFieldSetup forceFieldSetup = getForceFieldSetup(world, x, y, z);
if (forceFieldSetup != null) {
for (IEffector effector : forceFieldSetup.getEffectors()) {
effector.onEntityCollided(world, x, y, z, entity);
}
if (entity instanceof EntityLiving && new Vector3(x, y, z).translate(0.5F).distanceTo_square(entity) < 0.4D) {
boolean hasPermission = false;
List<EntityPlayer> entities = world.getEntitiesWithinAABB(EntityPlayer.class, AxisAlignedBB.getBoundingBox(x, y, z, x + 1, y + 0.9D, z + 1));
for (EntityPlayer entityPlayer : entities) {
if (entityPlayer != null && entityPlayer.isSneaking()) {
if ( entityPlayer.capabilities.isCreativeMode
|| forceFieldSetup.isAccessGranted(entityPlayer, PermissionNode.SNEAK_THROUGH)) {
hasPermission = true;
break;
}
}
}
// always slowdown
((EntityLiving) entity).addPotionEffect(new PotionEffect(Potion.moveSlowdown.id, 20, 1));
if (!hasPermission) {
((EntityLiving) entity).addPotionEffect(new PotionEffect(Potion.confusion.id, 80, 3));
entity.attackEntityFrom(WarpDrive.damageShock, 5);
}
}
}
}
@Override
public int colorMultiplier(IBlockAccess blockAccess, int x, int y, int z) {
TileEntity tileEntity = blockAccess.getTileEntity(x, y, z);
if (tileEntity instanceof TileEntityForceField) {
ForceFieldSetup forceFieldSetup = ((TileEntityForceField)tileEntity).getForceFieldSetup();
if (forceFieldSetup != null) {
Block blockCamouflage = forceFieldSetup.getCamouflageBlock();
if (blockCamouflage != null) {
try {
return blockCamouflage.colorMultiplier(blockAccess, x, y, z);
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
}
return super.colorMultiplier(blockAccess, x, y, z);
}
@Override
public int getLightValue(IBlockAccess blockAccess, int x, int y, int z) {
TileEntity tileEntity = blockAccess.getTileEntity(x, y, z);
if (tileEntity instanceof TileEntityForceField) {
ForceFieldSetup forceFieldSetup = ((TileEntityForceField)tileEntity).getForceFieldSetup();
if (forceFieldSetup != null) {
Block blockCamouflage = forceFieldSetup.getCamouflageBlock();
if (blockCamouflage != null) {
try {
return blockCamouflage.getLightValue(blockAccess, x, y, z);
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
}
return 0;
}
@Override
public float getBlockHardness(World world, int x, int y, int z, DamageSource damageSource, int damageParameter, Vector3 damageDirection, int damageLevel) {
return WarpDriveConfig.HULL_HARDNESS[tier - 1];
}
@Override
public int applyDamage(World world, int x, int y, int z, DamageSource damageSource, int damageParameter, Vector3 damageDirection, int damageLevel) {
ForceFieldSetup forceFieldSetup = getForceFieldSetup(world, x, y, z);
if (forceFieldSetup != null) {
return forceFieldSetup.applyDamages(world, x, y, z, damageSource, damageParameter, damageDirection, damageLevel);
}
return 0;
}
}

View file

@ -0,0 +1,95 @@
package cr0s.warpdrive.block.forcefield;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.block.BlockAbstractContainer;
import cr0s.warpdrive.data.EnumForceFieldUpgrade;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.IIcon;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.World;
import java.util.List;
public class BlockForceFieldUpgrade extends BlockAbstractContainer {
@SideOnly(Side.CLIENT)
private final IIcon[] icons;
public BlockForceFieldUpgrade() {
super(Material.iron);
isRotating = false;
setBlockName("warpdrive.forcefield.upgrade");
setBlockTextureName("warpdrive:forcefield/upgrade");
icons = new IIcon[EnumForceFieldUpgrade.length];
}
@Override
public void getSubBlocks(Item item, CreativeTabs creativeTabs, List list) {
for (EnumForceFieldUpgrade enumForceFieldUpgrade : EnumForceFieldUpgrade.values()) {
list.add(new ItemStack(item, 1, enumForceFieldUpgrade.ordinal()));
}
}
@Override
public void registerBlockIcons(IIconRegister iconRegister) {
for (EnumForceFieldUpgrade enumForceFieldUpgrade : EnumForceFieldUpgrade.values()) {
icons[enumForceFieldUpgrade.ordinal()] = iconRegister.registerIcon("warpdrive:forcefield/upgrade" + "_" + enumForceFieldUpgrade.unlocalizedName);
}
}
@Override
public IIcon getIcon(int side, int damage) {
if (damage >= 0 && damage < EnumForceFieldUpgrade.length) {
return icons[damage];
}
return icons[0];
}
@Override
public int damageDropped(int damage) {
return damage;
}
@Override
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityPlayer, int side, float hitX, float hitY, float hitZ) {
if (world.isRemote) {
return false;
}
TileEntity tileEntity = world.getTileEntity(x, y, z);
if (!(tileEntity instanceof TileEntityForceFieldUpgrade)) {
return false;
}
TileEntityForceFieldUpgrade tileEntityForceFieldUpgrade = (TileEntityForceFieldUpgrade) tileEntity;
ItemStack itemStackHeld = entityPlayer.getHeldItem();
if (itemStackHeld == null) {
WarpDrive.addChatMessage(entityPlayer, tileEntityForceFieldUpgrade.getStatus());
return true;
}
return false;
}
@Override
public TileEntity createNewTileEntity(World world, int metadata) {
return new TileEntityForceFieldUpgrade();
}
@Override
protected boolean canSilkHarvest() {
return false;
}
public ItemStack getPickBlock(MovingObjectPosition target, World world, int x, int y, int z, EntityPlayer entityPlayer) {
return null; // FIXME
}
}

View file

@ -0,0 +1,163 @@
package cr0s.warpdrive.block.forcefield;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.block.BlockAbstractContainer;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.EnumForceFieldShape;
import cr0s.warpdrive.item.ItemForceFieldShape;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.IIcon;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public class BlockProjector extends BlockAbstractContainer {
@SideOnly(Side.CLIENT)
private IIcon[] icons;
protected byte tier;
public BlockProjector(final byte tier) {
super(Material.iron);
isRotating = true;
this.tier = tier;
setHardness(WarpDriveConfig.HULL_HARDNESS[tier - 1]);
setResistance(WarpDriveConfig.HULL_BLAST_RESISTANCE[tier - 1] * 5 / 3);
setBlockName("warpdrive.forcefield.projector" + tier);
setBlockTextureName("warpdrive:forcefield/projector");
}
@Override
public void registerBlockIcons(IIconRegister iconRegister) {
icons = new IIcon[11];
icons[ 0] = iconRegister.registerIcon("warpdrive:forcefield/projectorSide_notConnected");
icons[ 1] = iconRegister.registerIcon("warpdrive:forcefield/projectorSide_connectedNotPowered");
icons[ 2] = iconRegister.registerIcon("warpdrive:forcefield/projectorSide_connectedPowered");
icons[ 3] = iconRegister.registerIcon("warpdrive:forcefield/projectorShape_none");
icons[ 4] = iconRegister.registerIcon("warpdrive:forcefield/projectorShape_sphere");
icons[ 5] = iconRegister.registerIcon("warpdrive:forcefield/projectorShape_cylinder_h");
icons[ 6] = iconRegister.registerIcon("warpdrive:forcefield/projectorShape_cylinder_v");
icons[ 7] = iconRegister.registerIcon("warpdrive:forcefield/projectorShape_cube");
icons[ 8] = iconRegister.registerIcon("warpdrive:forcefield/projectorShape_plane");
icons[ 9] = iconRegister.registerIcon("warpdrive:forcefield/projectorShape_tube");
icons[10] = iconRegister.registerIcon("warpdrive:forcefield/projectorShape_tunnel");
}
@Override
public IIcon getIcon(IBlockAccess world, int x, int y, int z, int side) {
int metadata = world.getBlockMetadata(x, y, z);
TileEntity tileEntity = world.getTileEntity(x, y, z);
if (tileEntity == null || !(tileEntity instanceof TileEntityProjector)) {
return icons[0];
}
if (side == (metadata & 7) || (((TileEntityProjector)tileEntity).isDoubleSided && ForgeDirection.OPPOSITES[side] == (metadata & 7))) {
return icons[3 + ((TileEntityProjector)tileEntity).getShape().ordinal()];
} else if (((TileEntityProjector)tileEntity).isConnected) {
if (((TileEntityProjector)tileEntity).isPowered) {
return icons[2];
} else {
return icons[1];
}
}
return icons[0];
}
@Override
public IIcon getIcon(int side, int metadata) {
return side == 3 ? icons[4] : icons[2];
}
@Override
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityPlayer, int side, float hitX, float hitY, float hitZ) {
if (world.isRemote) {
return false;
}
TileEntity tileEntity = world.getTileEntity(x, y, z);
if (!(tileEntity instanceof TileEntityProjector)) {
return false;
}
TileEntityProjector tileEntityProjector = (TileEntityProjector) tileEntity;
ItemStack itemStackHeld = entityPlayer.getHeldItem();
int metadata = world.getBlockMetadata(x, y, z);
if (itemStackHeld == null) {
if (entityPlayer.isSneaking()) {
if (tileEntityProjector.getShape() != EnumForceFieldShape.NONE) {
if (side == (metadata & 7) || (tileEntityProjector.isDoubleSided && ForgeDirection.OPPOSITES[side] == (metadata & 7))) {
// dismount the shape item(s)
ItemStack itemStackDrop = ItemForceFieldShape.getItemStackNoCache(tileEntityProjector.getShape(), tileEntityProjector.isDoubleSided ? 2 : 1);
EntityItem entityItem = new EntityItem(world, entityPlayer.posX, entityPlayer.posY + 0.5D, entityPlayer.posZ, itemStackDrop);
entityItem.delayBeforeCanPickup = 0;
world.spawnEntityInWorld(entityItem);
tileEntityProjector.setShape(EnumForceFieldShape.NONE);
} else {
// wrong side TODO
WarpDrive.addChatMessage(entityPlayer, tileEntityProjector.getStatus());
return true;
}
} else {
// no shape to dismount TODO
WarpDrive.addChatMessage(entityPlayer, tileEntityProjector.getStatus());
return true;
}
} else {
WarpDrive.addChatMessage(entityPlayer, tileEntityProjector.getStatus());
return true;
}
} else if (itemStackHeld.getItem() instanceof ItemForceFieldShape) {
if (side == (metadata & 7) || (((TileEntityProjector) tileEntity).isDoubleSided && ForgeDirection.OPPOSITES[side] == (metadata & 7))) {
// validate quantity
if (itemStackHeld.stackSize < (tileEntityProjector.isDoubleSided ? 2 : 1)) {
// not enough shape items TODO
WarpDrive.addChatMessage(entityPlayer, ((TileEntityProjector) tileEntity).getStatus());
return true;
}
// update player inventory
itemStackHeld.stackSize -= tileEntityProjector.isDoubleSided ? 2 : 1;
// dismount the shape item(s)
if (tileEntityProjector.getShape() != EnumForceFieldShape.NONE) {
ItemStack itemStackDrop = ItemForceFieldShape.getItemStackNoCache(tileEntityProjector.getShape(), tileEntityProjector.isDoubleSided ? 2 : 1);
EntityItem entityItem = new EntityItem(world, entityPlayer.posX, entityPlayer.posY + 0.5D, entityPlayer.posZ, itemStackDrop);
entityItem.delayBeforeCanPickup = 0;
world.spawnEntityInWorld(entityItem);
}
// mount the new shape item(s)
tileEntityProjector.setShape(EnumForceFieldShape.get(itemStackHeld.getItemDamage()));
} else {
// wrong side TODO
WarpDrive.addChatMessage(entityPlayer, ((TileEntityProjector) tileEntity).getStatus());
return true;
}
}
return false;
}
@Override
public TileEntity createNewTileEntity(World world, int metadata) {
return new TileEntityProjector();
}
@Override
protected boolean canSilkHarvest() {
return false;
}
public ItemStack getPickBlock(MovingObjectPosition target, World world, int x, int y, int z, EntityPlayer entityPlayer) {
return null; // FIXME
}
}

View file

@ -0,0 +1,78 @@
package cr0s.warpdrive.block.forcefield;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.data.DecorativeType;
import cr0s.warpdrive.data.EnumForceFieldUpgrade;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import net.minecraft.util.StatCollector;
import java.util.List;
public class ItemBlockForceFieldUpgrade extends ItemBlock {
private static ItemStack[] itemStackCache;
public ItemBlockForceFieldUpgrade(Block block) {
super(block);
setHasSubtypes(true);
setUnlocalizedName("warpdrive.forcefield.upgrade");
itemStackCache = new ItemStack[EnumForceFieldUpgrade.length];
}
@Override
public int getMetadata(int damage) {
return damage;
}
@Override
public void getSubItems(Item item, CreativeTabs creativeTab, List list) {
for(EnumForceFieldUpgrade enumForceFieldUpgrade : EnumForceFieldUpgrade.values()) {
list.add(new ItemStack(item, 1, enumForceFieldUpgrade.ordinal()));
}
}
@Override
public String getUnlocalizedName(ItemStack itemStack) {
int damage = itemStack.getItemDamage();
if (damage >= 0 && damage < EnumForceFieldUpgrade.length) {
return getUnlocalizedName() + "." + EnumForceFieldUpgrade.get(damage).unlocalizedName;
}
return getUnlocalizedName();
}
public static ItemStack getItemStack(EnumForceFieldUpgrade enumForceFieldUpgrade) {
if (enumForceFieldUpgrade != null) {
int damage = enumForceFieldUpgrade.ordinal();
if (itemStackCache[damage] == null) {
itemStackCache[damage] = new ItemStack(WarpDrive.itemComponent, 1, damage);
}
return itemStackCache[damage];
}
return null;
}
public static ItemStack getItemStackNoCache(EnumForceFieldUpgrade enumForceFieldUpgrade, int amount) {
return new ItemStack(WarpDrive.blockForceFieldUpgrade, amount, enumForceFieldUpgrade.ordinal());
}
@Override
public void addInformation(ItemStack itemStack, EntityPlayer entityPlayer, List list, boolean advancedItemTooltips) {
super.addInformation(itemStack, entityPlayer, list, advancedItemTooltips);
String tooltipName1 = getUnlocalizedName(itemStack) + ".tooltip";
if (StatCollector.canTranslate(tooltipName1)) {
WarpDrive.addTooltip(list, StatCollector.translateToLocalFormatted(tooltipName1));
}
String tooltipName2 = getUnlocalizedName() + ".tooltip";
if ((!tooltipName1.equals(tooltipName2)) && StatCollector.canTranslate(tooltipName2)) {
WarpDrive.addTooltip(list, StatCollector.translateToLocalFormatted(tooltipName2));
}
}
}

View file

@ -0,0 +1,196 @@
package cr0s.warpdrive.block.forcefield;
import cpw.mods.fml.common.Optional;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IBeamFrequency;
import cr0s.warpdrive.block.TileEntityAbstractEnergy;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.ForceFieldRegistry;
import cr0s.warpdrive.data.Vector3;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.peripheral.IComputerAccess;
import li.cil.oc.api.machine.Arguments;
import li.cil.oc.api.machine.Callback;
import li.cil.oc.api.machine.Context;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
import net.minecraft.util.StatCollector;
/**
* Created by LemADEC on 16/05/2016.
*/
public class TileEntityAbstractForceField extends TileEntityAbstractEnergy implements IBeamFrequency {
// persistent properties
protected int beamFrequency = -1;
public boolean isEnabled = true;
// computed properties
protected Vector3 vRGB;
protected boolean isConnected = true;
public TileEntityAbstractForceField() {
super();
addMethods(new String[]{
"enable",
"beamFrequency"
});
}
@Override
protected void onFirstUpdateTick() {
if (beamFrequency >= 0 && beamFrequency <= IBeamFrequency.BEAM_FREQUENCY_MAX) {
ForceFieldRegistry.updateInRegistry(this);
}
}
@Override
public void updateEntity() {
super.updateEntity();
// Frequency is not set
isConnected = beamFrequency > 0 && beamFrequency <= IBeamFrequency.BEAM_FREQUENCY_MAX;
}
@Override
public void invalidate() {
super.invalidate();
ForceFieldRegistry.removeFromRegistry(this);
}
@Override
public void onChunkUnload() {
super.onChunkUnload();
// reload chunks as needed?
// ForceFieldRegistry.removeFromRegistry(this);
}
@Override
public int getBeamFrequency() {
return beamFrequency;
}
@Override
public void setBeamFrequency(final int parBeamFrequency) {
if (beamFrequency != parBeamFrequency && (parBeamFrequency <= BEAM_FREQUENCY_MAX) && (parBeamFrequency > 0)) {
if (WarpDriveConfig.LOGGING_VIDEO_CHANNEL) {
WarpDrive.logger.info(this + " Beam frequency set from " + beamFrequency + " to " + parBeamFrequency);
}
if (worldObj != null) {
ForceFieldRegistry.removeFromRegistry(this);
}
beamFrequency = parBeamFrequency;
vRGB = IBeamFrequency.getBeamColor(beamFrequency);
}
if (worldObj != null) {
ForceFieldRegistry.updateInRegistry(this);
worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
}
}
protected String getBeamFrequencyStatus() {
if (beamFrequency < 0) {
return StatCollector.translateToLocalFormatted("warpdrive.beamFrequency.statusLine.invalid",
beamFrequency);
} else {
return StatCollector.translateToLocalFormatted("warpdrive.beamFrequency.statusLine.valid",
beamFrequency);
}
}
public String getStatus() {
return StatCollector.translateToLocalFormatted("warpdrive.guide.prefix",
getBlockType().getLocalizedName())
+ getBeamFrequencyStatus();
}
@Override
public void readFromNBT(NBTTagCompound tag) {
super.readFromNBT(tag);
setBeamFrequency(tag.getInteger("beamFrequency"));
isEnabled = tag.getBoolean("isEnabled");
}
@Override
public void writeToNBT(NBTTagCompound tag) {
super.writeToNBT(tag);
tag.setInteger("beamFrequency", beamFrequency);
tag.setBoolean("isEnabled", isEnabled);
}
@Override
public Packet getDescriptionPacket() {
NBTTagCompound tagCompound = new NBTTagCompound();
writeToNBT(tagCompound);
tagCompound.setBoolean("isConnected", isConnected);
return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 1, tagCompound);
}
@Override
public void onDataPacket(NetworkManager networkManager, S35PacketUpdateTileEntity packet) {
NBTTagCompound tagCompound = packet.func_148857_g();
readFromNBT(tagCompound);
isConnected = tagCompound.getBoolean("isConnected");
}
// OpenComputer callback methods
@Callback
@Optional.Method(modid = "OpenComputers")
public Object[] enable(Context context, Arguments arguments) throws Exception {
return enable(argumentsOCtoCC(arguments));
}
@Callback
@Optional.Method(modid = "OpenComputers")
public Object[] beamFrequency(Context context, Arguments arguments) {
if (arguments.count() == 1) {
setBeamFrequency(arguments.checkInteger(0));
}
return new Integer[] { beamFrequency };
}
public Object[] enable(Object[] arguments) throws Exception {
if (arguments.length == 1) {
boolean enable;
try {
enable = toBool(arguments[0]);
} catch (Exception exception) {
throw new Exception("Function expects a boolean value");
}
isEnabled = enable;
}
return new Object[] { isEnabled };
}
// ComputerCraft IPeripheral methods implementation
@Override
@Optional.Method(modid = "ComputerCraft")
public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) {
String methodName = getMethodName(method);
try {
switch (methodName) {
case "enable":
return enable(arguments);
case "beamFrequency":
if (arguments.length == 1) {
setBeamFrequency(toInt(arguments[0]));
}
return new Integer[]{ beamFrequency };
}
} catch (Exception exception) {
return new String[] { exception.getMessage() };
}
return super.callMethod(computer, context, method, arguments);
}
@Override
public String toString() {
return String.format("%s Beam \'%d\' @ \'%s\' (%d %d %d)", getClass().getSimpleName(),
beamFrequency, worldObj == null ? "~NULL~" : worldObj.getWorldInfo().getWorldName(), xCoord, yCoord, zCoord);
}
}

View file

@ -0,0 +1,115 @@
package cr0s.warpdrive.block.forcefield;
import cr0s.warpdrive.block.TileEntityAbstractBase;
import cr0s.warpdrive.data.ForceFieldSetup;
import cr0s.warpdrive.data.VectorI;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
import net.minecraft.tileentity.TileEntity;
/**
* Created by LemADEC on 16/05/2016.
*/
public class TileEntityForceField extends TileEntityAbstractBase {
private VectorI vProjector;
// cache parameters used for rendering, force projector check for others
private int cache_beamFrequency;
private ItemStack cache_itemStackCamouflage;
private int gracePeriod_calls = 1;
@Override
public boolean canUpdate() {
return false;
}
@Override
public void readFromNBT(NBTTagCompound tag) {
super.readFromNBT(tag);
if (tag.hasKey("projector")) {
vProjector = VectorI.readFromNBT(tag.getCompoundTag("projector"));
cache_beamFrequency = tag.getInteger("beamFrequency");
if (tag.hasKey("projector")) {
try {
cache_itemStackCamouflage = ItemStack.loadItemStackFromNBT(tag.getCompoundTag("camouflage"));
} catch (Exception exception) {
exception.printStackTrace();
}
} else {
cache_itemStackCamouflage = null;
}
} else {
vProjector = null;
cache_beamFrequency = -1;
cache_itemStackCamouflage = null;
}
}
@Override
public void writeToNBT(NBTTagCompound tagCompound) {
super.writeToNBT(tagCompound);
if (vProjector != null) {
tagCompound.setTag("projector", vProjector.writeToNBT(new NBTTagCompound()));
tagCompound.setInteger("beamFrequency", cache_beamFrequency);
if (cache_itemStackCamouflage != null) {
tagCompound.setTag("camouflage", cache_itemStackCamouflage.writeToNBT(new NBTTagCompound()));
}
}
}
@Override
public Packet getDescriptionPacket() {
NBTTagCompound tagCompound = new NBTTagCompound();
writeToNBT(tagCompound);
return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, -1, tagCompound);
}
@Override
public void onDataPacket(NetworkManager networkManager, S35PacketUpdateTileEntity packet) {
NBTTagCompound tagCompound = packet.func_148857_g();
readFromNBT(tagCompound);
// worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); // TODO is it needed?
}
public void setProjector(final VectorI vectorI) {
vProjector = vectorI;
ForceFieldSetup forceFieldSetup = getForceFieldSetup();
if (forceFieldSetup != null) {
cache_beamFrequency = forceFieldSetup.beamFrequency;
cache_itemStackCamouflage = forceFieldSetup.itemStackCamouflage;
}
worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
}
public TileEntityProjector getProjector() {
if (vProjector != null) {
TileEntity tileEntity = vProjector.getTileEntity(worldObj);
if (tileEntity instanceof TileEntityProjector) {
TileEntityProjector tileEntityProjector = (TileEntityProjector) tileEntity;
if (worldObj.isRemote || tileEntityProjector.isPartOfForceField(new VectorI(this))) {
return tileEntityProjector;
}
}
}
if (!worldObj.isRemote) {
gracePeriod_calls--;
if (gracePeriod_calls < 0) {
worldObj.setBlockToAir(xCoord, yCoord, zCoord);
}
}
return null;
}
public ForceFieldSetup getForceFieldSetup() {
TileEntityProjector tileEntityProjector = getProjector();
if (tileEntityProjector == null) {
return null;
}
return tileEntityProjector.getForceFieldSetup();
}
}

View file

@ -0,0 +1,50 @@
package cr0s.warpdrive.block.forcefield;
import cr0s.warpdrive.api.IForceFieldUpgrade;
import cr0s.warpdrive.data.EnumForceFieldUpgrade;
/**
* Created by LemADEC on 16/05/2016.
*/
public class TileEntityForceFieldUpgrade extends TileEntityAbstractForceField implements IForceFieldUpgrade {
public TileEntityForceFieldUpgrade() {
super();
peripheralName = "warpdriveForceFieldUpgrade";
}
@Override
public String getUpgradeKey() {
return isEnabled ? EnumForceFieldUpgrade.get(getBlockMetadata()).unlocalizedName : null;
}
@Override
public int getUpgradeValue() {
return 1000;
}
@Override
public float getMaxScanSpeed(final String upgradeKey, final int upgradeCount) {
return 10.0F;
}
@Override
public float getMaxPlaceSpeed(final String upgradeKey, final int upgradeCount) {
return 10.0F;
}
@Override
public float getStartupEnergyCost(final String upgradeKey, final int upgradeCount) {
return 100.0F;
}
@Override
public float getScanEnergyCost(final String upgradeKey, final int upgradeCount) {
return 1.0F;
}
@Override
public float getPlaceEnergyCost(final String upgradeKey, final int upgradeCount) {
return 10.0F;
}
}

View file

@ -0,0 +1,502 @@
package cr0s.warpdrive.block.forcefield;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IShapeProvider;
import cr0s.warpdrive.config.*;
import cr0s.warpdrive.config.Dictionary;
import cr0s.warpdrive.data.*;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.StatCollector;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.common.util.ForgeDirection;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Created by LemADEC on 16/05/2016.
*/
public class TileEntityProjector extends TileEntityAbstractForceField {
private static final int PROJECTOR_MAX_ENERGY_STORED = 100000;
private static final int PROJECTOR_COOLDOWN_TICKS = 200;
private static final int PROJECTOR_PROJECTION_UPDATE_TICKS = 8;
private static final int PROJECTOR_SOUND_UPDATE_TICKS = Integer.MAX_VALUE; // TODO
private static final int PROJECTOR_SCAN_MAX_BLOCKS_PER_UPDATE = 200;
private static final int PROJECTOR_PLACE_MAX_BLOCKS_PER_UPDATE = 100;
// persistent properties
public boolean isDoubleSided = true;
private byte tier = -1;
private EnumForceFieldShape shape = EnumForceFieldShape.NONE;
// computed properties
private int cooldownTicks;
private int updateTicks;
protected boolean isPowered = true;
private final boolean enableSound = false;
// allow only one computation at a time
private static final AtomicBoolean isGlobalThreadRunning = new AtomicBoolean(false);
// computation is ongoing for this specific tile
private final AtomicBoolean isThreadRunning = new AtomicBoolean(false);
// parameters have changed, new computation is required
private final AtomicBoolean isDirty = new AtomicBoolean(true);
private Set<VectorI> calculated_interiorField = null;
private Set<VectorI> calculated_forceField = null;
private Iterator<VectorI> iteratorForcefield = null;
// currently placed forcefields
private final Set<VectorI> vForceFields = new HashSet<>();
public TileEntityProjector() {
super();
peripheralName = "warpdriveForceFieldProjector";
addMethods(new String[]{
"status" // isConnected, isPowered, shape
});
}
@Override
protected void onFirstUpdateTick() {
super.onFirstUpdateTick();
tier = ((BlockProjector) getBlockType()).tier;
cooldownTicks = worldObj.rand.nextInt(PROJECTOR_PROJECTION_UPDATE_TICKS);
}
@Override
public void updateEntity() {
super.updateEntity();
// Frequency is not set
if (!isConnected) {
return;
}
// Powered ?
int energyRequired;
energyRequired = getEnergyRequired();
isPowered = getEnergyStored() >= energyRequired;
boolean isEnabledAndValid = isEnabled && isValid();
boolean isOn = isEnabledAndValid && cooldownTicks <= 0 && isPowered;
if (isOn) {
consumeEnergy(energyRequired, false);
cooldownTicks = 0;
updateTicks++;
if (!worldObj.isRemote) {
if (updateTicks > PROJECTOR_PROJECTION_UPDATE_TICKS) {
updateTicks = 0;
if (!isCalculated()) {
calculateForceField();
} else {
projectForceField();
}
}
} else {
// TODO add some animation
if (updateTicks > PROJECTOR_SOUND_UPDATE_TICKS) {
if (enableSound) {
worldObj.playSoundEffect(xCoord + 0.5D, yCoord + 0.5D, zCoord + 0.5D, "projecting", 1.0F, 0.85F + 0.15F * worldObj.rand.nextFloat());
}
}
}
} else if (!worldObj.isRemote) {
destroyForceField(false);
if (cooldownTicks > 0) {
cooldownTicks--;
} else if (isEnabledAndValid) {
cooldownTicks = PROJECTOR_COOLDOWN_TICKS;
String msg = "We're running out of power captain, reduce our consumption or get that scottish engineer to boost our power!";
AxisAlignedBB axisalignedbb = AxisAlignedBB.getBoundingBox(xCoord - 10, yCoord - 10, zCoord - 10, xCoord + 10, yCoord + 10, zCoord + 10);
List<Entity> list = worldObj.getEntitiesWithinAABBExcludingEntity(null, axisalignedbb);
System.out.println(this + " messageToPlayersNearby: " + msg);
for (Entity entity : list) {
if (entity == null || (!(entity instanceof EntityPlayer)) || entity instanceof FakePlayer) {
continue;
}
WarpDrive.addChatMessage((EntityPlayer) entity, "[Projector] " + msg);
}
}
}
}
@Override
public void invalidate() {
super.invalidate();
destroyForceField(true);
}
private int getEnergyRequired() {
return 6 + 2 * tier;
}
public boolean isValid() {
return getShape() != EnumForceFieldShape.NONE;
}
public boolean isCalculated() {
return !isDirty.get() && !isThreadRunning.get();
}
private void calculateForceField() {
if ((!worldObj.isRemote) && isValid()) {
if (!isGlobalThreadRunning.getAndSet(true)) {
isThreadRunning.set(true);
isDirty.set(false);
iteratorForcefield = null;
calculated_interiorField = null;
calculated_forceField = null;
vForceFields.clear();
new ThreadCalculation(this).start();
}
}
}
private void calculation_done(Set<VectorI> interiorField, Set<VectorI> forceField) {
if (interiorField == null || forceField == null) {
calculated_interiorField = new HashSet<>(0);
calculated_forceField = new HashSet<>(0);
} else {
calculated_interiorField = interiorField;
calculated_forceField = forceField;
}
isThreadRunning.set(false);
isGlobalThreadRunning.set(false);
}
public boolean isPartOfForceField(VectorI vector) {
if (!isEnabled || !isValid()) {
return false;
}
if (!isCalculated()) {
return true;
}
// only consider the forcefield itself
return calculated_forceField.contains(vector);
}
private Set<VectorI> getInteriorPoints() {
if (!isCalculated()) {
throw new ConcurrentModificationException("Calculation ongoing...");
}
return calculated_interiorField;
}
private void projectForceField() {
if (worldObj.isRemote || (!isCalculated())) {
return;
}
ForceFieldSetup forceFieldSetup = getForceFieldSetup();
int scanCount = 0;
int scanSpeed = Math.min(calculated_forceField.size(), PROJECTOR_SCAN_MAX_BLOCKS_PER_UPDATE);
int constructionCount = 0;
int constructionSpeed = Math.min(forceFieldSetup.getProjectionSpeed(), PROJECTOR_PLACE_MAX_BLOCKS_PER_UPDATE);
boolean hasDisintegration = forceFieldSetup.disintegrationLevel > 0;
Set<TileEntityProjector> projectors = new HashSet<>();
if (forceFieldSetup.hasFusion) {
for (TileEntity tileEntity : ForceFieldRegistry.getTileEntities(getBeamFrequency())) {
if ( (tileEntity instanceof TileEntityProjector)
&& (tileEntity != this)
&& (((TileEntityProjector) tileEntity).worldObj == worldObj)
&& (((TileEntityProjector) tileEntity).isEnabled)
&& (((TileEntityProjector) tileEntity).isValid())
&& (((TileEntityProjector) tileEntity).isCalculated())) {
projectors.add((TileEntityProjector) tileEntity);
}
}
}
VectorI vector;
Block block;
boolean noFusion;
while (scanCount < scanSpeed && constructionCount < constructionSpeed) {
if (iteratorForcefield == null || !iteratorForcefield.hasNext()) {
iteratorForcefield = calculated_forceField.iterator();
}
scanCount++;
vector = iteratorForcefield.next();
if (!worldObj.blockExists(vector.x, vector.y, vector.z) || !worldObj.getChunkFromBlockCoords(vector.x, vector.z).isChunkLoaded) {
continue;
}
block = vector.getBlock(worldObj);
noFusion = true;
if (forceFieldSetup.hasFusion) {
for (TileEntityProjector projector : projectors) {
if (projector.getInteriorPoints().contains(vector)) {
noFusion = false;
break;
}
}
}
if (noFusion) {
// TODO: check area protection
// MFR laser is unbreakable and replaceable
// Liquid, vine and snow are replaceable
if ( (block == null) || (block == Blocks.tallgrass) || (block == Blocks.deadbush)
|| Dictionary.BLOCKS_EXPANDABLE.contains(block)
|| (hasDisintegration && (block.getBlockHardness(worldObj, vector.x, vector.y, vector.z) != -1.0F))
|| (!hasDisintegration && block.isReplaceable(worldObj, vector.x, vector.y, vector.z))) {
if ((block != WarpDrive.blockForceField) && (!vector.equals(this))) {
float energyConsumed = 0;
// if (forceFieldSetup.disintegrationLevel > 0) {
// TODO break the block
// TODO store result in chest or drop it?
// } else if (forceFieldSetup.hasStabilize) {
// TODO collect from chest
// TODO place block (ItemBlock.place?)
// } else if (forceFieldSetup.hasPump) {
// } else if (forceFieldSetup.temperatureLevel != 0 && forceFieldSetup.hasWorldInteraction) {
// TODO glass <> sandstone <> sand <> gravel <> cobblestone <> stone <> obsidian
// TODO ice <> snow <> water <> air > fire
// TODO obsidian < lava
// } else {
energyConsumed = 1; // TODO
worldObj.setBlock(vector.x, vector.y, vector.z, WarpDrive.blockForceField, 0, 2);
TileEntity tileEntity = worldObj.getTileEntity(vector.x, vector.y, vector.z);
if (tileEntity instanceof TileEntityForceField) {
((TileEntityForceField) tileEntity).setProjector(new VectorI(this));
}
vForceFields.add(vector);
// }
if (energyConsumed > 0) {
constructionCount++;
consumeEnergy(Math.round(energyConsumed), false);
} else {
consumeEnergy(Math.round(1), false); // TODO
}
}
} else if (block == WarpDrive.blockForceField && !vForceFields.contains(vector)) {
TileEntity tileEntity = worldObj.getTileEntity(vector.x, vector.y, vector.z);
if (tileEntity instanceof TileEntityForceField && (((TileEntityForceField) tileEntity).getProjector() == this)) {
vForceFields.add(vector);
}
}
} else {
if (block == WarpDrive.blockForceField) {
if (((BlockForceField) block).getProjector(worldObj, vector.x, vector.y, vector.z) == this) {
worldObj.setBlockToAir(vector.x, vector.y, vector.z);
}
}
}
}
}
private void destroyForceField(boolean isChunkLoading) {
if ((!worldObj.isRemote) && (!vForceFields.isEmpty())) {
for (Iterator<VectorI> iterator = vForceFields.iterator(); iterator.hasNext();) {
VectorI vector = iterator.next();
if (!isChunkLoading) {
if (!(worldObj.blockExists(vector.x, vector.y, vector.z))) {// chunk is not loaded, skip it
continue;
}
if (!worldObj.getChunkFromBlockCoords(vector.x, vector.z).isChunkLoaded) {// chunk is unloading, skip it
continue;
}
}
Block block = vector.getBlock(worldObj);
if (block == WarpDrive.blockForceField) {
worldObj.setBlockToAir(vector.x, vector.y, vector.z);
}
iterator.remove();
}
}
if ((!worldObj.isRemote) && isCalculated() && isChunkLoading) {
for (VectorI vector : calculated_forceField) {
Block block = vector.getBlock(worldObj);
if (block == WarpDrive.blockForceField) {
TileEntity tileEntity = worldObj.getTileEntity(vector.x, vector.y, vector.z);
if (tileEntity instanceof TileEntityForceField && (((TileEntityForceField) tileEntity).getProjector() == this)) {
worldObj.setBlockToAir(vector.x, vector.y, vector.z);
}
}
}
}
}
public IShapeProvider getShapeProvider() {
return WarpDrive.itemForceFieldShape;
}
@Override
public int getBeamFrequency() {
return beamFrequency;
}
@Override
public void setBeamFrequency(final int parBeamFrequency) {
super.setBeamFrequency(parBeamFrequency);
isDirty.set(true);
if (worldObj != null) {
destroyForceField(false);
}
}
public String getStatus() {
return StatCollector.translateToLocalFormatted("warpdrive.guide.prefix",
getBlockType().getLocalizedName())
+ getBeamFrequencyStatus();
// TODO add energy info
}
@Override
public void readFromNBT(NBTTagCompound tag) {
super.readFromNBT(tag);
isDoubleSided = tag.getBoolean("isDoubleSided");
tier = tag.getByte("tier");
setShape(EnumForceFieldShape.get(tag.getByte("shape")));
}
@Override
public void writeToNBT(NBTTagCompound tag) {
super.writeToNBT(tag);
tag.setBoolean("isDoubleSided", isDoubleSided);
tag.setByte("tier", tier);
tag.setByte("shape", (byte) getShape().ordinal());
}
@Override
public Packet getDescriptionPacket() {
NBTTagCompound tagCompound = new NBTTagCompound();
writeToNBT(tagCompound);
tagCompound.setBoolean("isPowered", isPowered);
return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 1, tagCompound);
}
@Override
public void onDataPacket(NetworkManager networkManager, S35PacketUpdateTileEntity packet) {
NBTTagCompound tagCompound = packet.func_148857_g();
readFromNBT(tagCompound);
isPowered = tagCompound.getBoolean("isPowered");
}
public ForceFieldSetup getForceFieldSetup() {
return new ForceFieldSetup(worldObj.provider.dimensionId, xCoord, yCoord, zCoord, tier, beamFrequency);
}
@Override
public int getMaxEnergyStored() {
return PROJECTOR_MAX_ENERGY_STORED;
}
@Override
public boolean canInputEnergy(ForgeDirection from) {
return true;
}
public EnumForceFieldShape getShape() {
return shape;
}
public void setShape(EnumForceFieldShape shape) {
this.shape = shape;
isDirty.set(true);
if (worldObj != null) {
worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
destroyForceField(false);
}
}
private class ThreadCalculation extends Thread {
private final TileEntityProjector projector;
public ThreadCalculation(TileEntityProjector projector) {
this.projector = projector;
}
@Override
public void run() {
Set<VectorI> vPerimeterBlocks = null;
Set<VectorI> vInteriorBlocks = null;
// calculation start is done synchronously, by caller
try {
if (projector.isValid()) {
ForceFieldSetup forceFieldSetup = projector.getForceFieldSetup();
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
WarpDrive.logger.info("Calculation started for " + projector);
}
// create HashSets
VectorI vScale = forceFieldSetup.vMax.clone().subtract(forceFieldSetup.vMin);
vInteriorBlocks = new HashSet<>(vScale.x * vScale.y * vScale.z);
vPerimeterBlocks = new HashSet<>(2 * vScale.x * vScale.y + 2 * vScale.x * vScale.z + 2 * vScale.y * vScale.z);
// compute interior fields to remove overlapping parts
for (Map.Entry<VectorI, Boolean> entry : forceFieldSetup.shapeProvider.getVertexes(forceFieldSetup).entrySet()) {
VectorI vPosition = entry.getKey();
if (forceFieldSetup.isDoubleSided || vPosition.y >= yCoord) {
if ((forceFieldSetup.rotationYaw != 0) || (forceFieldSetup.rotationPitch != 0)) {
vPosition.rotateByAngle(forceFieldSetup.rotationYaw, forceFieldSetup.rotationPitch);
}
vPosition.translate(forceFieldSetup.vTranslation);
if (vPosition.y > 0 && vPosition.y <= projector.worldObj.getHeight()) {
if (entry.getValue()) {
vPerimeterBlocks.add(vPosition);
} else {
vInteriorBlocks.add(vPosition);
}
}
}
}
// compute forcefield itself
if (forceFieldSetup.isInverted) {
// inverted mode => same as interior before fusion => need to be fully cloned
vPerimeterBlocks = new HashSet<>(vInteriorBlocks);
}
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
WarpDrive.logger.info(projector + " Calculation done: "
+ vInteriorBlocks.size() + " blocks inside, including " + vPerimeterBlocks.size() + " blocks to place");
}
} else {
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
WarpDrive.logger.info(projector + " Calculation aborted");
}
}
} catch (Exception exception) {
vInteriorBlocks = null;
vPerimeterBlocks = null;
exception.printStackTrace();
WarpDrive.logger.error(projector + " Calculation failed");
}
projector.calculation_done(vInteriorBlocks, vPerimeterBlocks);
}
}
}

View file

@ -133,6 +133,8 @@ public class WarpDriveConfig {
public static boolean LOGGING_DICTIONARY = false;
public static boolean LOGGING_STARMAP = false;
public static boolean LOGGING_BREAK_PLACE = false;
public static boolean LOGGING_FORCEFIELD = false;
public static boolean LOGGING_FORCEFIELD_REGISTRY = false;
// Planets
public static Planet[] PLANETS = null;
@ -340,6 +342,7 @@ public class WarpDriveConfig {
public static void onFMLpreInitialization(final String stringConfigDirectory) {
// create mod folder
configDirectory = new File(stringConfigDirectory, WarpDrive.MODID);
//noinspection ResultOfMethodCallIgnored
configDirectory.mkdir();
if (!configDirectory.isDirectory()) {
throw new RuntimeException("Unable to create config directory " + configDirectory);
@ -419,6 +422,8 @@ public class WarpDriveConfig {
LOGGING_DICTIONARY = config.get("logging", "enable_dictionary_logs", LOGGING_DICTIONARY, "Dictionary logs, enable it to dump blocks hardness and blast resistance at boot").getBoolean(true);
LOGGING_STARMAP = config.get("logging", "enable_starmap_logs", LOGGING_STARMAP, "Starmap logs, enable it to dump starmap registry updates").getBoolean(false);
LOGGING_BREAK_PLACE = config.get("logging", "enable_break_place_logs", LOGGING_BREAK_PLACE, "Detailed break/place event logs to help debug the mod, enable it before reporting a bug").getBoolean(false);
LOGGING_FORCEFIELD = config.get("logging", "enable_forcefield_logs", LOGGING_FORCEFIELD, "Detailed forcefield logs to help debug the mod, enable it before reporting a bug").getBoolean(false);
LOGGING_FORCEFIELD_REGISTRY = config.get("logging", "enable_forcefield_registry_logs", LOGGING_FORCEFIELD_REGISTRY, "ForceField registry logs, enable it to dump forcefield registry updates").getBoolean(false);
// Planets
{
@ -854,11 +859,8 @@ public class WarpDriveConfig {
public static void onFMLPostInitialization() {
// unpack default XML files if none are defined
File[] files = configDirectory.listFiles(new FilenameFilter() {
@Override
public boolean accept(File file_notUsed, String name) {
return name.endsWith(".xml");
}
File[] files = configDirectory.listFiles((file_notUsed, name) -> {
return name.endsWith(".xml");
});
if (files.length == 0) {
for (String defaultXMLfilename : defaultXMLfilenames) {

View file

@ -0,0 +1,35 @@
package cr0s.warpdrive.data;
import java.util.HashMap;
public enum EnumForceFieldShape {
NONE ("none"),
SPHERE ("sphere"),
CYLINDER_H ("cylinder_h"),
CYLINDER_V ("cylinder_v"),
CUBE ("cube"),
PLANE ("plane"),
TUBE ("tube"),
TUNNEL ("tunnel");
public final String unlocalizedName;
// cached values
public static final int length;
private static final HashMap<Integer, EnumForceFieldShape> ID_MAP = new HashMap<>();
static {
length = EnumForceFieldShape.values().length;
for (EnumForceFieldShape enumForceFieldShape : values()) {
ID_MAP.put(enumForceFieldShape.ordinal(), enumForceFieldShape);
}
}
EnumForceFieldShape(String unlocalizedName) {
this.unlocalizedName = unlocalizedName;
}
public static EnumForceFieldShape get(final int damage) {
return ID_MAP.get(damage);
}
}

View file

@ -0,0 +1,49 @@
package cr0s.warpdrive.data;
import java.util.HashMap;
public enum EnumForceFieldUpgrade {
NONE ("none" , false, false),
BREAK ("break" , false, true ),
CAMOUFLAGE ("camouflage" , false, true ),
COOL ("cool" , true , true ),
FUSION ("fusion" , true , true ),
MUTE ("mute" , true , false),
RANGE ("range" , true , true ),
ROTATION ("rotation" , true , false),
SHOCK ("shock" , true , true ),
SPEED ("speed" , true , true ),
STABILIZE ("stabilize" , false, true ),
THICKNESS ("thickness" , true , true ),
TRANSLATION ("translation" , true , false),
WARM ("warm" , true , true ),
// reserved 13
// reserved 14
// reserved 15
;
public final String unlocalizedName;
public final boolean allowAsItem;
public final boolean allowAsBlock;
// cached values
public static final int length;
private static final HashMap<Integer, EnumForceFieldUpgrade> ID_MAP = new HashMap<>();
static {
length = EnumForceFieldUpgrade.values().length;
for (EnumForceFieldUpgrade forceFieldShapeType : values()) {
ID_MAP.put(forceFieldShapeType.ordinal(), forceFieldShapeType);
}
}
EnumForceFieldUpgrade(final String unlocalizedName, final boolean allowAsItem, final boolean allowAsBlock) {
this.unlocalizedName = unlocalizedName;
this.allowAsItem = allowAsItem;
this.allowAsBlock = allowAsBlock;
}
public static EnumForceFieldUpgrade get(final int damage) {
return ID_MAP.get(damage);
}
}

View file

@ -0,0 +1,105 @@
package cr0s.warpdrive.data;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IBeamFrequency;
import cr0s.warpdrive.config.WarpDriveConfig;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.WorldServer;
import java.util.*;
/**
* Registry of all known forcefield in the loaded worlds, grouped by frequency
*
* @author LemADEC
*/
public class ForceFieldRegistry {
private static final int FORCE_FIELD_REGISTRY_DEFAULT_ENTRIES_PER_FREQUENCY = 10;
private static final HashMap<Integer, HashSet<GlobalPosition>> registry = new HashMap<>();
public static Set<TileEntity> getTileEntities(final int beamFrequency) {
Set<TileEntity> setEntries = new HashSet<>();
Set<GlobalPosition> setGlobalPositions = registry.get(beamFrequency);
if (setGlobalPositions == null) {
return setEntries;
}
for (Iterator<GlobalPosition> iterator = setGlobalPositions.iterator(); iterator.hasNext();) {
GlobalPosition globalPosition = iterator.next();
WorldServer world = globalPosition.getWorldServerIfLoaded();
if (world != null) {
TileEntity tileEntity = world.getTileEntity(globalPosition.x, globalPosition.y, globalPosition.z);
if ((tileEntity instanceof IBeamFrequency) && ((IBeamFrequency)tileEntity).getBeamFrequency() == beamFrequency) {
setEntries.add(tileEntity);
continue;
}
}
// world isn't loaded or block no longer exist => remove from registry
iterator.remove();
if (WarpDriveConfig.LOGGING_FORCEFIELD_REGISTRY) {
printRegistry("removed");
}
}
return setEntries;
}
public static boolean isInRegistry(final int beamFrequency) {
return !getTileEntities(beamFrequency).isEmpty();
}
public static void updateInRegistry(IBeamFrequency tileEntity) {
assert(tileEntity instanceof TileEntity);
HashSet<GlobalPosition> setGlobalPositions = registry.get(tileEntity.getBeamFrequency());
if (setGlobalPositions == null) {
setGlobalPositions = new HashSet<>(FORCE_FIELD_REGISTRY_DEFAULT_ENTRIES_PER_FREQUENCY);
}
for (Iterator<GlobalPosition> iterator = setGlobalPositions.iterator(); iterator.hasNext();) {
GlobalPosition globalPosition = iterator.next();
if (globalPosition.equals(tileEntity)) {
// already registered
return;
}
}
// not found => add
setGlobalPositions.add(new GlobalPosition((TileEntity)tileEntity));
registry.put(tileEntity.getBeamFrequency(), setGlobalPositions);
if (WarpDriveConfig.LOGGING_FORCEFIELD_REGISTRY) {
printRegistry("added");
}
}
public static void removeFromRegistry(IBeamFrequency tileEntity) {
assert(tileEntity instanceof TileEntity);
Set<GlobalPosition> setGlobalPositions = registry.get(tileEntity.getBeamFrequency());
if (setGlobalPositions == null) {
// noting to remove
return;
}
for (Iterator<GlobalPosition> iterator = setGlobalPositions.iterator(); iterator.hasNext();) {
GlobalPosition globalPosition = iterator.next();
if (globalPosition.equals(tileEntity)) {
// found it, remove and exit
iterator.remove();
return;
}
}
// not found => ignore it
}
public static void printRegistry(final String trigger) {
WarpDrive.logger.info("Forcefield registry (" + registry.size() + " entries after " + trigger + "):");
for (Map.Entry<Integer, HashSet<GlobalPosition>> entry : registry.entrySet()) {
String message = "";
for (GlobalPosition globalPosition : entry.getValue()) {
if (!message.isEmpty()) {
message += ", ";
}
message += globalPosition.dimensionId + ": " + globalPosition.x + " " + globalPosition.y + " " + globalPosition.z;
}
WarpDrive.logger.info("- " + entry.getValue().size() + " entries at frequency " + entry.getKey() + ": " + message);
}
}
}

View file

@ -0,0 +1,138 @@
package cr0s.warpdrive.data;
import cr0s.warpdrive.api.IEffector;
import cr0s.warpdrive.api.IForceFieldUpgrade;
import cr0s.warpdrive.api.IShapeProvider;
import cr0s.warpdrive.block.forcefield.TileEntityProjector;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.DamageSource;
import net.minecraft.world.World;
import java.util.*;
public class ForceFieldSetup extends GlobalPosition {
public int beamFrequency;
public byte tier;
public ItemStack itemStackCamouflage;
private Block blockCamouflage_cache;
private static final List<Integer> ALLOWED_RENDER_TYPES = Arrays.asList(0, 1, 4, 5, 6, 8, 7, 12, 13, 14, 16, 17, 20, 23, 29, 30, 31, 39);
private final HashMap<String, Integer> upgrades = new HashMap<>(EnumForceFieldUpgrade.length);
// TODO
public Set<TileEntityProjector> projectors = new HashSet<>();
public Set<IEffector> effectors = new HashSet<>();
public int disintegrationLevel;
public int temperatureLevel;
public boolean hasStabilize;
public boolean isInverted = false;
public boolean hasFusion;
// Projector provided properties
public float rotationYaw;
public float rotationPitch;
public VectorI vTranslation = new VectorI(0, 0, 0);
public VectorI vMin = new VectorI(-8, -8, -8);
public VectorI vMax = new VectorI(8, 8, 8);
public IShapeProvider shapeProvider;
public EnumForceFieldShape enumForceFieldShape;
public boolean isDoubleSided = true;
public float thickness = 1.0F;
public ForceFieldSetup(final int dimensionId, final int x, final int y, final int z, final byte tier, final int beamFrequency) {
super(dimensionId, x, y, z);
this.tier = tier;
this.beamFrequency = beamFrequency;
refresh();
}
public Collection<IEffector> getEffectors() {
return effectors;
}
public boolean isAccessGranted(EntityPlayer entityPlayer, PermissionNode permissionNode) {
return false; // TODO
}
public static boolean isValidCamouflage(ItemStack itemStack) {
if (itemStack != null && itemStack.stackSize > 0 && itemStack.getItem() instanceof ItemBlock) {
Block block = Block.getBlockFromItem(itemStack.getItem());
return ALLOWED_RENDER_TYPES.contains(block.getRenderType());
}
return false;
}
public Block getCamouflageBlock() {
if (blockCamouflage_cache != null) {
return blockCamouflage_cache;
}
if (isValidCamouflage(itemStackCamouflage)) {
blockCamouflage_cache = Block.getBlockFromItem(itemStackCamouflage.getItem());
return blockCamouflage_cache;
}
return null;
}
public void refresh() {
Set<TileEntity> tileEntities = ForceFieldRegistry.getTileEntities(beamFrequency);
for (TileEntity tileEntity : tileEntities) {
// only consider same dimension
if (tileEntity.getWorldObj().provider.dimensionId != dimensionId) {
continue;
}
// projectors
if (tileEntity instanceof TileEntityProjector) {
TileEntityProjector projector = (TileEntityProjector) tileEntity;
if (tileEntity.xCoord == x && tileEntity.yCoord == y && tileEntity.zCoord == z) {
shapeProvider = projector.getShapeProvider();
enumForceFieldShape = projector.getShape();
isDoubleSided = projector.isDoubleSided;
vTranslation = new VectorI(projector);
// TODO vMin = projector.vMin;
// TODO vMax = projector.vMax;
} else {
if ((((TileEntityProjector) tileEntity).isEnabled)
&& (((TileEntityProjector) tileEntity).isCalculated())
&& (((TileEntityProjector) tileEntity).isValid())) {
projectors.add((TileEntityProjector) tileEntity);
}
}
}
// block upgrades
if (tileEntity instanceof IForceFieldUpgrade) {
String upgradeKey = ((IForceFieldUpgrade)tileEntity).getUpgradeKey();
if (!upgradeKey.isEmpty()) {
Integer count = upgrades.get(upgradeKey);
if (count == null) {
count = 0;
}
upgrades.put(upgradeKey, count + ((IForceFieldUpgrade)tileEntity).getUpgradeValue());
}
}
}
hasFusion = upgrades.containsKey(EnumForceFieldUpgrade.FUSION);
}
@Override
public String toString() {
return String.format("%s @ DIM%d (%d %d %d) (%d %d %d) -> (%d %d %d)",
getClass().getSimpleName(), dimensionId,
x, y, z,
vMin.x, vMin.y, vMin.z,
vMax.x, vMax.y, vMax.z);
}
public int applyDamages(World world, int x, int y, int z, DamageSource damageSource, int damageParameter, Vector3 damageDirection, int damageLevel) {
// TODO
return 0;
}
public int getProjectionSpeed() {
return 1; // TODO
}
}

View file

@ -0,0 +1,33 @@
package cr0s.warpdrive.data;
import java.util.HashMap;
public enum PermissionNode {
NONE ("None"),
ENABLE ("Enable"),
OPEN_GUI ("OpenGUI"),
MODIFY ("Modify"),
SNEAK_THROUGH ("SneakThrough"),
;
public final String unlocalizedName;
// cached values
public static final int length;
private static final HashMap<Integer, PermissionNode> ID_MAP = new HashMap<>();
static {
length = PermissionNode.values().length;
for (PermissionNode permissionNode : values()) {
ID_MAP.put(permissionNode.ordinal(), permissionNode);
}
}
PermissionNode(String unlocalizedName) {
this.unlocalizedName = unlocalizedName;
}
public static PermissionNode get(final int id) {
return ID_MAP.get(id);
}
}

View file

@ -2,8 +2,9 @@ package cr0s.warpdrive.item;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IShapeProvider;
import cr0s.warpdrive.data.ComponentType;
import cr0s.warpdrive.data.ForceFieldShapeType;
import cr0s.warpdrive.data.ForceFieldSetup;
import cr0s.warpdrive.data.EnumForceFieldShape;
import cr0s.warpdrive.data.VectorI;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
@ -12,25 +13,25 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import net.minecraft.util.StatCollector;
import java.util.List;
import java.util.*;
public class ItemForceFieldShape extends Item implements IShapeProvider {
private IIcon[] icons;
private final IIcon[] icons;
private static ItemStack[] itemStackCache;
public ItemForceFieldShape() {
super();
setHasSubtypes(true);
setUnlocalizedName("warpdrive.forcefield.shapeProvider");
setUnlocalizedName("warpdrive.forcefield.shape");
setCreativeTab(WarpDrive.creativeTabWarpDrive);
icons = new IIcon[ForceFieldShapeType.length];
itemStackCache = new ItemStack[ComponentType.length];
icons = new IIcon[EnumForceFieldShape.length];
itemStackCache = new ItemStack[EnumForceFieldShape.length];
}
public static ItemStack getItemStack(ComponentType componentType) {
if (componentType != null) {
int damage = componentType.ordinal();
public static ItemStack getItemStack(EnumForceFieldShape enumForceFieldShape) {
if (enumForceFieldShape != null) {
int damage = enumForceFieldShape.ordinal();
if (itemStackCache[damage] == null) {
itemStackCache[damage] = new ItemStack(WarpDrive.itemComponent, 1, damage);
}
@ -39,29 +40,29 @@ public class ItemForceFieldShape extends Item implements IShapeProvider {
return null;
}
public static ItemStack getItemStackNoCache(ComponentType componentType, int amount) {
return new ItemStack(WarpDrive.itemComponent, amount, componentType.ordinal());
public static ItemStack getItemStackNoCache(EnumForceFieldShape enumForceFieldShape, int amount) {
return new ItemStack(WarpDrive.itemForceFieldShape, amount, enumForceFieldShape.ordinal());
}
@Override
public void registerIcons(IIconRegister par1IconRegister) {
for(ComponentType componentType : ComponentType.values()) {
icons[componentType.ordinal()] = par1IconRegister.registerIcon("warpdrive:component" + componentType.unlocalizedName);
for(EnumForceFieldShape enumForceFieldShape : EnumForceFieldShape.values()) {
icons[enumForceFieldShape.ordinal()] = par1IconRegister.registerIcon("warpdrive:forcefield/shape_" + enumForceFieldShape.unlocalizedName);
}
}
@Override
public String getUnlocalizedName(ItemStack itemStack) {
int damage = itemStack.getItemDamage();
if (damage >= 0 && damage < ComponentType.length) {
return "item.warpdrive.crafting." + ComponentType.get(damage).unlocalizedName;
if (damage >= 0 && damage < EnumForceFieldShape.length) {
return getUnlocalizedName() + "." + EnumForceFieldShape.get(damage).unlocalizedName;
}
return getUnlocalizedName();
}
@Override
public IIcon getIconFromDamage(int damage) {
if (damage >= 0 && damage < ComponentType.length) {
if (damage >= 0 && damage < EnumForceFieldShape.length) {
return icons[damage];
}
return icons[0];
@ -69,51 +70,163 @@ public class ItemForceFieldShape extends Item implements IShapeProvider {
@Override
public void getSubItems(Item item, CreativeTabs creativeTab, List list) {
for(ComponentType componentType : ComponentType.values()) {
list.add(new ItemStack(item, 1, componentType.ordinal()));
for(EnumForceFieldShape enumForceFieldShape : EnumForceFieldShape.values()) {
list.add(new ItemStack(item, 1, enumForceFieldShape.ordinal()));
}
}
// For empty air canister
@Override
public boolean canContainAir(ItemStack itemStack) {
return (itemStack.getItem() instanceof ItemForceFieldShape && itemStack.getItemDamage() == ComponentType.AIR_CANISTER.ordinal());
}
@Override
public boolean containsAir(ItemStack itemStack) {
return false;
}
@Override
public ItemStack fullDrop(ItemStack itemStack) {
if (canContainAir(itemStack)) {
return WarpDrive.itemAirCanisterFull.fullDrop(itemStack);
}
return null;
}
@Override
public ItemStack emptyDrop(ItemStack itemStack) {
if (canContainAir(itemStack)) {
return WarpDrive.itemAirCanisterFull.emptyDrop(itemStack);
}
return null;
}
@Override
public void addInformation(ItemStack itemStack, EntityPlayer entityPlayer, List list, boolean advancedItemTooltips) {
super.addInformation(itemStack, entityPlayer, list, advancedItemTooltips);
String tooltip = "";
switch (ComponentType.get(itemStack.getItemDamage())) {
case AIR_CANISTER:
tooltip += StatCollector.translateToLocalFormatted("item.warpdrive.crafting.AirCanisterEmpty.tooltip");
break;
default:
break;
String tooltipName1 = getUnlocalizedName(itemStack) + ".tooltip";
if (StatCollector.canTranslate(tooltipName1)) {
WarpDrive.addTooltip(list, StatCollector.translateToLocalFormatted(tooltipName1));
}
WarpDrive.addTooltip(list, tooltip);
String tooltipName2 = getUnlocalizedName() + ".tooltip";
if ((!tooltipName1.equals(tooltipName2)) && StatCollector.canTranslate(tooltipName2)) {
WarpDrive.addTooltip(list, StatCollector.translateToLocalFormatted(tooltipName2));
}
}
@Override
public Map<VectorI, Boolean> getVertexes(ForceFieldSetup forceFieldSetup) {
VectorI vScale = forceFieldSetup.vMax.clone().translateBack(forceFieldSetup.vMin);
Map<VectorI, Boolean> mapVertexes = new HashMap<>(vScale.x * vScale.y * vScale.z);
int radius;
int thickness;
int radiusInterior2;
int radiusPerimeter2;
VectorI vCenter;
switch(forceFieldSetup.enumForceFieldShape) {
case SPHERE:
radius = forceFieldSetup.vMax.y;
radiusInterior2 = Math.round((radius - forceFieldSetup.thickness) * (radius - forceFieldSetup.thickness));
radiusPerimeter2 = Math.round((radius + forceFieldSetup.thickness) * (radius + forceFieldSetup.thickness));
vCenter = new VectorI(0, 0, 0);
for (int y = forceFieldSetup.vMin.y; y <= forceFieldSetup.vMax.y; y++) {
int y2 = (y - vCenter.y) * (y - vCenter.y);
for (int x = forceFieldSetup.vMin.x; x <= forceFieldSetup.vMax.x; x++) {
int x2 = (x - vCenter.x) * (x - vCenter.x);
for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) {
int z2 = (z - vCenter.z) * (z - vCenter.z);
if (x2 + y2 + z2 <= radiusPerimeter2) {
mapVertexes.put(new VectorI(x, y, z), x2 + y2 + z2 >= radiusInterior2);
}
}
}
}
break;
case CYLINDER_H:
radius = Math.round((forceFieldSetup.vMax.y + forceFieldSetup.vMax.z) / 2);
radiusInterior2 = Math.round((radius - forceFieldSetup.thickness) * (radius - forceFieldSetup.thickness));
radiusPerimeter2 = Math.round((radius + forceFieldSetup.thickness) * (radius + forceFieldSetup.thickness));
vCenter = new VectorI(0, 0, 0);
for (int y = forceFieldSetup.vMin.y; y <= forceFieldSetup.vMax.y; y++) {
int y2 = (y - vCenter.y) * (y - vCenter.y);
for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) {
int z2 = (z - vCenter.z) * (z - vCenter.z);
if (y2 + z2 <= radiusPerimeter2) {
boolean isPerimeter = y2 + z2 >= radiusInterior2;
for (int x = forceFieldSetup.vMin.x; x <= forceFieldSetup.vMax.x; x++) {
mapVertexes.put(new VectorI(x, y, z), isPerimeter);
}
}
}
}
break;
case CYLINDER_V:
radius = Math.round((forceFieldSetup.vMax.x + forceFieldSetup.vMax.y) / 2);
radiusInterior2 = Math.round((radius - forceFieldSetup.thickness) * (radius - forceFieldSetup.thickness));
radiusPerimeter2 = Math.round((radius + forceFieldSetup.thickness) * (radius + forceFieldSetup.thickness));
vCenter = new VectorI(0, 0, 0);
for (int x = forceFieldSetup.vMin.x; x <= forceFieldSetup.vMax.x; x++) {
int x2 = (x - vCenter.x) * (x - vCenter.x);
for (int y = forceFieldSetup.vMin.y; y <= forceFieldSetup.vMax.y; y++) {
int y2 = (y - vCenter.y) * (y - vCenter.y);
if (x2 + y2 <= radiusPerimeter2) {
boolean isPerimeter = x2 + y2 >= radiusInterior2;
for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) {
mapVertexes.put(new VectorI(x, y, z), isPerimeter);
}
}
}
}
break;
case TUBE:
radius = Math.round((forceFieldSetup.vMax.x + forceFieldSetup.vMax.z) / 2);
radiusInterior2 = Math.round((radius - forceFieldSetup.thickness) * (radius - forceFieldSetup.thickness));
radiusPerimeter2 = Math.round((radius + forceFieldSetup.thickness) * (radius + forceFieldSetup.thickness));
vCenter = new VectorI(0, 0, 0);
for (int x = forceFieldSetup.vMin.x; x <= forceFieldSetup.vMax.x; x++) {
int x2 = (x - vCenter.x) * (x - vCenter.x);
for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) {
int z2 = (z - vCenter.z) * (z - vCenter.z);
if (x2 + z2 <= radiusPerimeter2) {
boolean isPerimeter = x2 + z2 >= radiusInterior2;
for (int y = forceFieldSetup.vMin.y; y <= forceFieldSetup.vMax.y; y++) {
mapVertexes.put(new VectorI(x, y, z), isPerimeter);
}
}
}
}
break;
case CUBE:
thickness = Math.round(forceFieldSetup.thickness);
for (int y = forceFieldSetup.vMin.y; y <= forceFieldSetup.vMax.y; y++) {
boolean yFace = Math.abs(y - forceFieldSetup.vMin.y) <= thickness
|| Math.abs(y - forceFieldSetup.vMax.y) <= thickness;
for (int x = forceFieldSetup.vMin.x; x <= forceFieldSetup.vMax.x; x++) {
boolean xFace = Math.abs(x - forceFieldSetup.vMin.x) <= thickness
|| Math.abs(x - forceFieldSetup.vMax.x) <= thickness;
for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) {
boolean zFace = Math.abs(z - forceFieldSetup.vMin.z) <= thickness
|| Math.abs(z - forceFieldSetup.vMax.z) <= thickness;
mapVertexes.put(new VectorI(x, y, z), xFace || yFace || zFace);
}
}
}
break;
case PLANE:
thickness = Math.round(forceFieldSetup.thickness);
for (int y = forceFieldSetup.vMin.y; y <= forceFieldSetup.vMax.y; y++) {
boolean yFace = Math.abs(y - forceFieldSetup.vMin.y) <= thickness
|| Math.abs(y - forceFieldSetup.vMax.y) <= thickness;
for (int x = forceFieldSetup.vMin.x; x <= forceFieldSetup.vMax.x; x++) {
for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) {
mapVertexes.put(new VectorI(x, y, z), yFace);
}
}
}
break;
case TUNNEL:
thickness = Math.round(forceFieldSetup.thickness);
for (int y = forceFieldSetup.vMin.y; y <= forceFieldSetup.vMax.y; y++) {
for (int x = forceFieldSetup.vMin.x; x <= forceFieldSetup.vMax.x; x++) {
boolean xFace = Math.abs(x - forceFieldSetup.vMin.x) <= thickness
|| Math.abs(x - forceFieldSetup.vMax.x) <= thickness;
for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) {
boolean isPerimeter = xFace
|| Math.abs(z - forceFieldSetup.vMin.z) <= thickness
|| Math.abs(z - forceFieldSetup.vMax.z) <= thickness;
mapVertexes.put(new VectorI(x, y, z), isPerimeter);
}
}
}
break;
default:
break;
}
return mapVertexes;
}
}

View file

@ -0,0 +1,114 @@
package cr0s.warpdrive.render;
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
import cr0s.warpdrive.block.forcefield.TileEntityForceField;
import cr0s.warpdrive.data.ForceFieldSetup;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.IBlockAccess;
// wrapper to native classes to renderId is non-zero so we don't render faces when player camera is inside the block
public class RenderBlockForceField implements ISimpleBlockRenderingHandler {
public static int renderId = 0;
public static RenderBlockForceField instance = new RenderBlockForceField();
@Override
public void renderInventoryBlock(Block block, int metadata, int modelId, RenderBlocks renderer) {
// not supposed to happen
}
@Override
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {
TileEntity tileEntity = world.getTileEntity(x, y, z);
if (!(tileEntity instanceof TileEntityForceField)) {
return false;
}
ForceFieldSetup forceFieldSetup = ((TileEntityForceField)tileEntity).getForceFieldSetup();
if (forceFieldSetup == null) {
return false;
}
int renderType = -1;
Block blockCamouflage = forceFieldSetup.getCamouflageBlock();
if (blockCamouflage != null) {
renderType = blockCamouflage.getRenderType();
}
if (renderType >= 0) {
try {
if (blockCamouflage != null) {
renderer.setRenderBoundsFromBlock(blockCamouflage);
}
switch (renderType) {
case 1 :
renderer.renderCrossedSquares(block, x, y, z);
break;
case 4 :
renderer.renderBlockLiquid(block, x, y, z);
break;
case 5 :
renderer.renderBlockRedstoneWire(block, x, y, z);
break;
case 6 :
renderer.renderBlockCrops(block, x, y, z);
break;
case 7 :
renderer.renderBlockDoor(block, x, y, z);
break;
case 12 :
renderer.renderBlockLever(block, x, y, z);
break;
case 13 :
renderer.renderBlockCactus(block, x, y, z);
break;
case 14 :
renderer.renderBlockBed(block, x, y, z);
break;
case 16 :
renderer.renderPistonBase(block, x, y, z, false);
break;
case 17 :
renderer.renderPistonExtension(block, x, y, z, true);
break;
case 20 :
renderer.renderBlockVine(block, x, y, z);
break;
case 23 :
renderer.renderBlockLilyPad(block, x, y, z);
break;
case 29 :
renderer.renderBlockTripWireSource(block, x, y, z);
break;
case 30 :
renderer.renderBlockTripWire(block, x, y, z);
break;
case 31 :
renderer.renderBlockLog(block, x, y, z);
break;
case 39 :
renderer.renderBlockQuartz(block, x, y, z);
break;
default:
return false;
}
} catch(Exception exception) {
renderer.renderBlockAsItem(blockCamouflage, forceFieldSetup.itemStackCamouflage.getItemDamage(), 1);
}
return true;
}
return renderer.renderStandardBlock(block, x, y, z);
}
@Override
public boolean shouldRender3DInInventory(int modelId) {
return true;
}
@Override
public int getRenderId() {
return renderId;
}
}

View file

@ -32,10 +32,20 @@ item.warpdrive.crafting.BoneCharcoal.name=Bone Charcoal
item.warpdrive.crafting.ActivatedCarbon.name=Activated Carbon
item.warpdrive.crafting.LaserMediumEmpty.name=Laser Medium (empty)
item.warpdrive.energy.IC2reactorLaserFocus.name=IC2 Reactor Laser Focus
item.warpdrive.armor.AirCanisterFull.name=Air Canister
item.warpdrive.armor.Helmet.name=Warp Helmet
item.warpdrive.energy.IC2reactorLaserFocus.name=IC2 Reactor Laser Focus
item.warpdrive.forcefield.shape.none.name=No shape
item.warpdrive.forcefield.shape.sphere.name=Sphere shape
item.warpdrive.forcefield.shape.cylinder_h.name=Horizontal cylinder shape
item.warpdrive.forcefield.shape.cylinder_v.name=Vertical cylinder shape
item.warpdrive.forcefield.shape.cube.name=Cube shape
item.warpdrive.forcefield.shape.plane.name=Plane shape
item.warpdrive.forcefield.shape.tube.name=Tube shape
item.warpdrive.forcefield.shape.tunnel.name=Tunnel shape
item.warpdrive.upgrade.Power.name=Power Upgrade
item.warpdrive.upgrade.Speed.name=Speed Upgrade
item.warpdrive.upgrade.Range.name=Range Upgrade
@ -96,6 +106,26 @@ tile.warpdrive.energy.EnanReactorLaser.name=Enantiomorphic Reactor Stabilization
tile.warpdrive.energy.EnergyBank.name=Anuic Energy Bank
tile.warpdrive.energy.IC2ReactorLaserMonitor.name=IC2 Reactor Laser Monitor
tile.warpdrive.forcefield.block.name=Forcefield
tile.warpdrive.forcefield.projector1.name=Basic Forcefield Projector
tile.warpdrive.forcefield.projector2.name=Advanced Forcefield Projector
tile.warpdrive.forcefield.projector3.name=Superior Forcefield Projector
tile.warpdrive.forcefield.upgrade.none.name=No upgrade
tile.warpdrive.forcefield.upgrade.break.name=Block breaker upgrade
tile.warpdrive.forcefield.upgrade.camouflage.name=Camouflage upgrade
tile.warpdrive.forcefield.upgrade.cool.name=Cooling upgrade
tile.warpdrive.forcefield.upgrade.fusion.name=Fusion upgrade
tile.warpdrive.forcefield.upgrade.mute.name=Muting upgrade
tile.warpdrive.forcefield.upgrade.range .name=Range upgrade
tile.warpdrive.forcefield.upgrade.rotation.name=Rotation upgrade
tile.warpdrive.forcefield.upgrade.shock.name=Shock upgrade
tile.warpdrive.forcefield.upgrade.speed.name=Speed upgrade
tile.warpdrive.forcefield.upgrade.stabilize.name=Stabilization upgrade
tile.warpdrive.forcefield.upgrade.thickness.name=Thickness upgrade
tile.warpdrive.forcefield.upgrade.translation.name=Translation upgrade
tile.warpdrive.forcefield.upgrade.warm.name=Heating upgrade
tile.warpdrive.movement.Lift.name=Lift
tile.warpdrive.movement.ShipController.name=Ship Controller
tile.warpdrive.movement.ShipCore.name=Ship Core