Add the CE quarries, a port of CE's improved BuildCraft quarries
Port CE's three quarries from BuildCraft 3.1.5 (Minecraft 1.2.5) to BuildCraft 7.1. TileCEQuarry follows BuildCraft 7's TileQuarry, whose state is private, with CE's changes: - Twice the battery, so the arm moves faster. - A configurable default area (64x64), mirrored when placed while sneaking, and a configurable lowest Y level (5). - Lava no longer blocks the columns below it. - The search continues from the last target and moves past each one once done, so fluids flowing back in do not hold the arm in place. - No chunk loading. - CEQ-3 removes lava sources; CEQ-4 turns fluids around the drill into glass and accepts five times the input. Soft blocks are checked without BuildCraft's cache, which is stale in chunks without players. The arm is a copy of EntityMechanicalArm, which only works with BuildCraft's own quarry. The recipes keep CE's layout with BuildCraft 7 items; GateRecipe checks the gates' material and logic, which ShapedOreRecipe ignores. Textures come from CE. Also give the EMC Builder a default.png for its back, sides and bottom instead of substituting the bottom icon in code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No files matched your search
@@ -13,9 +13,30 @@ BuildCraft の Builder を拡張し、建築に必要な資材を EMC で支払
|
||||
- GUI の EMC スロットにアイテムを入れると、Transmutation Table と同様に EMC に変換されます。
|
||||
- レシピ: Builder + Transmutation Table(不定形)
|
||||
|
||||
### CE クアーリー
|
||||
|
||||
BuildCraft の Quarry の強化版です。動作は BuildCraft 7 の Quarry と同じく、フレームを建ててからアームで掘り、掘ったアイテムを隣接するチェストやパイプに送ります。
|
||||
|
||||
- **採掘強化型クアーリー(CEQ-2)**: バッテリーが BuildCraft の Quarry の 2 倍で、その分アームが速く動きます。
|
||||
- マーカーがなければ、本体の後ろ側を 64x64 の範囲で掘ります。スニークしながら置くと、範囲が左右反転します。
|
||||
- y=5 で止まるので、岩盤層は荒らしません。
|
||||
- 溶岩はスキップするだけで、その下の列も掘ります。
|
||||
- 前回の位置から探索を続けます。レンチで右クリックすると、掘り終えた後でも最初から掘り直します。
|
||||
- チャンクロード機能はありません。
|
||||
- **溶岩除去型クアーリー(CEQ-3)**: CEQ-2 の機能に加えて、範囲内の溶岩源を除去します。
|
||||
- **液体対策型クアーリー(CEQ-4)**: CEQ-3 の機能に加えて、アームに隣接する水・溶岩・オイルなどの液体をガラスに変えながら掘ります。受電量は 5 倍です。
|
||||
|
||||
レシピ(CE と同じ配置で、素材を BuildCraft 7 のものに置き換えています):
|
||||
|
||||
- CEQ-2: 上段 鉄歯車・レッドストーン・鉄歯車 / 中段 金歯車・鉄歯車・金歯車 / 下段 ダイヤ歯車・Quarry・ダイヤ歯車
|
||||
- CEQ-3: 上段 エンダーパール・タンク・エンダーパール / 中段 ダイヤチップセット・ポンプ・ダイヤチップセット / 下段 ダイヤ AND ゲート・CEQ-2・ダイヤ AND ゲート
|
||||
- CEQ-4: 上段 ガラス×3 / 中段 水バケツ・CEQ-3・溶岩バケツ / 下段 タンク・鉄 AND ゲート・タンク
|
||||
|
||||
`config/cemodern.cfg` の `quarry` で、初期範囲の大きさ(`defaultArea`)、本体の位置(`defaultPosition`)、掘る深さ(`miningYmin`)を変えられます。
|
||||
|
||||
## 必要な Mod
|
||||
|
||||
- BuildCraft 7.1.x(Builders)
|
||||
- BuildCraft 7.1.x(Builders, Factory, Silicon, Transport)
|
||||
- ProjectE
|
||||
|
||||
## ビルド
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package net.kanawo.cemodern;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
|
||||
/** Settings read from config/cemodern.cfg. */
|
||||
public final class CEConfig {
|
||||
|
||||
private static final String CATEGORY_QUARRY = "quarry";
|
||||
|
||||
/** Side length of the area a CE quarry digs when no marker is next to it. */
|
||||
public static int quarryDefaultSize = 64;
|
||||
/** Where the quarry sits along the edge of its default area, counted from one corner. */
|
||||
public static int quarryDefaultPosition = 0;
|
||||
/** Lowest Y level CE quarries dig down to. Bedrock is at 0 to 4. */
|
||||
public static int quarryMinY = 5;
|
||||
|
||||
private CEConfig() {}
|
||||
|
||||
public static void load(File file) {
|
||||
Configuration config = new Configuration(file);
|
||||
|
||||
quarryDefaultSize = config.getInt(
|
||||
"defaultArea",
|
||||
CATEGORY_QUARRY,
|
||||
quarryDefaultSize,
|
||||
3,
|
||||
130,
|
||||
"Side length of the area a CE quarry digs when no marker is next to it.");
|
||||
quarryDefaultPosition = config.getInt(
|
||||
"defaultPosition",
|
||||
CATEGORY_QUARRY,
|
||||
quarryDefaultPosition,
|
||||
0,
|
||||
129,
|
||||
"Where the quarry sits along the edge of its default area, counted from one corner."
|
||||
+ " Sneak while placing it to count from the other corner.");
|
||||
quarryMinY = config.getInt(
|
||||
"miningYmin",
|
||||
CATEGORY_QUARRY,
|
||||
quarryMinY,
|
||||
0,
|
||||
255,
|
||||
"Lowest Y level CE quarries dig down to. Bedrock is at 0 to 4.");
|
||||
|
||||
quarryDefaultPosition = Math.min(quarryDefaultPosition, quarryDefaultSize - 1);
|
||||
|
||||
if (config.hasChanged()) {
|
||||
config.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,8 @@ import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
version = Tags.VERSION,
|
||||
name = "CE-modern",
|
||||
acceptedMinecraftVersions = "[1.7.10]",
|
||||
dependencies = "required-after:BuildCraft|Builders;required-after:ProjectE")
|
||||
dependencies = "required-after:BuildCraft|Builders;required-after:BuildCraft|Factory;"
|
||||
+ "required-after:BuildCraft|Silicon;required-after:BuildCraft|Transport;required-after:ProjectE")
|
||||
public class CEModern {
|
||||
|
||||
public static final String MODID = "cemodern";
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package net.kanawo.cemodern;
|
||||
|
||||
import net.kanawo.cemodern.entity.EntityCEQuarryArm;
|
||||
import net.kanawo.cemodern.tile.TileCEQuarry;
|
||||
import net.kanawo.cemodern.tile.TileEMCBuilder;
|
||||
|
||||
import buildcraft.core.lib.render.RenderVoid;
|
||||
import buildcraft.core.render.RenderBuilder;
|
||||
import cpw.mods.fml.client.registry.ClientRegistry;
|
||||
import cpw.mods.fml.client.registry.RenderingRegistry;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
|
||||
public class ClientProxy extends CommonProxy {
|
||||
@@ -15,5 +19,12 @@ public class ClientProxy extends CommonProxy {
|
||||
// The Builder's own renderer (RenderBuilderTile) also draws BuildCraft's lit top while building. Its base
|
||||
// renderer draws only the area box, path lasers and flying items.
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEMCBuilder.class, new RenderBuilder());
|
||||
|
||||
// The quarries draw their area box and the frames flying into place. The arm is drawn by its parts.
|
||||
RenderBuilder quarryRenderer = new RenderBuilder();
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileCEQuarry.Fast.class, quarryRenderer);
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileCEQuarry.Lava.class, quarryRenderer);
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileCEQuarry.Fluid.class, quarryRenderer);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityCEQuarryArm.class, new RenderVoid());
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,26 @@
|
||||
package net.kanawo.cemodern;
|
||||
|
||||
import net.kanawo.cemodern.block.BlockCEQuarry;
|
||||
import net.kanawo.cemodern.block.BlockEMCBuilder;
|
||||
import net.kanawo.cemodern.block.SchematicEMCBuilder;
|
||||
import net.kanawo.cemodern.gui.GuiHandler;
|
||||
import net.kanawo.cemodern.recipe.GateRecipe;
|
||||
import net.kanawo.cemodern.tile.QuarryType;
|
||||
import net.kanawo.cemodern.tile.TileCEQuarry;
|
||||
import net.kanawo.cemodern.tile.TileEMCBuilder;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.oredict.RecipeSorter;
|
||||
import net.minecraftforge.oredict.RecipeSorter.Category;
|
||||
import net.minecraftforge.oredict.ShapedOreRecipe;
|
||||
|
||||
import buildcraft.BuildCraftBuilders;
|
||||
import buildcraft.BuildCraftFactory;
|
||||
import buildcraft.api.blueprints.BuilderAPI;
|
||||
import buildcraft.builders.schematics.SchematicBuilderLike;
|
||||
import buildcraft.transport.gates.GateDefinition.GateLogic;
|
||||
import buildcraft.transport.gates.GateDefinition.GateMaterial;
|
||||
import buildcraft.transport.gates.ItemGate;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.network.NetworkRegistry;
|
||||
@@ -17,21 +30,100 @@ import moze_intel.projecte.gameObjs.ObjHandler;
|
||||
public class CommonProxy {
|
||||
|
||||
public static BlockEMCBuilder emcBuilderBlock;
|
||||
public static BlockCEQuarry quarry2Block;
|
||||
public static BlockCEQuarry quarry3Block;
|
||||
public static BlockCEQuarry quarry4Block;
|
||||
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
CEConfig.load(event.getSuggestedConfigurationFile());
|
||||
|
||||
emcBuilderBlock = new BlockEMCBuilder();
|
||||
GameRegistry.registerBlock(emcBuilderBlock, "emcBuilder");
|
||||
GameRegistry.registerTileEntity(TileEMCBuilder.class, CEModern.MODID + ":EMCBuilder");
|
||||
|
||||
quarry2Block = registerQuarry(QuarryType.FAST, TileCEQuarry.Fast.class);
|
||||
quarry3Block = registerQuarry(QuarryType.LAVA, TileCEQuarry.Lava.class);
|
||||
quarry4Block = registerQuarry(QuarryType.FLUID, TileCEQuarry.Fluid.class);
|
||||
}
|
||||
|
||||
private static BlockCEQuarry registerQuarry(QuarryType type, Class<? extends TileCEQuarry> tile) {
|
||||
BlockCEQuarry block = new BlockCEQuarry(type);
|
||||
GameRegistry.registerBlock(block, type.name);
|
||||
GameRegistry.registerTileEntity(tile, CEModern.MODID + ":" + type.name);
|
||||
return block;
|
||||
}
|
||||
|
||||
public void init(FMLInitializationEvent event) {
|
||||
NetworkRegistry.INSTANCE.registerGuiHandler(CEModern.instance, new GuiHandler());
|
||||
|
||||
BuilderAPI.schematicRegistry.registerSchematicBlock(emcBuilderBlock, SchematicEMCBuilder.class);
|
||||
BuilderAPI.schematicRegistry.registerSchematicBlock(quarry2Block, SchematicBuilderLike.class);
|
||||
BuilderAPI.schematicRegistry.registerSchematicBlock(quarry3Block, SchematicBuilderLike.class);
|
||||
BuilderAPI.schematicRegistry.registerSchematicBlock(quarry4Block, SchematicBuilderLike.class);
|
||||
|
||||
GameRegistry.addShapelessRecipe(
|
||||
new ItemStack(emcBuilderBlock),
|
||||
BuildCraftBuilders.builderBlock,
|
||||
ObjHandler.transmuteStone);
|
||||
|
||||
RecipeSorter.register(CEModern.MODID + ":gate", GateRecipe.class, Category.SHAPED, "after:forge:shapedore");
|
||||
|
||||
// CE's recipes, with BuildCraft 7's items in place of BuildCraft 3's.
|
||||
GameRegistry.addRecipe(
|
||||
new ShapedOreRecipe(
|
||||
new ItemStack(quarry2Block),
|
||||
"iri",
|
||||
"gig",
|
||||
"dqd",
|
||||
'r',
|
||||
"dustRedstone",
|
||||
'i',
|
||||
"gearIron",
|
||||
'g',
|
||||
"gearGold",
|
||||
'd',
|
||||
"gearDiamond",
|
||||
'q',
|
||||
BuildCraftBuilders.quarryBlock));
|
||||
GameRegistry.addRecipe(
|
||||
new GateRecipe(
|
||||
new ItemStack(quarry3Block),
|
||||
GateMaterial.DIAMOND,
|
||||
GateLogic.AND,
|
||||
"ete",
|
||||
"cpc",
|
||||
"gqg",
|
||||
'e',
|
||||
Items.ender_pearl,
|
||||
't',
|
||||
BuildCraftFactory.tankBlock,
|
||||
'p',
|
||||
BuildCraftFactory.pumpBlock,
|
||||
'q',
|
||||
quarry2Block,
|
||||
'c',
|
||||
"chipsetDiamond",
|
||||
'g',
|
||||
ItemGate.makeGateItem(GateMaterial.DIAMOND, GateLogic.AND)));
|
||||
GameRegistry.addRecipe(
|
||||
new GateRecipe(
|
||||
new ItemStack(quarry4Block),
|
||||
GateMaterial.IRON,
|
||||
GateLogic.AND,
|
||||
"ggg",
|
||||
"wql",
|
||||
"tit",
|
||||
'g',
|
||||
"blockGlass",
|
||||
'w',
|
||||
Items.water_bucket,
|
||||
'l',
|
||||
Items.lava_bucket,
|
||||
'q',
|
||||
quarry3Block,
|
||||
't',
|
||||
BuildCraftFactory.tankBlock,
|
||||
'i',
|
||||
ItemGate.makeGateItem(GateMaterial.IRON, GateLogic.AND)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package net.kanawo.cemodern.block;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import net.kanawo.cemodern.CEModern;
|
||||
import net.kanawo.cemodern.tile.QuarryType;
|
||||
import net.kanawo.cemodern.tile.TileCEQuarry;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IIconRegister;
|
||||
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.world.World;
|
||||
|
||||
import buildcraft.BuildCraftBuilders;
|
||||
import buildcraft.api.tools.IToolWrench;
|
||||
import buildcraft.core.lib.block.BlockBuildCraft;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
/**
|
||||
* A CE quarry. Like BuildCraft's quarry it faces away from the placer, digs the area behind it, restarts when
|
||||
* wrenched, and takes its frame with it when broken.
|
||||
* <p>
|
||||
* Textures are looked up as textures/blocks/{quarry2,quarry3,quarry4}/{front,top,side}.png. The side texture is
|
||||
* also used for the back and the bottom.
|
||||
*/
|
||||
public class BlockCEQuarry extends BlockBuildCraft {
|
||||
|
||||
public final QuarryType type;
|
||||
|
||||
public BlockCEQuarry(QuarryType type) {
|
||||
super(Material.iron);
|
||||
this.type = type;
|
||||
|
||||
setHardness(10F);
|
||||
setResistance(10F);
|
||||
setStepSound(soundTypeAnvil);
|
||||
setRotatable(true);
|
||||
setBlockName("ce" + Character.toUpperCase(type.name.charAt(0)) + type.name.substring(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createNewTileEntity(World world, int metadata) {
|
||||
return type.createTile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the icons directly. BlockBuildCraft's lookup would fall back to a missing "default" texture for the
|
||||
* bottom, which has no texture of its own.
|
||||
*/
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void registerBlockIcons(IIconRegister register) {
|
||||
String prefix = CEModern.MODID + ":" + type.name + "/";
|
||||
IIcon side = register.registerIcon(prefix + "side");
|
||||
|
||||
// Indexed by side: bottom, top, front, back, left, right.
|
||||
icons = new IIcon[16][];
|
||||
icons[0] = new IIcon[] { side, register.registerIcon(prefix + "top"), register.registerIcon(prefix + "front"),
|
||||
side, side, side };
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<ItemStack> getDrops(World world, int x, int y, int z, int metadata, int fortune) {
|
||||
if (BuildCraftBuilders.quarryOneTimeUse) {
|
||||
return new ArrayList<ItemStack>();
|
||||
}
|
||||
|
||||
return super.getDrops(world, x, y, z, metadata, fortune);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void breakBlock(World world, int x, int y, int z, Block block, int metadata) {
|
||||
if (world.isRemote) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildCraftBuilders.frameBlock.removeNeighboringFrames(world, x, y, z);
|
||||
|
||||
super.breakBlock(world, x, y, z, block, metadata);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX,
|
||||
float hitY, float hitZ) {
|
||||
if (super.onBlockActivated(world, x, y, z, player, side, hitX, hitY, hitZ)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.isSneaking()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Restart the quarry if it is a wrench.
|
||||
Item equipped = player.getCurrentEquippedItem() != null ? player.getCurrentEquippedItem()
|
||||
.getItem() : null;
|
||||
TileEntity tile = world.getTileEntity(x, y, z);
|
||||
if (tile instanceof TileCEQuarry && equipped instanceof IToolWrench
|
||||
&& ((IToolWrench) equipped).canWrench(player, x, y, z)) {
|
||||
((TileCEQuarry) tile).reinitialize();
|
||||
((IToolWrench) equipped).wrenchUsed(player, x, y, z);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package net.kanawo.cemodern.block;
|
||||
import net.kanawo.cemodern.CEModern;
|
||||
import net.kanawo.cemodern.gui.GuiHandler;
|
||||
import net.kanawo.cemodern.tile.TileEMCBuilder;
|
||||
import net.minecraft.client.renderer.texture.IIconRegister;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
@@ -14,7 +13,6 @@ import buildcraft.api.events.BlockInteractionEvent;
|
||||
import buildcraft.builders.BlockBuilder;
|
||||
import buildcraft.builders.ItemConstructionMarker;
|
||||
import buildcraft.core.lib.fluids.TankUtils;
|
||||
import buildcraft.core.lib.utils.ResourceUtils;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
@@ -74,23 +72,13 @@ public class BlockEMCBuilder extends BlockBuilder {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Textures are looked up as textures/blocks/emcbuilderBlock/{top,bottom,front,side,...}.png. */
|
||||
/**
|
||||
* Textures are looked up as textures/blocks/emcbuilderBlock/{top,front,default}.png. default.png covers the faces
|
||||
* without a texture of their own: the back, the left, the right and the bottom.
|
||||
*/
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public String[] getIconBlockNames() {
|
||||
return new String[] { TEXTURE_PREFIX };
|
||||
}
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void registerBlockIcons(IIconRegister register) {
|
||||
super.registerBlockIcons(register);
|
||||
|
||||
// Without bottom.png BlockBuildCraft would fall back to a missing "default" texture. Use the left face
|
||||
// (index 4), which resolves to side.png, instead.
|
||||
String bottom = TEXTURE_PREFIX + "/bottom";
|
||||
if (!ResourceUtils.resourceExists(ResourceUtils.iconToResourcePath(register, bottom))) {
|
||||
icons[0][0] = icons[0][4];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package net.kanawo.cemodern.entity;
|
||||
|
||||
import net.kanawo.cemodern.tile.TileCEQuarry;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import buildcraft.builders.BuilderProxy;
|
||||
import buildcraft.core.lib.EntityBlock;
|
||||
|
||||
/**
|
||||
* The mechanical arm of a CE quarry, the same as BuildCraft's {@code EntityMechanicalArm}, which only works with
|
||||
* BuildCraft's own quarry tile.
|
||||
* <p>
|
||||
* It only draws the arm: three beams and the drill head, made of BuildCraft's {@link EntityBlock}s. The quarry spawns
|
||||
* one on each side and moves its head. The entity is not registered, so it is neither sent to clients nor saved.
|
||||
*/
|
||||
public class EntityCEQuarryArm extends Entity {
|
||||
|
||||
private TileCEQuarry parent;
|
||||
|
||||
private double armSizeX;
|
||||
private double armSizeZ;
|
||||
private double xRoot;
|
||||
private double yRoot;
|
||||
private double zRoot;
|
||||
|
||||
private int headX, headY, headZ;
|
||||
private EntityBlock xArm, yArm, zArm, head;
|
||||
|
||||
public EntityCEQuarryArm(World world) {
|
||||
super(world);
|
||||
makeParts(world);
|
||||
noClip = true;
|
||||
}
|
||||
|
||||
public EntityCEQuarryArm(World world, double x, double y, double z, double width, double height,
|
||||
TileCEQuarry parent) {
|
||||
this(world);
|
||||
setPositionAndRotation(parent.xCoord, parent.yCoord, parent.zCoord, 0, 0);
|
||||
this.xRoot = x;
|
||||
this.yRoot = y;
|
||||
this.zRoot = z;
|
||||
this.motionX = 0.0;
|
||||
this.motionY = 0.0;
|
||||
this.motionZ = 0.0;
|
||||
setArmSize(width, height);
|
||||
setHead(x, y - 2, z);
|
||||
this.parent = parent;
|
||||
parent.setArm(this);
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
public void setHead(double x, double y, double z) {
|
||||
this.headX = (int) (x * 32D);
|
||||
this.headY = (int) (y * 32D);
|
||||
this.headZ = (int) (z * 32D);
|
||||
}
|
||||
|
||||
private void setArmSize(double x, double z) {
|
||||
armSizeX = x;
|
||||
xArm.iSize = x;
|
||||
armSizeZ = z;
|
||||
zArm.kSize = z;
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
private void makeParts(World world) {
|
||||
xArm = BuilderProxy.proxy.newDrill(world, 0, 0, 0, 1, 0.5, 0.5, true);
|
||||
yArm = BuilderProxy.proxy.newDrill(world, 0, 0, 0, 0.5, 1, 0.5, false);
|
||||
zArm = BuilderProxy.proxy.newDrill(world, 0, 0, 0, 0.5, 0.5, 1, true);
|
||||
|
||||
head = BuilderProxy.proxy.newDrillHead(world, 0, 0, 0, 0.2, 1, 0.2);
|
||||
head.shadowSize = 1.0F;
|
||||
|
||||
world.spawnEntityInWorld(xArm);
|
||||
world.spawnEntityInWorld(yArm);
|
||||
world.spawnEntityInWorld(zArm);
|
||||
world.spawnEntityInWorld(head);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void entityInit() {}
|
||||
|
||||
@Override
|
||||
protected void readEntityFromNBT(NBTTagCompound nbt) {
|
||||
xRoot = nbt.getDouble("xRoot");
|
||||
yRoot = nbt.getDouble("yRoot");
|
||||
zRoot = nbt.getDouble("zRoot");
|
||||
armSizeX = nbt.getDouble("armSizeX");
|
||||
armSizeZ = nbt.getDouble("armSizeZ");
|
||||
setArmSize(armSizeX, armSizeZ);
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeEntityToNBT(NBTTagCompound nbt) {
|
||||
nbt.setDouble("xRoot", xRoot);
|
||||
nbt.setDouble("yRoot", yRoot);
|
||||
nbt.setDouble("zRoot", zRoot);
|
||||
nbt.setDouble("armSizeX", armSizeX);
|
||||
nbt.setDouble("armSizeZ", armSizeZ);
|
||||
}
|
||||
|
||||
private void findAndJoinQuarry() {
|
||||
TileEntity te = worldObj.getTileEntity((int) posX, (int) posY, (int) posZ);
|
||||
if (te instanceof TileCEQuarry) {
|
||||
parent = (TileCEQuarry) te;
|
||||
parent.setArm(this);
|
||||
} else {
|
||||
setDead();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate() {
|
||||
super.onUpdate();
|
||||
updatePosition();
|
||||
|
||||
if (parent == null) {
|
||||
findAndJoinQuarry();
|
||||
}
|
||||
|
||||
if (parent == null) {
|
||||
setDead();
|
||||
}
|
||||
}
|
||||
|
||||
public void updatePosition() {
|
||||
double headPosX = headX / 32D;
|
||||
double headPosY = headY / 32D;
|
||||
double headPosZ = headZ / 32D;
|
||||
xArm.setPosition(xRoot, yRoot, headPosZ + 0.25);
|
||||
yArm.jSize = yRoot - headPosY - 1;
|
||||
yArm.setPosition(headPosX + 0.25, headPosY + 1, headPosZ + 0.25);
|
||||
zArm.setPosition(headPosX + 0.25, yRoot, zRoot);
|
||||
head.setPosition(headPosX + 0.4, headPosY, headPosZ + 0.4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead() {
|
||||
if (worldObj != null && worldObj.isRemote) {
|
||||
xArm.setDead();
|
||||
yArm.setDead();
|
||||
zArm.setDead();
|
||||
head.setDead();
|
||||
}
|
||||
|
||||
super.setDead();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package net.kanawo.cemodern.recipe;
|
||||
|
||||
import net.minecraft.inventory.InventoryCrafting;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.oredict.ShapedOreRecipe;
|
||||
|
||||
import buildcraft.transport.gates.GateDefinition.GateLogic;
|
||||
import buildcraft.transport.gates.GateDefinition.GateMaterial;
|
||||
import buildcraft.transport.gates.ItemGate;
|
||||
|
||||
/**
|
||||
* A shaped recipe whose gates must be of one material and logic. Gates are told apart only by NBT, which
|
||||
* {@link ShapedOreRecipe} ignores, so without this any gate would do. Expansions on the gate are allowed.
|
||||
*/
|
||||
public class GateRecipe extends ShapedOreRecipe {
|
||||
|
||||
private final GateMaterial material;
|
||||
private final GateLogic logic;
|
||||
|
||||
/** The recipe arguments are those of {@link ShapedOreRecipe}; give the gate as {@code ItemGate.makeGateItem}. */
|
||||
public GateRecipe(ItemStack result, GateMaterial material, GateLogic logic, Object... recipe) {
|
||||
super(result, recipe);
|
||||
this.material = material;
|
||||
this.logic = logic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(InventoryCrafting inv, World world) {
|
||||
if (!super.matches(inv, world)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < inv.getSizeInventory(); i++) {
|
||||
ItemStack stack = inv.getStackInSlot(i);
|
||||
if (stack != null && stack.getItem() instanceof ItemGate
|
||||
&& (ItemGate.getMaterial(stack) != material || ItemGate.getLogic(stack) != logic)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package net.kanawo.cemodern.tile;
|
||||
|
||||
/** The three CE quarries. They share {@link TileCEQuarry} and differ only in how they treat fluids. */
|
||||
public enum QuarryType {
|
||||
|
||||
/** CEQ-2: a faster BuildCraft quarry with a bigger battery. Skips fluids like BuildCraft's does. */
|
||||
FAST("quarry2", 1),
|
||||
/** CEQ-3: also targets lava sources and removes them. */
|
||||
LAVA("quarry3", 1),
|
||||
/** CEQ-4: targets any fluid and turns fluids next to the drill into glass before digging. */
|
||||
FLUID("quarry4", 5);
|
||||
|
||||
/** Block registry name, also the texture folder name. */
|
||||
public final String name;
|
||||
/** How many times BuildCraft's quarry input rate this quarry accepts per tick. */
|
||||
final int receiveMultiplier;
|
||||
|
||||
QuarryType(String name, int receiveMultiplier) {
|
||||
this.name = name;
|
||||
this.receiveMultiplier = receiveMultiplier;
|
||||
}
|
||||
|
||||
public TileCEQuarry createTile() {
|
||||
switch (this) {
|
||||
case LAVA:
|
||||
return new TileCEQuarry.Lava();
|
||||
case FLUID:
|
||||
return new TileCEQuarry.Fluid();
|
||||
case FAST:
|
||||
default:
|
||||
return new TileCEQuarry.Fast();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,890 @@
|
||||
package net.kanawo.cemodern.tile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.kanawo.cemodern.CEConfig;
|
||||
import net.kanawo.cemodern.entity.EntityCEQuarryArm;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLiquid;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.inventory.ISidedInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
import net.minecraftforge.fluids.IFluidBlock;
|
||||
|
||||
import buildcraft.BuildCraftBuilders;
|
||||
import buildcraft.BuildCraftCore;
|
||||
import buildcraft.api.blueprints.BuilderAPI;
|
||||
import buildcraft.api.core.BuildCraftAPI;
|
||||
import buildcraft.api.core.IAreaProvider;
|
||||
import buildcraft.api.core.SafeTimeTracker;
|
||||
import buildcraft.api.filler.FillerManager;
|
||||
import buildcraft.api.statements.IStatementParameter;
|
||||
import buildcraft.api.tiles.IControllable;
|
||||
import buildcraft.api.tiles.IHasWork;
|
||||
import buildcraft.api.transport.IPipeConnection;
|
||||
import buildcraft.api.transport.IPipeTile;
|
||||
import buildcraft.core.Box;
|
||||
import buildcraft.core.Box.Kind;
|
||||
import buildcraft.core.CoreConstants;
|
||||
import buildcraft.core.DefaultProps;
|
||||
import buildcraft.core.blueprints.Blueprint;
|
||||
import buildcraft.core.blueprints.BptBuilderBase;
|
||||
import buildcraft.core.blueprints.BptBuilderBlueprint;
|
||||
import buildcraft.core.builders.TileAbstractBuilder;
|
||||
import buildcraft.core.builders.patterns.FillerPattern;
|
||||
import buildcraft.core.internal.IDropControlInventory;
|
||||
import buildcraft.core.lib.RFBattery;
|
||||
import buildcraft.core.lib.utils.BlockMiner;
|
||||
import buildcraft.core.lib.utils.BlockUtils;
|
||||
import buildcraft.core.lib.utils.Utils;
|
||||
import buildcraft.core.proxy.CoreProxy;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
/**
|
||||
* The CE quarries, a port of CE's TileQuarry2 and TileQuarry4 for BuildCraft 1.2.5.
|
||||
* <p>
|
||||
* It works like BuildCraft's {@code TileQuarry}: it builds a frame, then moves a mechanical arm over the area and
|
||||
* mines blocks with BuildCraft's {@link BlockMiner}. That class keeps its state private, so this one cannot extend it
|
||||
* and follows it instead. What CE changed:
|
||||
* <ul>
|
||||
* <li>Twice the battery, so the arm, whose speed grows with the stored energy, moves faster.</li>
|
||||
* <li>A configurable default area (64x64 by default), mirrored when the quarry is placed while sneaking.</li>
|
||||
* <li>It stops at a configurable Y level (5 by default) instead of digging into the bedrock.</li>
|
||||
* <li>Lava does not block the columns below it.</li>
|
||||
* <li>It remembers where it is in the area, so each search continues from the last target instead of starting
|
||||
* over.</li>
|
||||
* <li>It does not load chunks.</li>
|
||||
* <li>CEQ-3 removes lava sources, and CEQ-4 turns fluids around the drill into glass (see {@link QuarryType}).</li>
|
||||
* </ul>
|
||||
*/
|
||||
public abstract class TileCEQuarry extends TileAbstractBuilder
|
||||
implements IHasWork, ISidedInventory, IDropControlInventory, IPipeConnection, IControllable {
|
||||
|
||||
/** Tiles registered separately per type, so a quarry keeps its type when loaded from NBT. */
|
||||
public static class Fast extends TileCEQuarry {
|
||||
|
||||
public Fast() {
|
||||
super(QuarryType.FAST);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Lava extends TileCEQuarry {
|
||||
|
||||
public Lava() {
|
||||
super(QuarryType.LAVA);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Fluid extends TileCEQuarry {
|
||||
|
||||
public Fluid() {
|
||||
super(QuarryType.FLUID);
|
||||
}
|
||||
}
|
||||
|
||||
private enum Stage {
|
||||
BUILDING,
|
||||
DIGGING,
|
||||
MOVING,
|
||||
IDLE,
|
||||
DONE
|
||||
}
|
||||
|
||||
private enum ScanResult {
|
||||
FOUND,
|
||||
NONE,
|
||||
PENDING
|
||||
}
|
||||
|
||||
/** Blocks looked at per tick while searching, so an empty area does not stall a tick. */
|
||||
private static final int SCAN_BUDGET = 4096;
|
||||
/** RF to remove a lava source (CE: 100 MJ). */
|
||||
private static final int LAVA_ERASE_ENERGY = 1000;
|
||||
/** RF to turn one fluid block into glass (CE: 200 MJ). */
|
||||
private static final int FLUID_REPLACE_ENERGY = 2000;
|
||||
|
||||
public final QuarryType type;
|
||||
|
||||
public EntityCEQuarryArm arm;
|
||||
|
||||
private final Box box = new Box();
|
||||
private int targetX, targetY, targetZ;
|
||||
private double headPosX, headPosY, headPosZ;
|
||||
private double speed = 0.03;
|
||||
private Stage stage = Stage.BUILDING;
|
||||
private boolean movingHorizontally;
|
||||
private boolean movingVertically;
|
||||
private float headTrajectory;
|
||||
/** True while the arm returns to its rest position after the last target. */
|
||||
private boolean parking;
|
||||
|
||||
/**
|
||||
* Next block to look at: a layer and an index into that layer's serpentine order. {@link Integer#MAX_VALUE}
|
||||
* means start again from the top.
|
||||
*/
|
||||
private int scanY = Integer.MAX_VALUE;
|
||||
private int scanIndex;
|
||||
|
||||
/** Whether the placer was sneaking, which mirrors the default area. */
|
||||
private boolean mirrored;
|
||||
|
||||
private final SafeTimeTracker updateTracker = new SafeTimeTracker(BuildCraftCore.updateFactor);
|
||||
|
||||
private BptBuilderBase builder;
|
||||
private boolean frameProducer = true;
|
||||
private NBTTagCompound initNBT = null;
|
||||
private BlockMiner miner;
|
||||
|
||||
protected TileCEQuarry(QuarryType type) {
|
||||
this.type = type;
|
||||
box.kind = Kind.STRIPES;
|
||||
setBattery(
|
||||
new RFBattery(
|
||||
(int) (4 * 64 * BuilderAPI.BREAK_ENERGY * BuildCraftCore.miningMultiplier),
|
||||
(int) (1000 * type.receiveMultiplier * BuildCraftCore.miningMultiplier),
|
||||
0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockPlacedBy(EntityLivingBase entity, ItemStack stack) {
|
||||
super.onBlockPlacedBy(entity, stack);
|
||||
mirrored = entity.isSneaking();
|
||||
}
|
||||
|
||||
private void createUtilsIfNeeded() {
|
||||
if (!worldObj.isRemote && builder == null) {
|
||||
if (!box.isInitialized()) {
|
||||
setBoundaries();
|
||||
}
|
||||
|
||||
initializeBlueprintBuilder();
|
||||
}
|
||||
|
||||
if (stage != Stage.BUILDING) {
|
||||
box.isVisible = false;
|
||||
|
||||
if (arm == null) {
|
||||
createArm();
|
||||
}
|
||||
|
||||
if (!worldObj.isRemote
|
||||
&& (headPosX < box.xMin || headPosX > box.xMax || headPosZ < box.zMin || headPosZ > box.zMax)) {
|
||||
setHead(box.xMin + 1, yCoord + 2, box.zMin + 1);
|
||||
}
|
||||
} else {
|
||||
box.isVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void createArm() {
|
||||
worldObj.spawnEntityInWorld(
|
||||
new EntityCEQuarryArm(
|
||||
worldObj,
|
||||
box.xMin + CoreConstants.PIPE_MAX_POS,
|
||||
yCoord + box.sizeY() - 1 + CoreConstants.PIPE_MIN_POS,
|
||||
box.zMin + CoreConstants.PIPE_MAX_POS,
|
||||
box.sizeX() - 2 + CoreConstants.PIPE_MIN_POS * 2,
|
||||
box.sizeZ() - 2 + CoreConstants.PIPE_MIN_POS * 2,
|
||||
this));
|
||||
}
|
||||
|
||||
/** Callback from the arm once it is created. */
|
||||
public void setArm(EntityCEQuarryArm arm) {
|
||||
this.arm = arm;
|
||||
}
|
||||
|
||||
/** The quarry does not load chunks, so it waits until every chunk of its area is loaded. */
|
||||
private boolean areChunksLoaded() {
|
||||
for (int chunkX = box.xMin >> 4; chunkX <= box.xMax >> 4; chunkX++) {
|
||||
for (int chunkZ = box.zMin >> 4; chunkZ <= box.zMax >> 4; chunkZ++) {
|
||||
if (!worldObj.blockExists(chunkX << 4, box.yMax, chunkZ << 4)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEntity() {
|
||||
super.updateEntity();
|
||||
|
||||
if (worldObj.isRemote) {
|
||||
if (stage != Stage.DONE) {
|
||||
moveHead(speed);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (stage == Stage.DONE) {
|
||||
if (mode == Mode.Loop) {
|
||||
resetScan();
|
||||
stage = Stage.IDLE;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!areChunksLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == Mode.Off && stage != Stage.MOVING) {
|
||||
return;
|
||||
}
|
||||
|
||||
createUtilsIfNeeded();
|
||||
|
||||
if (stage == Stage.BUILDING) {
|
||||
if (builder != null && !builder.isDone(this)) {
|
||||
builder.buildNextSlot(worldObj, this, xCoord, yCoord, zCoord);
|
||||
} else {
|
||||
stage = Stage.IDLE;
|
||||
}
|
||||
} else if (stage == Stage.DIGGING) {
|
||||
dig();
|
||||
} else if (stage == Stage.IDLE) {
|
||||
// idling() sends its own network update when the stage changes.
|
||||
idling();
|
||||
return;
|
||||
} else if (stage == Stage.MOVING) {
|
||||
int energyUsed = getBattery()
|
||||
.useEnergy(20, (int) Math.ceil(20D + (double) getBattery().getEnergyStored() / 10), false);
|
||||
|
||||
if (energyUsed >= 20) {
|
||||
speed = 0.1 + energyUsed / 2000F;
|
||||
moveHead(speed);
|
||||
} else {
|
||||
speed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (updateTracker.markTimeIfDelay(worldObj)) {
|
||||
sendNetworkUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private void dig() {
|
||||
if (miner == null) {
|
||||
stage = Stage.IDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
int rfTaken = miner.acceptEnergy(getBattery().getEnergyStored());
|
||||
getBattery().useEnergy(rfTaken, rfTaken, false);
|
||||
|
||||
// BlockMiner also reports hasMined() when the break event was cancelled, so check hasFailed() first.
|
||||
if (miner.hasMined() && !miner.hasFailed()) {
|
||||
// Collect items dropped around the head, such as the contents of a mined chest.
|
||||
AxisAlignedBB around = AxisAlignedBB
|
||||
.getBoundingBox(headPosX - 2, headPosY - 2, headPosZ - 2, headPosX + 3, headPosY + 3, headPosZ + 3);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<EntityItem> items = worldObj.getEntitiesWithinAABB(EntityItem.class, around);
|
||||
for (EntityItem entity : items) {
|
||||
if (entity.isDead) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemStack mineable = entity.getEntityItem();
|
||||
if (mineable.stackSize <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CoreProxy.proxy.removeEntity(entity);
|
||||
miner.mineStack(mineable);
|
||||
}
|
||||
}
|
||||
|
||||
if (miner.hasMined() || miner.hasFailed()) {
|
||||
miner = null;
|
||||
scanIndex++;
|
||||
|
||||
if (!findFrame()) {
|
||||
initializeBlueprintBuilder();
|
||||
} else {
|
||||
stage = Stage.IDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Whether the frame next to the quarry is still there. If not, the quarry rebuilds it. */
|
||||
private boolean findFrame() {
|
||||
for (int i = 2; i < 6; i++) {
|
||||
ForgeDirection o = ForgeDirection.getOrientation(i);
|
||||
if (box.contains(xCoord + o.offsetX, yCoord + o.offsetY, zCoord + o.offsetZ)) {
|
||||
return worldObj.getBlock(xCoord + o.offsetX, yCoord + o.offsetY, zCoord + o.offsetZ)
|
||||
== BuildCraftBuilders.frameBlock;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void idling() {
|
||||
ScanResult result = parking ? ScanResult.NONE : findTarget();
|
||||
|
||||
if (result == ScanResult.PENDING) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == ScanResult.FOUND) {
|
||||
stage = Stage.MOVING;
|
||||
} else {
|
||||
int restX = box.xMin + 1, restY = yCoord + 2, restZ = box.zMin + 1;
|
||||
|
||||
if (headPosX == restX && headPosY == restY && headPosZ == restZ) {
|
||||
parking = false;
|
||||
stage = Stage.DONE;
|
||||
} else {
|
||||
setTarget(restX, restY, restZ);
|
||||
parking = true;
|
||||
stage = Stage.MOVING;
|
||||
}
|
||||
}
|
||||
|
||||
movingHorizontally = true;
|
||||
movingVertically = true;
|
||||
headTrajectory = (float) Math.atan2(targetZ - headPosZ, targetX - headPosX);
|
||||
sendNetworkUpdate();
|
||||
}
|
||||
|
||||
private void resetScan() {
|
||||
scanY = Integer.MAX_VALUE;
|
||||
scanIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for the next block to dig, from the top layer down to {@link CEConfig#quarryMinY}. Each layer is walked
|
||||
* in a serpentine order that starts where the layer above ended, and the search continues from where the last one
|
||||
* stopped. If something is found, it becomes the target, and the search moves past it once the arm is done with it
|
||||
* (see {@link #positionReached} and {@link #dig}). Each block is visited once per pass, so a fluid flowing back in
|
||||
* behind the arm does not hold it in place.
|
||||
*/
|
||||
private ScanResult findTarget() {
|
||||
int sizeX = box.sizeX() - 2;
|
||||
int sizeZ = box.sizeZ() - 2;
|
||||
int perLayer = sizeX * sizeZ;
|
||||
int minY = Math.max(CEConfig.quarryMinY, 0);
|
||||
int budget = SCAN_BUDGET;
|
||||
|
||||
if (scanY > yCoord + 3) {
|
||||
scanY = yCoord + 3;
|
||||
scanIndex = 0;
|
||||
}
|
||||
|
||||
for (; scanY >= minY; scanY--, scanIndex = 0) {
|
||||
for (; scanIndex < perLayer; scanIndex++) {
|
||||
if (budget-- <= 0) {
|
||||
return ScanResult.PENDING;
|
||||
}
|
||||
|
||||
int row = scanIndex / sizeZ;
|
||||
int column = scanIndex % sizeZ;
|
||||
int searchX = (scanY & 1) == 0 ? row : sizeX - 1 - row;
|
||||
int searchZ = (searchX & 1) == (scanY & 1) ? column : sizeZ - 1 - column;
|
||||
int x = box.xMin + 1 + searchX;
|
||||
int z = box.zMin + 1 + searchZ;
|
||||
|
||||
if (isTarget(x, scanY, z)) {
|
||||
setTarget(x, scanY + 1, z);
|
||||
return ScanResult.FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ScanResult.NONE;
|
||||
}
|
||||
|
||||
private boolean isTarget(int x, int y, int z) {
|
||||
Block block = worldObj.getBlock(x, y, z);
|
||||
return isFluidTarget(block, worldObj.getBlockMetadata(x, y, z)) || isMineable(block, x, y, z);
|
||||
}
|
||||
|
||||
private boolean isMineable(Block block, int x, int y, int z) {
|
||||
return BlockUtils.canChangeBlock(block, worldObj, x, y, z) && !isSoft(block, x, y, z)
|
||||
&& !isFluid(block)
|
||||
&& block != BuildCraftBuilders.frameBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link BuildCraftAPI#isSoftBlock}, without its cache. The cache is only updated when the block change is
|
||||
* sent to players, so in a chunk without players a mined block would still read as solid.
|
||||
*/
|
||||
private boolean isSoft(Block block, int x, int y, int z) {
|
||||
return block.isAir(worldObj, x, y, z) || BuildCraftAPI.softBlocks.contains(block)
|
||||
|| block.isReplaceable(worldObj, x, y, z);
|
||||
}
|
||||
|
||||
/** Fluids this quarry goes to even though it cannot mine them. */
|
||||
private boolean isFluidTarget(Block block, int meta) {
|
||||
switch (type) {
|
||||
case LAVA:
|
||||
return block instanceof BlockLiquid && block.getMaterial() == Material.lava && meta == 0;
|
||||
case FLUID:
|
||||
return isFluid(block);
|
||||
case FAST:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isFluid(Block block) {
|
||||
return block instanceof BlockLiquid || block instanceof IFluidBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(NBTTagCompound nbt) {
|
||||
super.readFromNBT(nbt);
|
||||
|
||||
if (nbt.hasKey("box")) {
|
||||
box.initialize(nbt.getCompoundTag("box"));
|
||||
}
|
||||
|
||||
targetX = nbt.getInteger("targetX");
|
||||
targetY = nbt.getInteger("targetY");
|
||||
targetZ = nbt.getInteger("targetZ");
|
||||
headPosX = nbt.getDouble("headPosX");
|
||||
headPosY = nbt.getDouble("headPosY");
|
||||
headPosZ = nbt.getDouble("headPosZ");
|
||||
|
||||
if (nbt.hasKey("scanY")) {
|
||||
scanY = nbt.getInteger("scanY");
|
||||
scanIndex = nbt.getInteger("scanIndex");
|
||||
}
|
||||
|
||||
parking = nbt.getBoolean("parking");
|
||||
|
||||
// The build state is loaded in initialize(), once the frame blueprint exists.
|
||||
initNBT = (NBTTagCompound) nbt.getCompoundTag("bpt")
|
||||
.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(NBTTagCompound nbt) {
|
||||
super.writeToNBT(nbt);
|
||||
|
||||
nbt.setInteger("targetX", targetX);
|
||||
nbt.setInteger("targetY", targetY);
|
||||
nbt.setInteger("targetZ", targetZ);
|
||||
nbt.setDouble("headPosX", headPosX);
|
||||
nbt.setDouble("headPosY", headPosY);
|
||||
nbt.setDouble("headPosZ", headPosZ);
|
||||
nbt.setInteger("scanY", scanY);
|
||||
nbt.setInteger("scanIndex", scanIndex);
|
||||
nbt.setBoolean("parking", parking);
|
||||
|
||||
NBTTagCompound boxTag = new NBTTagCompound();
|
||||
box.writeToNBT(boxTag);
|
||||
nbt.setTag("box", boxTag);
|
||||
|
||||
NBTTagCompound bptNBT = new NBTTagCompound();
|
||||
|
||||
if (builder != null) {
|
||||
NBTTagCompound builderCpt = new NBTTagCompound();
|
||||
builder.saveBuildStateToNBT(builderCpt, this);
|
||||
bptNBT.setTag("builderState", builderCpt);
|
||||
}
|
||||
|
||||
nbt.setTag("bpt", bptNBT);
|
||||
}
|
||||
|
||||
/** Called by {@link #moveHead} when the arm arrives at its target. */
|
||||
private void positionReached() {
|
||||
if (worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parking) {
|
||||
parking = false;
|
||||
stage = Stage.DONE;
|
||||
return;
|
||||
}
|
||||
|
||||
int x = targetX;
|
||||
int y = targetY - 1;
|
||||
int z = targetZ;
|
||||
|
||||
if (type == QuarryType.FLUID) {
|
||||
// The target itself becomes glass and is then mined. Its neighbours stay glass, walling off the shaft.
|
||||
replaceFluid(x, y, z);
|
||||
replaceFluid(x + 1, y, z);
|
||||
replaceFluid(x - 1, y, z);
|
||||
replaceFluid(x, y, z + 1);
|
||||
replaceFluid(x, y, z - 1);
|
||||
replaceFluid(x, y + 1, z);
|
||||
}
|
||||
|
||||
Block block = worldObj.getBlock(x, y, z);
|
||||
|
||||
if (type == QuarryType.LAVA && isFluidTarget(block, worldObj.getBlockMetadata(x, y, z))) {
|
||||
worldObj.setBlockToAir(x, y, z);
|
||||
useFluidEnergy(LAVA_ERASE_ENERGY);
|
||||
scanIndex++;
|
||||
stage = Stage.IDLE;
|
||||
} else if (isMineable(block, x, y, z)) {
|
||||
// dig() moves the search on once the block is mined.
|
||||
miner = new BlockMiner(worldObj, this, x, y, z);
|
||||
stage = Stage.DIGGING;
|
||||
} else {
|
||||
scanIndex++;
|
||||
stage = Stage.IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
private void replaceFluid(int x, int y, int z) {
|
||||
if (worldObj.blockExists(x, y, z) && isFluid(worldObj.getBlock(x, y, z))) {
|
||||
worldObj.setBlock(x, y, z, Blocks.glass);
|
||||
useFluidEnergy(FLUID_REPLACE_ENERGY);
|
||||
}
|
||||
}
|
||||
|
||||
/** Takes what it can of the cost; like CE, a missing remainder does not stop the work. */
|
||||
private void useFluidEnergy(int energy) {
|
||||
int cost = (int) (energy * BuildCraftCore.miningMultiplier);
|
||||
getBattery().useEnergy(0, cost, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNetworkUpdateRange() {
|
||||
return DefaultProps.NETWORK_UPDATE_RANGE
|
||||
+ (int) Math.ceil(Math.sqrt(yCoord * yCoord + box.sizeX() * box.sizeX() + box.sizeZ() * box.sizeZ()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
super.invalidate();
|
||||
destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnload() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
if (arm != null) {
|
||||
arm.setDead();
|
||||
}
|
||||
|
||||
arm = null;
|
||||
|
||||
frameProducer = false;
|
||||
|
||||
if (miner != null) {
|
||||
miner.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasWork() {
|
||||
return stage != Stage.DONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the marker next to the quarry if it spans at least 3x3, or else the default area from the config. The
|
||||
* default area lies behind the quarry, with the quarry on its near edge.
|
||||
*/
|
||||
private void setBoundaries() {
|
||||
IAreaProvider a = Utils.getNearbyAreaProvider(worldObj, xCoord, yCoord, zCoord);
|
||||
|
||||
if (a != null && (a.xMax() - a.xMin() + 1 < 3 || a.zMax() - a.zMin() + 1 < 3)) {
|
||||
a = null;
|
||||
}
|
||||
|
||||
if (a != null) {
|
||||
box.initialize(a);
|
||||
|
||||
if (box.sizeY() < 5) {
|
||||
box.yMax = box.yMin + 4;
|
||||
}
|
||||
|
||||
a.removeFromWorld();
|
||||
} else {
|
||||
int size = CEConfig.quarryDefaultSize;
|
||||
int before = mirrored ? size - CEConfig.quarryDefaultPosition - 1 : CEConfig.quarryDefaultPosition;
|
||||
int after = size - before - 1;
|
||||
int far = size - 1;
|
||||
int xMin, zMin;
|
||||
|
||||
switch (worldObj.getBlockMetadata(xCoord, yCoord, zCoord) & 7) {
|
||||
case 3:
|
||||
xMin = xCoord - before;
|
||||
zMin = zCoord - far - 1;
|
||||
break;
|
||||
case 4:
|
||||
xMin = xCoord + 1;
|
||||
zMin = zCoord - before;
|
||||
break;
|
||||
case 5:
|
||||
xMin = xCoord - far - 1;
|
||||
zMin = zCoord - after;
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
xMin = xCoord - after;
|
||||
zMin = zCoord + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
box.initialize(xMin, yCoord, zMin, xMin + far, yCoord + 4, zMin + far);
|
||||
}
|
||||
|
||||
sendNetworkUpdate();
|
||||
}
|
||||
|
||||
/** Starts building the frame. Already placed frame blocks are kept. */
|
||||
private void initializeBlueprintBuilder() {
|
||||
Blueprint bpt = ((FillerPattern) FillerManager.registry.getPattern("buildcraft:frame"))
|
||||
.getBlueprint(box, worldObj, new IStatementParameter[0], BuildCraftBuilders.frameBlock, 0);
|
||||
|
||||
if (bpt != null) {
|
||||
builder = new BptBuilderBlueprint(bpt, worldObj, box.xMin, yCoord, box.zMin);
|
||||
speed = 0;
|
||||
stage = Stage.BUILDING;
|
||||
sendNetworkUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeData(ByteBuf stream) {
|
||||
super.writeData(stream);
|
||||
box.writeData(stream);
|
||||
stream.writeInt(targetX);
|
||||
stream.writeShort(targetY);
|
||||
stream.writeInt(targetZ);
|
||||
stream.writeDouble(headPosX);
|
||||
stream.writeDouble(headPosY);
|
||||
stream.writeDouble(headPosZ);
|
||||
stream.writeFloat((float) speed);
|
||||
stream.writeFloat(headTrajectory);
|
||||
int flags = stage.ordinal();
|
||||
flags |= movingHorizontally ? 0x10 : 0;
|
||||
flags |= movingVertically ? 0x20 : 0;
|
||||
stream.writeByte(flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readData(ByteBuf stream) {
|
||||
super.readData(stream);
|
||||
box.readData(stream);
|
||||
targetX = stream.readInt();
|
||||
targetY = stream.readUnsignedShort();
|
||||
targetZ = stream.readInt();
|
||||
headPosX = stream.readDouble();
|
||||
headPosY = stream.readDouble();
|
||||
headPosZ = stream.readDouble();
|
||||
speed = stream.readFloat();
|
||||
headTrajectory = stream.readFloat();
|
||||
int flags = stream.readUnsignedByte();
|
||||
stage = Stage.values()[flags & 0x07];
|
||||
movingHorizontally = (flags & 0x10) != 0;
|
||||
movingVertically = (flags & 0x20) != 0;
|
||||
|
||||
createUtilsIfNeeded();
|
||||
|
||||
if (arm != null) {
|
||||
arm.setHead(headPosX, headPosY, headPosZ);
|
||||
arm.updatePosition();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
|
||||
if (!worldObj.isRemote && !box.initialized) {
|
||||
setBoundaries();
|
||||
}
|
||||
|
||||
createUtilsIfNeeded();
|
||||
|
||||
if (initNBT != null && builder != null) {
|
||||
builder.loadBuildStateToNBT(initNBT.getCompoundTag("builderState"), this);
|
||||
}
|
||||
|
||||
initNBT = null;
|
||||
|
||||
sendNetworkUpdate();
|
||||
}
|
||||
|
||||
/** Rebuilds the frame and searches the whole area again, also after the quarry has finished. */
|
||||
public void reinitialize() {
|
||||
if (miner != null) {
|
||||
miner.invalidate();
|
||||
miner = null;
|
||||
}
|
||||
|
||||
parking = false;
|
||||
resetScan();
|
||||
initializeBlueprintBuilder();
|
||||
}
|
||||
|
||||
// The inventory holds an endless supply of frames for building the frame, and nothing else. It is hidden from
|
||||
// pipes and hoppers by the sided inventory methods below.
|
||||
|
||||
@Override
|
||||
public int getSizeInventory() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStackInSlot(int i) {
|
||||
return frameProducer ? new ItemStack(BuildCraftBuilders.frameBlock) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack decrStackSize(int i, int j) {
|
||||
return frameProducer ? new ItemStack(BuildCraftBuilders.frameBlock, j) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInventorySlotContents(int i, ItemStack itemstack) {}
|
||||
|
||||
@Override
|
||||
public ItemStack getStackInSlotOnClosing(int slot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInventoryName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomInventoryName() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInventoryStackLimit() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemValidForSlot(int i, ItemStack itemstack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseableByPlayer(EntityPlayer entityplayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openInventory() {}
|
||||
|
||||
@Override
|
||||
public void closeInventory() {}
|
||||
|
||||
@Override
|
||||
public boolean isBuildingMaterialSlot(int i) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getAccessibleSlotsFromSide(int side) {
|
||||
return new int[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInsertItem(int slot, ItemStack stack, int side) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtractItem(int slot, ItemStack stack, int side) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void moveHead(double instantSpeed) {
|
||||
if (movingHorizontally) {
|
||||
if (Math.abs(targetX - headPosX) < instantSpeed * 2 && Math.abs(targetZ - headPosZ) < instantSpeed * 2) {
|
||||
headPosX = targetX;
|
||||
headPosZ = targetZ;
|
||||
|
||||
movingHorizontally = false;
|
||||
|
||||
if (!movingVertically) {
|
||||
positionReached();
|
||||
headPosY = targetY;
|
||||
}
|
||||
} else {
|
||||
headPosX += MathHelper.cos(headTrajectory) * instantSpeed;
|
||||
headPosZ += MathHelper.sin(headTrajectory) * instantSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
if (movingVertically) {
|
||||
if (Math.abs(targetY - headPosY) < instantSpeed * 2) {
|
||||
headPosY = targetY;
|
||||
|
||||
movingVertically = false;
|
||||
|
||||
if (!movingHorizontally) {
|
||||
positionReached();
|
||||
headPosX = targetX;
|
||||
headPosZ = targetZ;
|
||||
}
|
||||
} else if (targetY > headPosY) {
|
||||
headPosY += instantSpeed;
|
||||
} else {
|
||||
headPosY -= instantSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
if (arm != null && worldObj.isRemote) {
|
||||
arm.setHead(headPosX, headPosY, headPosZ);
|
||||
arm.updatePosition();
|
||||
}
|
||||
}
|
||||
|
||||
private void setHead(double x, double y, double z) {
|
||||
headPosX = x;
|
||||
headPosY = y;
|
||||
headPosZ = z;
|
||||
}
|
||||
|
||||
private void setTarget(int x, int y, int z) {
|
||||
targetX = x;
|
||||
targetY = y;
|
||||
targetZ = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisAlignedBB getRenderBoundingBox() {
|
||||
return new Box(this).extendToEncompass(box)
|
||||
.expand(50)
|
||||
.getBoundingBox();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Box getBox() {
|
||||
return box;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsControlMode(Mode mode) {
|
||||
return mode == Mode.Off || mode == Mode.On || mode == Mode.Loop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doDrop() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectOverride overridePipeConnection(IPipeTile.PipeType type, ForgeDirection with) {
|
||||
return type == IPipeTile.PipeType.ITEM ? ConnectOverride.CONNECT : ConnectOverride.DEFAULT;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,5 @@
|
||||
tile.emcBuilder.name=EMC Builder
|
||||
gui.cemodern.stored=EMC: %s
|
||||
tile.ceQuarry2.name=Quarry of fast mining type
|
||||
tile.ceQuarry3.name=Quarry of lava removal type
|
||||
tile.ceQuarry4.name=Quarry of fluid replace type
|
||||
@@ -1,2 +1,5 @@
|
||||
tile.emcBuilder.name=EMCビルダー
|
||||
gui.cemodern.stored=EMC: %s
|
||||
tile.ceQuarry2.name=採掘強化型クアーリー
|
||||
tile.ceQuarry3.name=溶岩除去型クアーリー
|
||||
tile.ceQuarry4.name=液体対策型クアーリー
|
||||
|
After Width: | Height: | Size: 641 B |
|
After Width: | Height: | Size: 513 B |
|
After Width: | Height: | Size: 615 B |
|
After Width: | Height: | Size: 615 B |
|
After Width: | Height: | Size: 479 B |
|
After Width: | Height: | Size: 606 B |
|
After Width: | Height: | Size: 666 B |
|
After Width: | Height: | Size: 638 B |
|
After Width: | Height: | Size: 771 B |
@@ -3,7 +3,7 @@
|
||||
"modList": [{
|
||||
"modid": "${modId}",
|
||||
"name": "${modName}",
|
||||
"description": "A Minecraft 1.7.10 port of CE. Adds the EMC Builder, a BuildCraft Builder that pays for its materials with EMC.",
|
||||
"description": "A Minecraft 1.7.10 port of CE. Adds the EMC Builder, a BuildCraft Builder that pays for its materials with EMC, and the CE quarries, improved BuildCraft quarries.",
|
||||
"version": "${modVersion}",
|
||||
"mcversion": "${minecraftVersion}",
|
||||
"url": "",
|
||||
@@ -13,8 +13,8 @@
|
||||
"logoFile": "",
|
||||
"screenshots": [],
|
||||
"parent": "",
|
||||
"requiredMods": ["BuildCraft|Builders", "ProjectE"],
|
||||
"dependencies": ["BuildCraft|Builders", "ProjectE"],
|
||||
"requiredMods": ["BuildCraft|Builders", "BuildCraft|Factory", "BuildCraft|Silicon", "BuildCraft|Transport", "ProjectE"],
|
||||
"dependencies": ["BuildCraft|Builders", "BuildCraft|Factory", "BuildCraft|Silicon", "BuildCraft|Transport", "ProjectE"],
|
||||
"dependants": [],
|
||||
"useDependencyInformation": false
|
||||
}]
|
||||
|
||||