Moved API

Added temporary(!) API dependencies, will resolved via Maven later on
Added mcmod.info
Added pack.mcmeta template
Added hacked BC jar to use facades indev
Split build logic into several pieces
Update gitignore
Modify build.gradle to match changes
This commit is contained in:
thatsIch 2014-09-26 16:14:44 +02:00
parent b97f19bea8
commit 54802be11f
305 changed files with 22813 additions and 129 deletions

10
.gitignore vendored
View file

@ -16,12 +16,6 @@
# include sourcecode
!src/
# include important mods required for running
# need to include run first to exclude all existing to add mods later on
!run/
run/*
!run/mods
# include special libs like BC
!libs/
@ -29,5 +23,5 @@ run/*
!.gitmodules
!.gitignore
# include travis build
!.travis.yml
# code format to reduce noise in git commits
!codeformat/

6
.gitmodules vendored
View file

@ -1,7 +1,7 @@
[submodule "src/main/java/appeng/api"]
path = src/main/java/appeng/api
url = https://github.com/AppliedEnergistics/Applied-Energistics-2-API.git
[submodule "src/main/resources/assets/appliedenergistics2/lang"]
path = src/main/resources/assets/appliedenergistics2/lang
url = https://github.com/AppliedEnergistics/AppliedEnergistics-2-Localization.git
[submodule "src/api/java/appeng/api"]
path = src/api/java/appeng/api
url = https://github.com/AppliedEnergistics/Applied-Energistics-2-API.git

View file

@ -1,7 +1,12 @@
apply plugin: 'forge'
apply from: 'gradle/scripts/propertyloader.gradle'
apply from: 'gradle/scripts/dependencies.gradle'
apply from: 'gradle/scripts/artifacts.gradle'
apply from: 'gradle/scripts/autoinstallruntime.gradle'
buildscript {
repositories {
mavenCentral()
maven {
@ -13,89 +18,35 @@ buildscript {
name = "sonatype"
url = "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
}
}
apply plugin: 'forge'
repositories {
maven {
name 'CB Maven FS'
url "http://chickenbones.net/maven/"
}
maven {
name "IC2 Player Repo"
url "http://maven.ic2.player.to/"
}
maven {
name "Waila Mobius Repo"
url "http://mobiusstrip.eu/maven"
}
}
configurations.all {
resolutionStrategy.cacheDynamicVersionsFor 7200, 'hours'
}
// define the properties file
ext.configFile = file "build.properties"
configFile.withReader {
// read config. it shall from now on be referenced as simply config or as project.config
def prop = new Properties()
prop.load(it)
project.ext.config = new ConfigSlurper().parse prop
}
targetCompatibility = JavaVersion.VERSION_1_6
version = config.version+"-"+config.aechannel+"-"+config.build
version = config.version + "-" + config.aechannel + "-" + config.build
group = config.group
archivesBaseName = config.archivesBaseName
dependencies {
compile "net.industrial-craft:industrialcraft-2:${config.ic2_version}-experimental:dev"
compile "codechicken:ForgeMultipart:${config.cb_minecraft_version}-${config.fmp_version}:dev"
compile "codechicken:CodeChickenLib:${config.cb_minecraft_version}-${config.code_chicken_lib_version}:dev"
compile "codechicken:CodeChickenCore:${config.cb_minecraft_version}-${config.code_chicken_core_version}:dev"
compile "codechicken:NotEnoughItems:${config.cb_minecraft_version}-${config.nei_version}:dev"
compile "mcp.mobius.waila:Waila:${config.waila_version}"
compile files(fileTree(dir: 'libs', includes: ['*.jar']))
// compile "com.mod-buildcraft:buildcraft:6.0.8:dev"
}
// Add Coremod Manifest
jar {
manifest {
attributes 'FMLCorePlugin': 'appeng.transformer.AppEngCore'
attributes 'FMLCorePluginContainsFMLMod': 'true'
}
}
compileJava {
exclude("appeng/api/integration/*")
exclude("appeng/integration/modules/helpers/dead/**")
exclude("appeng/integration/modules/dead/**")
// exclude("appeng/fmp/**")
// specify which files are really included, can control which APIs should be in
include "appeng/**"
include "assets/**"
include "mcmod.info"
include "pack.mcmeta"
}
minecraft {
@ -104,85 +55,38 @@ minecraft {
replace "@version@", project.version
replace "@aechannel@", config.aechannel
// used when launching minecraft in dev env
runDir = "run"
}
sourceSets {
main {
java {
srcDirs += 'src/api/java'
srcDirs += 'src/main/java/'
exclude("src/api/**")
}
resources {
srcDir 'src/main/resources/'
srcDir "src/main/resources/"
include "assets/appliedenergistics2/recipes/*.recipe",
"assets/appliedenergistics2/lang/*.lang",
"assets/appliedenergistics2/textures/blocks/*",
"assets/appliedenergistics2/textures/guis/*",
"assets/appliedenergistics2/textures/models/*",
"assets/appliedenergistics2/textures/items/*"
"assets/appliedenergistics2/lang/*.lang",
"assets/appliedenergistics2/textures/blocks/*",
"assets/appliedenergistics2/textures/guis/*",
"assets/appliedenergistics2/textures/models/*",
"assets/appliedenergistics2/textures/items/*"
}
}
}
processResources {
// replace stuff in mcmod.info, nothing else
from(sourceSets.main.resources.srcDirs) {
include 'mcmod.info'
expand 'version': project.version, 'mcversion': config.minecraft_version
}
// copy everything else, thats not the mcmod.info
// copy everything else, that is not the mcmod.info
from(sourceSets.main.resources.srcDirs) {
exclude 'mcmod.info'
}
}
task myJavadocs(type: Javadoc) {
source = sourceSets.api.java
include "appeng/api/**"
classpath = configurations.compile
}
task javadocJar(type: Jar, dependsOn: myJavadocs) {
classifier = 'javadoc'
from 'build/docs/javadoc/'
}
task devJar(type: Jar) {
manifest {
attributes 'FMLCorePlugin': 'appeng.transformer.AppEngCore'
attributes 'FMLCorePluginContainsFMLMod': 'true'
}
from(sourceSets.main.output) {
include "appeng/**"
include "assets/**"
include 'mcmod.info'
}
classifier = 'dev'
}
task apiJar(type: Jar) {
from(sourceSets.api.java) {
include "appeng/api/**"
}
classifier = 'api'
}
artifacts {
archives devJar
archives apiJar
archives javadocJar
}

View file

@ -0,0 +1,43 @@
task myJavadocs(type: Javadoc) {
source = sourceSets.api.java
include "appeng/api/**"
classpath = configurations.compile
}
task javadocJar(type: Jar, dependsOn: myJavadocs) {
classifier = 'javadoc'
from 'build/docs/javadoc/'
}
task devJar(type: Jar) {
manifest {
attributes 'FMLCorePlugin': 'appeng.transformer.AppEngCore'
attributes 'FMLCorePluginContainsFMLMod': 'true'
}
from(sourceSets.main.output) {
include "appeng/**"
include "assets/**"
include 'mcmod.info'
}
classifier = 'dev'
}
task apiJar(type: Jar) {
from(sourceSets.api.java) {
include "appeng/api/**"
}
classifier = 'api'
}
artifacts {
archives devJar
archives apiJar
archives javadocJar
}

View file

@ -0,0 +1,34 @@
// searches for NEI and Chicken stuff from compile set
// and adds them to the mods in run dir
task copyChicken(type: Copy, dependsOn: "extractUserDev") {
from { configurations.compile }
include "**/*Chicken*.jar", "**/*NotEnoughItems*.jar"
exclude "**/CodeChickenLib*" // because CCC downloads it anyways.. -_-
into file(minecraft.runDir + "/mods")
mustRunAfter "deobfBinJar"
mustRunAfter "repackMinecraft"
}
tasks.setupDevWorkspace.dependsOn copyChicken
tasks.setupDecompWorkspace.dependsOn copyChicken
// same for BC hacked file
task copyBuildcraft(type: Copy, dependsOn: "extractUserDev") {
from { configurations.compile }
include "**/*buildcraft*.jar"
into file(minecraft.runDir + "/mods")
mustRunAfter "deobfBinJar"
mustRunAfter "repackMinecraft"
}
tasks.setupDevWorkspace.dependsOn copyBuildcraft
tasks.setupDecompWorkspace.dependsOn copyBuildcraft
// and for IC2 because it needs its EMLJ jar
task copyIndustrialcraft(type: Copy, dependsOn: "extractUserDev") {
from { configurations.compile }
include "**/*industrialcraft*.jar"
into file(minecraft.runDir + "/mods")
mustRunAfter "deobfBinJar"
mustRunAfter "repackMinecraft"
}
tasks.setupDevWorkspace.dependsOn copyIndustrialcraft
tasks.setupDecompWorkspace.dependsOn copyIndustrialcraft

View file

@ -0,0 +1,33 @@
repositories {
maven {
name 'CB Maven FS'
url "http://chickenbones.net/maven/"
}
maven {
name "IC2 Player Repo"
url "http://maven.ic2.player.to/"
}
maven {
name "Waila Mobius Repo"
url "http://mobiusstrip.eu/maven"
}
}
dependencies {
compile "net.industrial-craft:industrialcraft-2:${config.ic2_version}-experimental:dev"
compile "codechicken:ForgeMultipart:${config.cb_minecraft_version}-${config.fmp_version}:dev"
compile "codechicken:CodeChickenLib:${config.cb_minecraft_version}-${config.code_chicken_lib_version}:dev"
compile "codechicken:CodeChickenCore:${config.cb_minecraft_version}-${config.code_chicken_core_version}:dev"
compile "codechicken:NotEnoughItems:${config.cb_minecraft_version}-${config.nei_version}:dev"
compile "mcp.mobius.waila:Waila:${config.waila_version}"
// add hacked buildcraft jar to compile time (for facades)
compile fileTree(dir: 'libs', include: '*.jar')
}

View file

@ -0,0 +1,9 @@
// define the properties file
ext.configFile = file "build.properties"
configFile.withReader {
// read config. it shall from now on be referenced as simply config or as project.config
def prop = new Properties()
prop.load(it)
project.ext.config = new ConfigSlurper().parse prop
}

BIN
libs/buildcraft-dev.jar Normal file

Binary file not shown.

View file

@ -0,0 +1,67 @@
/*******************************************************************************
* @author Reika Kalseki
*
* Copyright 2014
*
* All rights reserved.
* Distribution of the software in any form is only allowed with
* explicit, prior permission from the owner.
******************************************************************************/
package Reika.RotaryCraft.API;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import net.minecraft.tileentity.TileEntity;
public class IOAPI {
private static Class io;
private static Method render;
static {
try {
io = Class.forName("Reika.RotaryCraft.Auxiliary.IORenderer", false, IOAPI.class.getClassLoader());
render = io.getMethod("renderIO", TileEntity.class, double.class, double.class, double.class);
}
catch (ClassNotFoundException e) {
System.out.println("RotaryCraft IORenderer class not found!");
e.printStackTrace();
}
catch (NoSuchMethodException e) {
System.out.println("Could not find renderIO method in IORenderer class!");
e.printStackTrace();
}
catch (SecurityException e) {
e.printStackTrace();
}
}
/** Call this to run the RotaryCraft I/O Renderer on your TileEntity.
*
* You must call this from inside your TE renderer's "renderTileEntityAt" method.
* Calling it on pass 1 only is strongly recommended to
* prevent visual glitches caused by OpenGL limitations.
* @param machine Your TileEntity as either a ShaftPowerEmitter or ShaftPowerReceiver
* @param par2 The "par2" passed in the "renderTileEntityAt"; related to x-displacement
* @param par4 The "par4" passed in the "renderTileEntityAt"; related to y-displacement
* @param par6 The "par6" passed in the "renderTileEntityAt"; related to z-displacement
*/
public static void renderIO(ShaftMachine machine, double par2, double par4, double par6) {
try {
render.invoke(null, machine, par2, par4, par6);
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (IllegalArgumentException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
catch (NullPointerException e) { //If init failed
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,26 @@
/*******************************************************************************
* @author Reika Kalseki
*
* Copyright 2014
*
* All rights reserved.
* Distribution of the software in any form is only allowed with
* explicit, prior permission from the owner.
******************************************************************************/
package Reika.RotaryCraft.API;
/** Implement this if your TE "spawns" power */
public interface PowerGenerator {
/** The maximum amount of power your machine can ever generate, in watts.
* If there is no cap, use Long.MAX_VALUE. */
public long getMaxPower();
/** The current power your machine is producing, in watts. */
public long getCurrentPower();
public int getEmittingX();
public int getEmittingY();
public int getEmittingZ();
}

View file

@ -0,0 +1,37 @@
/*******************************************************************************
* @author Reika Kalseki
*
* Copyright 2014
*
* All rights reserved.
* Distribution of the software in any form is only allowed with
* explicit, prior permission from the owner.
******************************************************************************/
package Reika.RotaryCraft.API;
public interface ShaftMachine {
/** For fetching the current rotational speed. This can be called from
* both client and server, so ensure that the TE is prepared for that. */
public int getOmega();
/** For fetching the current torque. This can be called from
* both client and server, so ensure that the TE is prepared for that. */
public int getTorque();
/** For fetching the current power value. This can be called from
* both client and server, so ensure that the TE is prepared for that. */
public long getPower();
/** For when to write it to chat or the like. This can be called from
* both client and server, so ensure that the TE is prepared for that. */
public String getName();
/** Analogous to TileEntityIOMachine's "iotick". Used to control I/O render opacity. */
public int getIORenderAlpha();
/** Analogous to TileEntityIOMachine's "iotick". Used to control I/O render opacity.
* This one is called by tools. */
public void setIORenderAlpha(int io);
}

View file

@ -0,0 +1,15 @@
/*******************************************************************************
* @author Reika Kalseki
*
* Copyright 2014
*
* All rights reserved.
* Distribution of the software in any form is only allowed with
* explicit, prior permission from the owner.
******************************************************************************/
package Reika.RotaryCraft.API;
/** If your machine merges two shafts, implement this to avoid being the source of a loop exploit or StackOverflow */
public interface ShaftMerger {
}

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* @author Reika Kalseki
*
* Copyright 2014
*
* All rights reserved.
* Distribution of the software in any form is only allowed with
* explicit, prior permission from the owner.
******************************************************************************/
package Reika.RotaryCraft.API;
import net.minecraftforge.common.util.ForgeDirection;
public interface ShaftPowerEmitter extends ShaftMachine, PowerGenerator {
/** x,y,z to write to */
public boolean canWriteTo(ForgeDirection dir);
/** Whether your machine is emitting power right now */
public boolean isEmitting();
}

View file

@ -0,0 +1,40 @@
/*******************************************************************************
* @author Reika Kalseki
*
* Copyright 2014
*
* All rights reserved.
* Distribution of the software in any form is only allowed with
* explicit, prior permission from the owner.
******************************************************************************/
package Reika.RotaryCraft.API;
import net.minecraftforge.common.util.ForgeDirection;
public interface ShaftPowerReceiver extends ShaftMachine {
/** RC machines set your machine's rotational speed with this. */
public void setOmega(int omega);
/** RC machines set your machine's torque with this. */
public void setTorque(int torque);
/** RC machines set your machine's power with this.
* You do not need to calculate power=omega*torque;
* RC code will do that for you. */
public void setPower(long power);
/** x,y,z to read from */
public boolean canReadFrom(ForgeDirection dir);
/** Whether your machine is able to receive power right now */
public boolean isReceiving();
/** When there is no input machine. Usually used to set power, speed, torque = 0 */
public void noInputMachine();
/** The minimum torque the machine requires to operate. Also controls flywheel deceleration.
* Pick something reasonable, preferably as realistic as possible. */
public int getMinTorque(int available);
}

View file

@ -0,0 +1,37 @@
/*******************************************************************************
* @author Reika Kalseki
*
* Copyright 2014
*
* All rights reserved.
* Distribution of the software in any form is only allowed with
* explicit, prior permission from the owner.
******************************************************************************/
package Reika.RotaryCraft.API;
import net.minecraft.world.World;
public interface ThermalMachine {
/** For fetching the temperature for display */
public int getTemperature();
/** For overwriting the temperature */
public void setTemperature(int T);
/** For updating the temperature */
public void addTemperature(int T);
/** For display purposes */
public String getName();
/** For overheating tests */
public int getMaxTemperature();
/** Actions to take on overheat */
public void onOverheat(World world, int x, int y, int z);
/** Can the friction heater heat this machine */
public boolean canBeFrictionHeated();
}

View file

@ -0,0 +1,158 @@
package cofh.api.energy;
import net.minecraft.nbt.NBTTagCompound;
/**
* Reference implementation of {@link IEnergyStorage}. Use/extend this or implement your own.
*
* @author King Lemming
*
*/
public class EnergyStorage implements IEnergyStorage {
protected int energy;
protected int capacity;
protected int maxReceive;
protected int maxExtract;
public EnergyStorage(int capacity) {
this(capacity, capacity, capacity);
}
public EnergyStorage(int capacity, int maxTransfer) {
this(capacity, maxTransfer, maxTransfer);
}
public EnergyStorage(int capacity, int maxReceive, int maxExtract) {
this.capacity = capacity;
this.maxReceive = maxReceive;
this.maxExtract = maxExtract;
}
public EnergyStorage readFromNBT(NBTTagCompound nbt) {
this.energy = nbt.getInteger("Energy");
if (energy > capacity) {
energy = capacity;
}
return this;
}
public NBTTagCompound writeToNBT(NBTTagCompound nbt) {
if (energy < 0) {
energy = 0;
}
nbt.setInteger("Energy", energy);
return nbt;
}
public void setCapacity(int capacity) {
this.capacity = capacity;
if (energy > capacity) {
energy = capacity;
}
}
public void setMaxTransfer(int maxTransfer) {
setMaxReceive(maxTransfer);
setMaxExtract(maxTransfer);
}
public void setMaxReceive(int maxReceive) {
this.maxReceive = maxReceive;
}
public void setMaxExtract(int maxExtract) {
this.maxExtract = maxExtract;
}
public int getMaxReceive() {
return maxReceive;
}
public int getMaxExtract() {
return maxExtract;
}
/**
* This function is included to allow for server -> client sync. Do not call this externally to the containing Tile Entity, as not all IEnergyHandlers are
* guaranteed to have it.
*
* @param energy
*/
public void setEnergyStored(int energy) {
this.energy = energy;
if (this.energy > capacity) {
this.energy = capacity;
} else if (this.energy < 0) {
this.energy = 0;
}
}
/**
* This function is included to allow the containing tile to directly and efficiently modify the energy contained in the EnergyStorage. Do not rely on this
* externally, as not all IEnergyHandlers are guaranteed to have it.
*
* @param energy
*/
public void modifyEnergyStored(int energy) {
this.energy += energy;
if (this.energy > capacity) {
this.energy = capacity;
} else if (this.energy < 0) {
this.energy = 0;
}
}
/* IEnergyStorage */
@Override
public int receiveEnergy(int maxReceive, boolean simulate) {
int energyReceived = Math.min(capacity - energy, Math.min(this.maxReceive, maxReceive));
if (!simulate) {
energy += energyReceived;
}
return energyReceived;
}
@Override
public int extractEnergy(int maxExtract, boolean simulate) {
int energyExtracted = Math.min(energy, Math.min(this.maxExtract, maxExtract));
if (!simulate) {
energy -= energyExtracted;
}
return energyExtracted;
}
@Override
public int getEnergyStored() {
return energy;
}
@Override
public int getMaxEnergyStored() {
return capacity;
}
}

View file

@ -0,0 +1,21 @@
package cofh.api.energy;
import net.minecraftforge.common.util.ForgeDirection;
/**
* Implement this interface on TileEntities which should connect to energy transportation blocks. This is intended for blocks which generate energy but do not
* accept it; otherwise just use IEnergyHandler.
*
* Note that {@link IEnergyHandler} is an extension of this.
*
* @author King Lemming
*
*/
public interface IEnergyConnection {
/**
* Returns TRUE if the TileEntity can connect on a given side.
*/
boolean canConnectEnergy(ForgeDirection from);
}

View file

@ -0,0 +1,52 @@
package cofh.api.energy;
import net.minecraft.item.ItemStack;
/**
* Implement this interface on Item classes that support external manipulation of their internal energy storages.
*
* A reference implementation is provided {@link ItemEnergyContainer}.
*
* @author King Lemming
*
*/
public interface IEnergyContainerItem {
/**
* Adds energy to a container item. Returns the quantity of energy that was accepted. This should always return 0 if the item cannot be externally charged.
*
* @param container
* ItemStack to be charged.
* @param maxReceive
* Maximum amount of energy to be sent into the item.
* @param simulate
* If TRUE, the charge will only be simulated.
* @return Amount of energy that was (or would have been, if simulated) received by the item.
*/
int receiveEnergy(ItemStack container, int maxReceive, boolean simulate);
/**
* Removes energy from a container item. Returns the quantity of energy that was removed. This should always return 0 if the item cannot be externally
* discharged.
*
* @param container
* ItemStack to be discharged.
* @param maxExtract
* Maximum amount of energy to be extracted from the item.
* @param simulate
* If TRUE, the discharge will only be simulated.
* @return Amount of energy that was (or would have been, if simulated) extracted from the item.
*/
int extractEnergy(ItemStack container, int maxExtract, boolean simulate);
/**
* Get the amount of energy currently stored in the container item.
*/
int getEnergyStored(ItemStack container);
/**
* Get the max amount of energy that can be stored in the container item.
*/
int getMaxEnergyStored(ItemStack container);
}

View file

@ -0,0 +1,51 @@
package cofh.api.energy;
import net.minecraftforge.common.util.ForgeDirection;
/**
* Implement this interface on TileEntities which should handle energy, generally storing it in one or more internal {@link IEnergyStorage} objects.
*
* A reference implementation is provided {@link TileEnergyHandler}.
*
* @author King Lemming
*
*/
public interface IEnergyHandler extends IEnergyConnection {
/**
* Add energy to an IEnergyHandler, internal distribution is left entirely to the IEnergyHandler.
*
* @param from
* Orientation the energy is received from.
* @param maxReceive
* Maximum amount of energy to receive.
* @param simulate
* If TRUE, the charge will only be simulated.
* @return Amount of energy that was (or would have been, if simulated) received.
*/
int receiveEnergy(ForgeDirection from, int maxReceive, boolean simulate);
/**
* Remove energy from an IEnergyHandler, internal distribution is left entirely to the IEnergyHandler.
*
* @param from
* Orientation the energy is extracted from.
* @param maxExtract
* Maximum amount of energy to extract.
* @param simulate
* If TRUE, the extraction will only be simulated.
* @return Amount of energy that was (or would have been, if simulated) extracted.
*/
int extractEnergy(ForgeDirection from, int maxExtract, boolean simulate);
/**
* Returns the amount of energy currently stored.
*/
int getEnergyStored(ForgeDirection from);
/**
* Returns the maximum amount of energy that can be stored.
*/
int getMaxEnergyStored(ForgeDirection from);
}

View file

@ -0,0 +1,45 @@
package cofh.api.energy;
/**
* An energy storage is the unit of interaction with Energy inventories.
*
* A reference implementation can be found at {@link EnergyStorage}.
*
* @author King Lemming
*
*/
public interface IEnergyStorage {
/**
* Adds energy to the storage. Returns quantity of energy that was accepted.
*
* @param maxReceive
* Maximum amount of energy to be inserted.
* @param simulate
* If TRUE, the insertion will only be simulated.
* @return Amount of energy that was (or would have been, if simulated) accepted by the storage.
*/
int receiveEnergy(int maxReceive, boolean simulate);
/**
* Removes energy from the storage. Returns quantity of energy that was removed.
*
* @param maxExtract
* Maximum amount of energy to be extracted.
* @param simulate
* If TRUE, the extraction will only be simulated.
* @return Amount of energy that was (or would have been, if simulated) extracted from the storage.
*/
int extractEnergy(int maxExtract, boolean simulate);
/**
* Returns the amount of energy currently stored.
*/
int getEnergyStored();
/**
* Returns the maximum amount of energy that can be stored.
*/
int getMaxEnergyStored();
}

View file

@ -0,0 +1,110 @@
package cofh.api.energy;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
/**
* Reference implementation of {@link IEnergyContainerItem}. Use/extend this or implement your own.
*
* @author King Lemming
*
*/
public class ItemEnergyContainer extends Item implements IEnergyContainerItem {
protected int capacity;
protected int maxReceive;
protected int maxExtract;
public ItemEnergyContainer() {
}
public ItemEnergyContainer(int capacity) {
this(capacity, capacity, capacity);
}
public ItemEnergyContainer(int capacity, int maxTransfer) {
this(capacity, maxTransfer, maxTransfer);
}
public ItemEnergyContainer(int capacity, int maxReceive, int maxExtract) {
this.capacity = capacity;
this.maxReceive = maxReceive;
this.maxExtract = maxExtract;
}
public ItemEnergyContainer setCapacity(int capacity) {
this.capacity = capacity;
return this;
}
public void setMaxTransfer(int maxTransfer) {
setMaxReceive(maxTransfer);
setMaxExtract(maxTransfer);
}
public void setMaxReceive(int maxReceive) {
this.maxReceive = maxReceive;
}
public void setMaxExtract(int maxExtract) {
this.maxExtract = maxExtract;
}
/* IEnergyContainerItem */
@Override
public int receiveEnergy(ItemStack container, int maxReceive, boolean simulate) {
if (container.stackTagCompound == null) {
container.stackTagCompound = new NBTTagCompound();
}
int energy = container.stackTagCompound.getInteger("Energy");
int energyReceived = Math.min(capacity - energy, Math.min(this.maxReceive, maxReceive));
if (!simulate) {
energy += energyReceived;
container.stackTagCompound.setInteger("Energy", energy);
}
return energyReceived;
}
@Override
public int extractEnergy(ItemStack container, int maxExtract, boolean simulate) {
if (container.stackTagCompound == null || !container.stackTagCompound.hasKey("Energy")) {
return 0;
}
int energy = container.stackTagCompound.getInteger("Energy");
int energyExtracted = Math.min(energy, Math.min(this.maxExtract, maxExtract));
if (!simulate) {
energy -= energyExtracted;
container.stackTagCompound.setInteger("Energy", energy);
}
return energyExtracted;
}
@Override
public int getEnergyStored(ItemStack container) {
if (container.stackTagCompound == null || !container.stackTagCompound.hasKey("Energy")) {
return 0;
}
return container.stackTagCompound.getInteger("Energy");
}
@Override
public int getMaxEnergyStored(ItemStack container) {
return capacity;
}
}

View file

@ -0,0 +1,62 @@
package cofh.api.energy;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
/**
* Reference implementation of {@link IEnergyHandler}. Use/extend this or implement your own.
*
* @author King Lemming
*
*/
public class TileEnergyHandler extends TileEntity implements IEnergyHandler {
protected EnergyStorage storage = new EnergyStorage(32000);
@Override
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
storage.readFromNBT(nbt);
}
@Override
public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
storage.writeToNBT(nbt);
}
/* IEnergyHandler */
@Override
public boolean canConnectEnergy(ForgeDirection from) {
return true;
}
@Override
public int receiveEnergy(ForgeDirection from, int maxReceive, boolean simulate) {
return storage.receiveEnergy(maxReceive, simulate);
}
@Override
public int extractEnergy(ForgeDirection from, int maxExtract, boolean simulate) {
return storage.extractEnergy(maxExtract, simulate);
}
@Override
public int getEnergyStored(ForgeDirection from) {
return storage.getEnergyStored();
}
@Override
public int getMaxEnergyStored(ForgeDirection from) {
return storage.getMaxEnergyStored();
}
}

View file

@ -0,0 +1,269 @@
package coloredlightscore.src.api;
import java.util.Random;
import net.minecraft.block.Block;
import cpw.mods.fml.common.FMLLog;
/**
* Public API for ColoredLightsCore
*
* @author CptSpaceToaster
*
*/
public class CLApi
{
public static float l[] = new float[] { 0F, 1F / 15, 2F / 15, 3F / 15, 4F / 15, 5F / 15, 6F / 15, 7F / 15, 8F / 15, 9F / 15, 10F / 15, 11F / 15, 12F / 15,
13F / 15, 14F / 15, 1F };
public static int r[] = new int[] { 0, 15, 0, 8, 0, 10, 0, 5, 10, 15, 8, 15, 0, 15, 15, 15 };
public static int g[] = new int[] { 0, 0, 15, 3, 0, 0, 15, 5, 10, 10, 15, 15, 8, 0, 12, 15 };
public static int b[] = new int[] { 0, 0, 0, 0, 15, 15, 15, 5, 10, 13, 0, 0, 15, 15, 10, 15 };
public static Random rand = new Random();
/**
* Computes a 20-bit lighting word, containing red, green, blue, and brightness settings. Allows overriding of the
* Minecraft brightness value. This value can be used directly for Block.lightValue
*
* Word format: 0RRRR 0GGGG 0BBBB 0LLLL
*
* @param r
* Red intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @param g
* Green intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @param b
* Blue intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @param currentLightValue
* The existing lightValue of a block. Only the lower-most 4 bits of this parameter are used.
* @return Integer describing RGBL color for a block
*/
public static int makeRGBLightValue(float r, float g, float b, float currentLightValue)
{
// Clamp color channels
if ( r < 0.0f )
r = 0.0f;
else if ( r > 1.0f )
r = 1.0f;
if ( g < 0.0f )
g = 0.0f;
else if ( g > 1.0f )
g = 1.0f;
if ( b < 0.0f )
b = 0.0f;
else if ( b > 1.0f )
b = 1.0f;
// if (currentLightValue != Math.max(r, Math.max(g, b))) {
// FMLLog.warning("One of the color value should be equal to Current Light Brightness, but not exceed it");
// FMLLog.warning("r: " + r + " g: " + g + " b: " + b + " l: " + currentLightValue);
// }
int brightness = (int) (currentLightValue * 15.0f);
brightness &= 15;
return brightness | ((((int) (15.0F * b)) << 15) + (((int) (15.0F * g)) << 10) + (((int) (15.0F * r)) << 5));
}
/**
* Computes a 20-bit lighting word, containing red, green, blue, and brightness settings. Allows overriding of the
* Minecraft brightness value. This value can be used directly for Block.lightValue
*
* Word format: 0RRRR 0GGGG 0BBBB 0LLLL
*
* @param r
* Red intensity, 0 to 15. Resolution is 4 bits.
* @param g
* Green intensity, 0 to 15. Resolution is 4 bits.
* @param b
* Blue intensity, 0 to 15. Resolution is 4 bits.
* @param brightness
* The existing lightValue of a block. Only the lower-most 4 bits of this parameter are used.
* @return Integer describing RGBL color for a block
*/
public static int makeRGBLightValue(int r, int g, int b, int brightness)
{
// Clamp color channels
if ( r < 0 )
r = 0;
else if ( r > 15 )
r = 15;
if ( g < 0 )
g = 0;
else if ( g > 15 )
g = 15;
if ( b < 0 )
b = 0;
else if ( b > 15 )
b = 15;
brightness &= 15;
if ( brightness != Math.max( r, Math.max( g, b ) ) )
{
FMLLog.warning( "One of the color value should be equal to Current Light Brightness, but not exceed it" );
FMLLog.warning( "r: " + r + " g: " + g + " b: " + b + " l: " + brightness );
}
return brightness | ((b << 15) + (g << 10) + (r << 5));
}
/**
* Computes a 20-bit lighting word, containing red, green, blue settings, and brightness settings. Automatically
* computes the Minecraft brightness value using the brightest of the r, g and b channels. This value can be used
* directly for Block.lightValue
*
* Word format: 0RRRR 0GGGG 0BBBB 0LLLL
*
* @param r
* Red intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @param g
* Green intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @param b
* Blue intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @return Integer describing RGB color for a block
*/
public static int makeRGBLightValue(float r, float g, float b)
{
// Clamp color channels
if ( r < 0.0f )
r = 0.0f;
else if ( r > 1.0f )
r = 1.0f;
if ( g < 0.0f )
g = 0.0f;
else if ( g > 1.0f )
g = 1.0f;
if ( b < 0.0f )
b = 0.0f;
else if ( b > 1.0f )
b = 1.0f;
int brightness = (int) (15.0f * Math.max( Math.max( r, g ), b ));
return brightness | ((((int) (15.0F * b)) << 15) + (((int) (15.0F * g)) << 10) + (((int) (15.0F * r)) << 5));
}
/**
* Computes a 20-bit lighting word, containing red, green, blue settings, and brightness settings. Automatically
* computes the Minecraft brightness value using the brightest of the r, g and b channels. This value can be used
* directly for Block.lightValue
*
* Word format: 0RRRR 0GGGG 0BBBB 0LLLL
*
* @param r
* Red intensity, 0 to 15. Resolution is 4 bits.
* @param g
* Green intensity, 0 to 15. Resolution is 4 bits.
* @param b
* Blue intensity, 0 to 15. Resolution is 4 bits.
* @return Integer describing RGB color for a block
*/
public static int makeRGBLightValue(int r, int g, int b)
{
// Clamp color channels
if ( r < 0 )
r = 0;
else if ( r > 15 )
r = 15;
if ( g < 0 )
g = 0;
else if ( g > 15 )
g = 15;
if ( b < 0 )
b = 0;
else if ( b > 15 )
b = 15;
int brightness = Math.max( Math.max( r, g ), b );
return brightness | ((b << 15) + (g << 10) + (r << 5));
}
/**
* Sets the lighting colors for a given block.
*
* @param block
* The block to set color on
* @param r
* Red intensity, 0 to 15. Resolution is 4 bits.
* @param g
* Green intensity, 0 to 15. Resolution is 4 bits.
* @param b
* Blue intensity, 0 to 15. Resolution is 4 bits.
* @param lightValue
* The Minecraft brightness to set for the block, 0 to 15.
* @return Reference to the block passed in.
*/
public static Block setBlockColorRGB(Block block, int r, int g, int b, int lightValue)
{
// block.lightValue = makeRGBLightValue(r, g, b, lightValue);
return block;
}
/**
* Sets the lighting colors for a given block.
*
* @param block
* The block to set color on
* @param r
* Red intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @param g
* Green intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @param b
* Blue intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @param lightValue
* The Minecraft brightness to set for the block, 0.0f to 1.0f.
* @return Reference to the block passed in.
*/
public static Block setBlockColorRGB(Block block, float r, float g, float b, float lightValue)
{
// block.lightValue = makeRGBLightValue(r, g, b, lightValue);
return block;
}
/**
* Sets the lighting colors for a given block. Does not alter/recompute the brightness.
*
* @param block
* The block to set color on
* @param r
* Red intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @param g
* Green intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @param b
* Blue intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @return Reference to the block passed in.
*/
public static Block setBlockColorRGB(Block block, int r, int g, int b)
{
// block.lightValue = makeRGBLightValue( r, g, b, block.lightValue );
return block;
}
/**
* Sets the lighting colors for a given block. Does not alter/recompute the brightness.
*
* @param block
* The block to set color on
* @param r
* Red intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @param g
* Green intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @param b
* Blue intensity, 0.0f to 1.0f. Resolution is 4 bits.
* @return Reference to the block passed in.
*/
public static Block setBlockColorRGB(Block block, float r, float g, float b)
{
// block.lightValue = makeRGBLightValue( r, g, b, block.lightValue / 15.0f );
return block;
}
}

View file

@ -0,0 +1,29 @@
package gregtechmod.api.interfaces;
import net.minecraft.item.ItemStack;
/**
* You are allowed to include this File in your Download, as i will not change it.
*/
public interface IDigitalChest extends IHasWorldObjectAndCoords {
/**
* Is this even a TileEntity of a Digital Chest?
* I need things like this Function for MetaTileEntities, you MUST check this!!!
* Do not assume that it's a Digital Chest or similar Device, when it just implements this Interface.
*/
public boolean isDigitalChest();
/**
* Gives an Array of Stacks with Size (of all the Data-stored Items) of the correspondent Item kinds (regular QChests have only one)
* Does NOT include the 64 "ready" Items inside the Slots, and neither the 128 Items in the overflow Buffer.
*/
public ItemStack[] getStoredItemData();
/**
* A generic Interface for just setting the amount of contained Items
*/
public void setItemCount(int aCount);
/**
* Gets the maximum Item count for this QChest alike Storage. This applies to the Data-Storage, not for the up to 192 buffered Items!
*/
public int getMaxItemCount();
}

View file

@ -0,0 +1,75 @@
package gregtechmod.api.interfaces;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
/**
* This is a bunch of Functions my TileEntities provide, to make life much easier, and to get rid of internal TileEntity stuff.
*/
public interface IHasWorldObjectAndCoords {
public World getWorld();
public int getXCoord();
public int getYCoord();
public int getZCoord();
public boolean isServerSide();
public boolean isClientSide();
public int getRandomNumber(int aRange);
public TileEntity getTileEntity(int aX, int aY, int aZ);
public TileEntity getTileEntityOffset(int aX, int aY, int aZ);
public TileEntity getTileEntityAtSide(byte aSide);
public TileEntity getTileEntityAtSideAndDistance(byte aSide, int aDistance);
public IInventory getIInventory(int aX, int aY, int aZ);
public IInventory getIInventoryOffset(int aX, int aY, int aZ);
public IInventory getIInventoryAtSide(byte aSide);
public IInventory getIInventoryAtSideAndDistance(byte aSide, int aDistance);
public short getBlockID(int aX, int aY, int aZ);
public short getBlockIDOffset(int aX, int aY, int aZ);
public short getBlockIDAtSide(byte aSide);
public short getBlockIDAtSideAndDistance(byte aSide, int aDistance);
public byte getMetaID(int aX, int aY, int aZ);
public byte getMetaIDOffset(int aX, int aY, int aZ);
public byte getMetaIDAtSide(byte aSide);
public byte getMetaIDAtSideAndDistance(byte aSide, int aDistance);
public byte getLightLevel(int aX, int aY, int aZ);
public byte getLightLevelOffset(int aX, int aY, int aZ);
public byte getLightLevelAtSide(byte aSide);
public byte getLightLevelAtSideAndDistance(byte aSide, int aDistance);
public boolean getSky(int aX, int aY, int aZ);
public boolean getSkyOffset(int aX, int aY, int aZ);
public boolean getSkyAtSide(byte aSide);
public boolean getSkyAtSideAndDistance(byte aSide, int aDistance);
public BiomeGenBase getBiome(int aX, int aZ);
/**
* Function of the regular TileEntity
*/
public void writeToNBT(NBTTagCompound aNBT);
/**
* Function of the regular TileEntity
*/
public void readFromNBT(NBTTagCompound aNBT);
/**
* Function of the regular TileEntity
*/
public boolean isInvalid();
/**
* Opens GUI-ID of any Mod
*/
public void openGUI(EntityPlayer aPlayer, int aID, Object aMod);
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2013 Andrew Crocker
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package invtweaks.api;
import java.util.Collection;
import java.util.List;
import java.util.Random;
public interface IItemTree {
public void registerOre(String category, String name, String oreName, int order);
boolean matches(List<IItemTreeItem> items, String keyword);
boolean isKeywordValid(String keyword);
Collection<IItemTreeCategory> getAllCategories();
IItemTreeCategory getRootCategory();
IItemTreeCategory getCategory(String keyword);
boolean isItemUnknown(String id, int damage);
List<IItemTreeItem> getItems(String id, int damage);
List<IItemTreeItem> getItems(String name);
IItemTreeItem getRandomItem(Random r);
boolean containsItem(String name);
boolean containsCategory(String name);
void setRootCategory(IItemTreeCategory category);
IItemTreeCategory addCategory(String parentCategory, String newCategory) throws NullPointerException;
void addCategory(String parentCategory, IItemTreeCategory newCategory) throws NullPointerException;
IItemTreeItem addItem(String parentCategory, String name, String id, int damage, int order)
throws NullPointerException;
void addItem(String parentCategory, IItemTreeItem newItem) throws NullPointerException;
int getKeywordDepth(String keyword);
int getKeywordOrder(String keyword);
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2013 Andrew Crocker
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package invtweaks.api;
import java.util.Collection;
import java.util.List;
public interface IItemTreeCategory {
boolean contains(IItemTreeItem item);
void addCategory(IItemTreeCategory category);
void addItem(IItemTreeItem item);
Collection<IItemTreeCategory> getSubCategories();
Collection<List<IItemTreeItem>> getItems();
String getName();
int getCategoryOrder();
int findCategoryOrder(String keyword);
int findKeywordDepth(String keyword);
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2013 Andrew Crocker
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package invtweaks.api;
public interface IItemTreeItem extends Comparable<IItemTreeItem> {
String getName();
String getId();
int getDamage();
int getOrder();
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2013 Andrew Crocker
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package invtweaks.api;
import java.util.EventListener;
public interface IItemTreeListener extends EventListener {
void onTreeLoaded(IItemTree tree);
}

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2013 Andrew Crocker
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package invtweaks.api;
import net.minecraft.item.ItemStack;
/**
* Interface to access functions exposed by Inventory Tweaks
* <p/>
* The main @Mod instance of the mod implements this interface, so a refernce to it can
* be obtained via @Instance("inventorytweaks") or methods in cpw.mods.fml.common.Loader
* <p/>
* All of these functions currently have no effect if called on a dedicated server.
*/
public interface InvTweaksAPI {
/**
* Add a listener for ItemTree load events
*
* @param listener
*/
void addOnLoadListener(IItemTreeListener listener);
/**
* Remove a listener for ItemTree load events
*
* @param listener
* @return true if the listener was previously added
*/
boolean removeOnLoadListener(IItemTreeListener listener);
/**
* Toggle sorting shortcut state.
*
* @param enabled
*/
void setSortKeyEnabled(boolean enabled);
/**
* Toggle sorting shortcut supression.
* Unlike setSortKeyEnabled, this flag is automatically cleared when GUIs are closed.
*
* @param enabled
*/
void setTextboxMode(boolean enabled);
/**
* Compare two items using the default (non-rule based) algorithm,
* sutable for an implementation of Comparator&lt;ItemStack&gt;.
*
* @param i
* @param j
* @return A value with a sign representing the relative order of the item stacks
*/
int compareItems(ItemStack i, ItemStack j);
}

View file

@ -0,0 +1,28 @@
package invtweaks.api.container;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* A marker for containers that have a chest-like persistant storage component. Enables the Inventroy Tweaks sorting
* buttons for this container.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ChestContainer {
// Size of a chest row
int rowSize() default 9;
// Uses 'large chest' mode for sorting buttons
// (Renders buttons vertically down the right side of the GUI)
boolean isLargeChest() default false;
// Annotation for method to get size of a chest row if it is not a fixed size for this container class
// Signature int func()
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RowSizeCallback {
}
}

View file

@ -0,0 +1,86 @@
/*
* Copyright (c) 2013 Andrew Crocker
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package invtweaks.api.container;
/**
* Names for specific parts of containers. For unknown container types (such as mod containers), only INVENTORY and
* CHEST sections are available.
*/
public enum ContainerSection {
/**
* The player's inventory
*/
INVENTORY,
/**
* The player's inventory (only the hotbar)
*/
INVENTORY_HOTBAR,
/**
* The player's inventory (all except the hotbar)
*/
INVENTORY_NOT_HOTBAR,
/**
* The chest or dispenser contents. Also used for unknown container contents.
*/
CHEST,
/**
* The crafting input
*/
CRAFTING_IN,
/**
* The crafting input, for containters that store it internally
*/
CRAFTING_IN_PERSISTENT,
/**
* The crafting output
*/
CRAFTING_OUT,
/**
* The armor slots
*/
ARMOR,
/**
* The furnace input
*/
FURNACE_IN,
/**
* The furnace output
*/
FURNACE_OUT,
/**
* The furnace fuel
*/
FURNACE_FUEL,
/**
* The enchantment table slot
*/
ENCHANTMENT,
/**
* The three bottles slots in brewing tables
*/
BREWING_BOTTLES,
/**
* The top slot in brewing tables
*/
BREWING_INGREDIENT
}

View file

@ -0,0 +1,16 @@
package invtweaks.api.container;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* A marker for a method to call which returns the set of ContainerSections for this container.
* <p/>
* Signature of the method should be Map<ContainerSection, List<Slot>> func()
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ContainerSectionCallback {
}

View file

@ -0,0 +1,15 @@
package invtweaks.api.container;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Use this annotation to override inherited annotation properties and mark a Container as unsortable.
* This effect is inherited as well.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IgnoreContainer {
}

View file

@ -0,0 +1,20 @@
package invtweaks.api.container;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* A marker for containers that need special treatment, such as crafting inputs or alternate player inventory positions,
* but do not have a chest-like component.
* <p/>
* Does not enable the Inventory Tweaks sorting buttons for this container.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface InventoryContainer {
// Set to true if the Inventory Tweaks options button should be shown for this container.
// (For instance, if you are replacing a vanilla container such as the player's inventory)
boolean showOptions() default true;
}

View file

@ -0,0 +1,28 @@
package mekanism.api;
import mekanism.api.gas.Gas;
import mekanism.common.util.StackUtils;
import net.minecraft.item.ItemStack;
public class AdvancedInput
{
public ItemStack itemStack;
public Gas gasType;
public AdvancedInput(ItemStack item, Gas gas)
{
itemStack = item;
gasType = gas;
}
public boolean isValid()
{
return itemStack != null && gasType != null;
}
public boolean matches(AdvancedInput input)
{
return StackUtils.equalsWildcard(itemStack, input.itemStack) && input.itemStack.stackSize >= itemStack.stackSize;
}
}

View file

@ -0,0 +1,38 @@
package mekanism.api;
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
public class BlockInfo
{
public Block block;
public int meta;
public BlockInfo(Block b, int j)
{
block = b;
meta = j;
}
public static BlockInfo get(ItemStack stack)
{
return new BlockInfo(Block.getBlockFromItem(stack.getItem()), stack.getItemDamage());
}
@Override
public boolean equals(Object obj)
{
return obj instanceof BlockInfo &&
((BlockInfo)obj).block == block &&
((BlockInfo)obj).meta == meta;
}
@Override
public int hashCode()
{
int code = 1;
code = 31 * code + block.getUnlocalizedName().hashCode();
code = 31 * code + meta;
return code;
}
}

View file

@ -0,0 +1,49 @@
package mekanism.api;
import java.util.Random;
import mekanism.common.util.StackUtils;
import net.minecraft.item.ItemStack;
public class ChanceOutput
{
private static Random rand = new Random();
public ItemStack primaryOutput;
public ItemStack secondaryOutput;
public double secondaryChance;
public ChanceOutput(ItemStack primary, ItemStack secondary, double chance)
{
primaryOutput = primary;
secondaryOutput = secondary;
secondaryChance = chance;
}
public ChanceOutput(ItemStack primary)
{
primaryOutput = primary;
}
public boolean checkSecondary()
{
return rand.nextDouble() <= secondaryChance;
}
public boolean hasPrimary()
{
return primaryOutput != null;
}
public boolean hasSecondary()
{
return secondaryOutput != null;
}
public ChanceOutput copy()
{
return new ChanceOutput(StackUtils.copy(primaryOutput), StackUtils.copy(secondaryOutput), secondaryChance);
}
}

View file

@ -0,0 +1,116 @@
package mekanism.api;
import mekanism.api.gas.GasStack;
import mekanism.api.gas.GasTank;
/**
* An input of gasses for recipe use.
* @author aidancbrady
*
*/
public class ChemicalPair
{
/** The left gas of this chemical input */
public GasStack leftGas;
/** The right gas of this chemical input */
public GasStack rightGas;
/**
* Creates a chemical input with two defined gasses.
* @param left - left gas
* @param right - right gas
*/
public ChemicalPair(GasStack left, GasStack right)
{
leftGas = left;
rightGas = right;
}
/**
* If this is a valid ChemicalPair
* @return
*/
public boolean isValid()
{
return leftGas != null && rightGas != null;
}
/**
* Whether or not the defined input contains the same gasses and at least the required amount of the defined gasses as this input.
* @param input - input to check
* @return if the input meets this input's requirements
*/
public boolean meetsInput(ChemicalPair input)
{
return meets(input) || meets(input.swap());
}
/**
* Swaps the right gas and left gas of this input.
* @return a swapped ChemicalInput
*/
public ChemicalPair swap()
{
return new ChemicalPair(rightGas, leftGas);
}
/**
* Draws the needed amount of gas from each tank.
* @param leftTank - left tank to draw from
* @param rightTank - right tank to draw from
*/
public void draw(GasTank leftTank, GasTank rightTank)
{
if(meets(new ChemicalPair(leftTank.getGas(), rightTank.getGas())))
{
leftTank.draw(leftGas.amount, true);
rightTank.draw(rightGas.amount, true);
}
else if(meets(new ChemicalPair(rightTank.getGas(), leftTank.getGas())))
{
leftTank.draw(rightGas.amount, true);
rightTank.draw(leftGas.amount, true);
}
}
/**
* Whether or not one of this ChemicalInput's GasStack entry's gas type is equal to the gas type of the given gas.
* @param stack - stack to check
* @return if the stack's gas type is contained in this ChemicalInput
*/
public boolean containsType(GasStack stack)
{
if(stack == null || stack.amount == 0)
{
return false;
}
return stack.isGasEqual(leftGas) || stack.isGasEqual(rightGas);
}
/**
* Actual implementation of meetsInput(), performs the checks.
* @param input - input to check
* @return if the input meets this input's requirements
*/
private boolean meets(ChemicalPair input)
{
if(input == null || !input.isValid())
{
return false;
}
if(input.leftGas.getGas() != leftGas.getGas() || input.rightGas.getGas() != rightGas.getGas())
{
return false;
}
return input.leftGas.amount >= leftGas.amount && input.rightGas.amount >= rightGas.amount;
}
public ChemicalPair copy()
{
return new ChemicalPair(leftGas.copy(), rightGas.copy());
}
}

View file

@ -0,0 +1,108 @@
package mekanism.api;
import net.minecraft.entity.Entity;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
/**
* Chunk3D - an integer-based way to keep track of and perform operations on chunks in a Minecraft-based environment. This also takes
* in account the dimension the chunk is in.
* @author aidancbrady
*
*/
public class Chunk3D
{
public int dimensionId;
public int xCoord;
public int zCoord;
/**
* Creates a Chunk3D object from the given x and z coordinates, as well as a dimension.
* @param x - chunk x location
* @param z - chunk z location
* @param dimension - the dimension this Chunk3D is in
*/
public Chunk3D(int x, int z, int dimension)
{
xCoord = x;
zCoord = z;
dimensionId = dimension;
}
/**
* Creates a Chunk3D from an entity based on it's location and dimension.
* @param entity - the entity to get the Chunk3D object from
*/
public Chunk3D(Entity entity)
{
xCoord = ((int)entity.posX) >> 4;
zCoord = ((int)entity.posZ) >> 4;
dimensionId = entity.dimension;
}
/**
* Creates a Chunk3D from a Coord4D based on it's coordinates and dimension.
* @param coord - the Coord4D object to get this Chunk3D from
*/
public Chunk3D(Coord4D coord)
{
xCoord = coord.xCoord >> 4;
zCoord = coord.zCoord >> 4;
dimensionId = coord.dimensionId;
}
/**
* Whether or not this chunk exists in the given world.
* @param world - the world to check in
* @return if the chunk exists
*/
public boolean exists(World world)
{
return world.getChunkProvider().chunkExists(xCoord, zCoord);
}
/**
* Gets a Chunk object corresponding to this Chunk3D's coordinates.
* @param world - the world to get the Chunk object from
* @return the corresponding Chunk object
*/
public Chunk getChunk(World world)
{
return world.getChunkFromChunkCoords(xCoord, zCoord);
}
@Override
public Coord4D clone()
{
return new Coord4D(xCoord, zCoord, dimensionId);
}
@Override
public String toString()
{
return "[Chunk3D: " + xCoord + ", " + zCoord + ", dim=" + dimensionId + "]";
}
@Override
public boolean equals(Object obj)
{
return obj instanceof Chunk3D &&
((Chunk3D)obj).xCoord == xCoord &&
((Chunk3D)obj).zCoord == zCoord &&
((Chunk3D)obj).dimensionId == dimensionId;
}
@Override
public int hashCode()
{
int code = 1;
code = 31 * code + xCoord;
code = 31 * code + zCoord;
code = 31 * code + dimensionId;
return code;
}
}

View file

@ -0,0 +1,358 @@
package mekanism.api;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import net.minecraft.block.Block;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.common.util.ForgeDirection;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
/**
* Coord4D - an integer-based way to keep track of and perform operations on blocks in a Minecraft-based environment. This also takes
* in account the dimension the coordinate is in.
* @author aidancbrady
*
*/
public class Coord4D
{
public int xCoord;
public int yCoord;
public int zCoord;
public int dimensionId;
/**
* Creates a Coord4D WITHOUT a dimensionId. Don't use unless absolutely necessary.
* @param x - x coordinate
* @param y - y coordinate
* @param z - z coordinate
*/
public Coord4D(int x, int y, int z)
{
xCoord = x;
yCoord = y;
zCoord = z;
dimensionId = 0;
}
/**
* Creates a Coord4D from the defined x, y, z, and dimension values.
* @param x - x coordinate
* @param y - y coordinate
* @param z - z coordinate
* @param dimension - dimension ID
*/
public Coord4D(int x, int y, int z, int dimension)
{
xCoord = x;
yCoord = y;
zCoord = z;
dimensionId = dimension;
}
/**
* Gets the metadata of the block representing this Coord4D.
* @param world - world this Coord4D is in
* @return the metadata of this Coord4D's block
*/
public int getMetadata(IBlockAccess world)
{
return world.getBlockMetadata(xCoord, yCoord, zCoord);
}
/**
* Gets the TileEntity of the block representing this Coord4D.
* @param world - world this Coord4D is in
* @return the TileEntity of this Coord4D's block
*/
public TileEntity getTileEntity(IBlockAccess world)
{
if(world instanceof World && !exists((World)world))
{
return null;
}
return world.getTileEntity(xCoord, yCoord, zCoord);
}
/**
* Gets the Block value of the block representing this Coord4D.
* @param world - world this Coord4D is in
* @return the Block value of this Coord4D's block
*/
public Block getBlock(IBlockAccess world)
{
if(world instanceof World && !exists((World)world))
{
return null;
}
return world.getBlock(xCoord, yCoord, zCoord);
}
/**
* Writes this Coord4D's data to an NBTTagCompound.
* @param nbtTags - tag compound to write to
* @return the tag compound with this Coord4D's data
*/
public NBTTagCompound write(NBTTagCompound nbtTags)
{
nbtTags.setInteger("x", xCoord);
nbtTags.setInteger("y", yCoord);
nbtTags.setInteger("z", zCoord);
nbtTags.setInteger("dimensionId", dimensionId);
return nbtTags;
}
/**
* Writes this Coord4D's data to an ArrayList for packet transfer.
* @param data - the ArrayList to add the data to
*/
public void write(ArrayList data)
{
data.add(xCoord);
data.add(yCoord);
data.add(zCoord);
data.add(dimensionId);
}
/**
* Writes this Coord4D's data to a ByteBuf for packet transfer.
* @param dataStream - the ByteBuf to add the data to
*/
public void write(ByteBuf dataStream)
{
dataStream.writeInt(xCoord);
dataStream.writeInt(yCoord);
dataStream.writeInt(zCoord);
dataStream.writeInt(dimensionId);
}
/**
* Translates this Coord4D by the defined x, y, and z values.
* @param x - x value to translate
* @param y - y value to translate
* @param z - z value to translate
* @return translated Coord4D
*/
public Coord4D translate(int x, int y, int z)
{
xCoord += x;
yCoord += y;
zCoord += z;
return this;
}
/**
* Creates and returns a new Coord4D translated to the defined offsets of the side.
* @param side - side to translate this Coord4D to
* @return translated Coord4D
*/
public Coord4D getFromSide(ForgeDirection side)
{
return getFromSide(side, 1);
}
public Coord4D getFromSide(ForgeDirection side, int amount)
{
return new Coord4D(xCoord+(side.offsetX*amount), yCoord+(side.offsetY*amount), zCoord+(side.offsetZ*amount), dimensionId);
}
/**
* Returns a new Coord4D from a defined TileEntity's xCoord, yCoord and zCoord values.
* @param tileEntity - TileEntity at the location that will represent this Coord4D
* @return the Coord4D object from the TileEntity
*/
public static Coord4D get(TileEntity tileEntity)
{
return new Coord4D(tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord, tileEntity.getWorldObj().provider.dimensionId);
}
/**
* Returns a new Coord4D from a tag compound.
* @param data - tag compound to read from
* @return the Coord4D from the tag compound
*/
public static Coord4D read(NBTTagCompound tag)
{
return new Coord4D(tag.getInteger("x"), tag.getInteger("y"), tag.getInteger("z"), tag.getInteger("id"));
}
/**
* Returns a new Coord4D from a ByteBuf.
* @param dataStream - data input to read from
* @return the Coord4D from the data input
*/
public static Coord4D read(ByteBuf dataStream)
{
return new Coord4D(dataStream.readInt(), dataStream.readInt(), dataStream.readInt(), dataStream.readInt());
}
/**
* Creates and returns a new Coord4D with values representing the difference between the defined Coord4D
* @param other - the Coord4D to subtract from this
* @return a Coord4D representing the distance between the defined Coord4D
*/
public Coord4D difference(Coord4D other)
{
return new Coord4D(xCoord-other.xCoord, yCoord-other.yCoord, zCoord-other.zCoord, dimensionId);
}
/**
* A method used to find the ForgeDirection represented by the distance of the defined Coord4D. Most likely won't have many
* applicable uses.
* @param other - Coord4D to find the side difference of
* @return ForgeDirection representing the side the defined relative Coord4D is on to this
*/
public ForgeDirection sideDifference(Coord4D other)
{
Coord4D diff = difference(other);
for(ForgeDirection side : ForgeDirection.VALID_DIRECTIONS)
{
if(side.offsetX == diff.xCoord && side.offsetY == diff.yCoord && side.offsetZ == diff.zCoord)
{
return side;
}
}
return ForgeDirection.UNKNOWN;
}
/**
* Gets the distance to a defined Coord4D.
* @param obj - the Coord4D to find the distance to
* @return the distance to the defined Coord4D
*/
public int distanceTo(Coord4D obj)
{
int subX = xCoord - obj.xCoord;
int subY = yCoord - obj.yCoord;
int subZ = zCoord - obj.zCoord;
return (int)MathHelper.sqrt_double(subX * subX + subY * subY + subZ * subZ);
}
/**
* Whether or not the defined side of this Coord4D is visible.
* @param side - side to check
* @param world - world this Coord4D is in
* @return
*/
public boolean sideVisible(ForgeDirection side, IBlockAccess world)
{
return world.isAirBlock(xCoord+side.offsetX, yCoord+side.offsetY, zCoord+side.offsetZ);
}
/**
* Gets a TargetPoint with the defined range from this Coord4D with the appropriate coordinates and dimension ID.
* @param range - the range the packet can be sent in of this Coord4D
* @return TargetPoint relative to this Coord4D
*/
public TargetPoint getTargetPoint(double range)
{
return new TargetPoint(dimensionId, xCoord, yCoord, zCoord, range);
}
/**
* Steps this Coord4D in the defined side's offset without creating a new value.
* @param side - side to step towards
* @return this Coord4D
*/
public Coord4D step(ForgeDirection side)
{
return translate(side.offsetX, side.offsetY, side.offsetZ);
}
/**
* Whether or not the chunk this Coord4D is in exists and is loaded.
* @param world - world this Coord4D is in
* @return the chunk of this Coord4D
*/
public boolean exists(World world)
{
return world.getChunkProvider().chunkExists(xCoord >> 4, zCoord >> 4);
}
/**
* Gets the chunk this Coord4D is in.
* @param world - world this Coord4D is in
* @return the chunk of this Coord4D
*/
public Chunk getChunk(World world)
{
return world.getChunkFromBlockCoords(xCoord, zCoord);
}
/**
* Gets the Chunk3D object with chunk coordinates correlating to this Coord4D's location
* @return Chunk3D with correlating chunk coordinates.
*/
public Chunk3D getChunk3D()
{
return new Chunk3D(this);
}
/**
* Whether or not the block this Coord4D represents is an air block.
* @param world - world this Coord4D is in
* @return if this Coord4D is an air block
*/
public boolean isAirBlock(IBlockAccess world)
{
return world.isAirBlock(xCoord, yCoord, zCoord);
}
/**
* Gets a bounding box that contains the area this Coord4D would take up in a world.
* @return this Coord4D's bounding box
*/
public AxisAlignedBB getBoundingBox()
{
return AxisAlignedBB.getBoundingBox(xCoord, yCoord, zCoord, xCoord+1, yCoord+1, zCoord+1);
}
@Override
public Coord4D clone()
{
return new Coord4D(xCoord, yCoord, zCoord, dimensionId);
}
@Override
public String toString()
{
return "[Coord4D: " + xCoord + ", " + yCoord + ", " + zCoord + ", dim=" + dimensionId + "]";
}
@Override
public boolean equals(Object obj)
{
return obj instanceof Coord4D &&
((Coord4D)obj).xCoord == xCoord &&
((Coord4D)obj).yCoord == yCoord &&
((Coord4D)obj).zCoord == zCoord &&
((Coord4D)obj).dimensionId == dimensionId;
}
@Override
public int hashCode()
{
int code = 1;
code = 31 * code + xCoord;
code = 31 * code + yCoord;
code = 31 * code + zCoord;
code = 31 * code + dimensionId;
return code;
}
}

View file

@ -0,0 +1,112 @@
package mekanism.api;
import net.minecraft.util.StatCollector;
/**
* Simple color enum for adding colors to in-game GUI strings of text.
* @author AidanBrady
*
*/
public enum EnumColor
{
BLACK("\u00a70", "black", "Black", new int[] {0, 0, 0}, 0),
DARK_BLUE("\u00a71", "darkBlue", "Blue", new int[] {0, 0, 170}, 4),
DARK_GREEN("\u00a72", "darkGreen", "Green", new int[] {0, 170, 0}, 2),
DARK_AQUA("\u00a73", "darkAqua", "Cyan", new int[] {0, 170, 170}, 6),
DARK_RED("\u00a74", "darkRed", null, new int[] {170, 0, 0}, -1),
PURPLE("\u00a75", "purple", "Purple", new int[] {170, 0, 170}, 5),
ORANGE("\u00a76", "orange", "Orange", new int[] {255, 170, 0}, 14),
GREY("\u00a77", "grey", "LightGray", new int[] {170, 170, 170}, 7),
DARK_GREY("\u00a78", "darkGrey", "Gray", new int[] {85, 85, 85}, 8),
INDIGO("\u00a79", "indigo", "LightBlue", new int[] {85, 85, 255}, 12),
BRIGHT_GREEN("\u00a7a", "brightGreen", "Lime", new int[] {85, 255, 85}, 10),
AQUA("\u00a7b", "aqua", null, new int[] {85, 255, 255}, -1),
RED("\u00a7c", "red", "Red", new int[] {255, 0, 0}, 1),
PINK("\u00a7d", "pink", "Magenta", new int[] {255, 85, 255}, 13),
YELLOW("\u00a7e", "yellow", "Yellow", new int[] {255, 255, 85}, 11),
WHITE("\u00a7f", "white", "White", new int[] {255, 255, 255}, 15),
//Extras for dye-completeness
BROWN("\u00a76", "brown", "Brown", new int[] {150, 75, 0}, 3),
BRIGHT_PINK("\u00a7d", "brightPink", "Pink", new int[] {255, 192, 203}, 9);
public static EnumColor[] DYES = new EnumColor[] {BLACK, RED, DARK_GREEN, BROWN, DARK_BLUE, PURPLE, DARK_AQUA, GREY, DARK_GREY, BRIGHT_PINK, BRIGHT_GREEN, YELLOW, INDIGO, PINK, ORANGE, WHITE};
/** The color code that will be displayed */
public final String code;
public final int[] rgbCode;
public final int mcMeta;
/** A friendly name of the color. */
public String unlocalizedName;
public String dyeName;
private EnumColor(String s, String n, String dye, int[] rgb, int meta)
{
code = s;
unlocalizedName = n;
dyeName = dye;
rgbCode = rgb;
mcMeta = meta;
}
/**
* Gets the localized name of this color by translating the unlocalized name.
* @return localized name
*/
public String getLocalizedName()
{
return StatCollector.translateToLocal("color." + unlocalizedName);
}
public String getDyeName()
{
return StatCollector.translateToLocal("dye." + unlocalizedName);
}
public String getOreDictName()
{
return dyeName;
}
/**
* Gets the name of this color with it's color prefix code.
* @return the color's name and color prefix
*/
public String getName()
{
return code + getLocalizedName();
}
public String getDyedName()
{
return code + getDyeName();
}
/**
* Gets the 0-1 of this color's RGB value by dividing by 255 (used for OpenGL coloring).
* @param index - R:0, G:1, B:2
* @return the color value
*/
public float getColor(int index)
{
return (float)rgbCode[index]/255F;
}
/**
* Gets the value of this color mapped to MC in-game item colors present in dyes and wool.
* @return mc meta value
*/
public int getMetaValue()
{
return mcMeta;
}
@Override
public String toString()
{
return code;
}
}

View file

@ -0,0 +1,8 @@
package mekanism.api;
public interface IClientTicker
{
public void clientTick();
public boolean needsTicks();
}

View file

@ -0,0 +1,27 @@
package mekanism.api;
import net.minecraft.entity.player.EntityPlayer;
/**
* Implement this in your TileEntity class if your block can be modified by a Configurator.
* @author aidancbrady
*
*/
public interface IConfigurable
{
/**
* Called when a player shift-right clicks this block with a Configurator.
* @param player - the player who clicked the block
* @param side - the side the block was clicked on
* @return whether or not an action was performed
*/
public boolean onSneakRightClick(EntityPlayer player, int side);
/**
* Called when a player right clicks this block with a Configurator.
* @param player - the player who clicked the block
* @param side - the side the block was clicked on
* @return whether or not an action was performed
*/
public boolean onRightClick(EntityPlayer player, int side);
}

View file

@ -0,0 +1,31 @@
package mekanism.api;
import net.minecraft.nbt.NBTTagCompound;
/**
* Implement this in your TileEntity class if you wish for Mekanism filters to be able to store any of their
* information.
* @author aidancbrady
*
*/
public interface IFilterAccess
{
/**
* Collects the TileEntity's filter card data into the parameterized NBTTagCompound.
* @param nbtTags - the NBTTagCompound of the filter card ItemStack
* @return the NBTTagCompound that now contains the TileEntity's filter card data
*/
public NBTTagCompound getFilterData(NBTTagCompound nbtTags);
/**
* Retrieves the TileEntity's data contained in the filter card based on the given NBTTagCompopund.
* @param nbtTags - the NBTTagCompound of the filter card ItemStack
*/
public void setFilterData(NBTTagCompound nbtTags);
/**
* A String name of this TileEntity that will be displayed as the type of data on the filter card.
* @return the String name of this TileEntity
*/
public String getDataType();
}

View file

@ -0,0 +1,11 @@
package mekanism.api;
/**
* Implement this class in a TileEntity if you wish for it to be able to heat up a Salination Plant.
* @author aidancbrady
*
*/
public interface ISalinationSolar
{
public boolean seesSun();
}

View file

@ -0,0 +1,38 @@
package mekanism.api;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
public class ItemInfo
{
public Item item;
public int meta;
public ItemInfo(Item i, int j)
{
item = i;
meta = j;
}
public static ItemInfo get(ItemStack stack)
{
return new ItemInfo(stack.getItem(), stack.getItemDamage());
}
@Override
public boolean equals(Object obj)
{
return obj instanceof BlockInfo &&
((ItemInfo)obj).item == item &&
((ItemInfo)obj).meta == meta;
}
@Override
public int hashCode()
{
int code = 1;
code = 31 * code + item.getUnlocalizedName().hashCode();
code = 31 * code + meta;
return code;
}
}

View file

@ -0,0 +1,71 @@
package mekanism.api;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
/**
* Use this class's 'getItem()' method to retrieve ItemStacks from the 'Mekanism'
* class.
* @author AidanBrady
*
*/
public final class ItemRetriever
{
/** The 'Mekanism' class that items and blocks are retrieved from. */
private static Class Mekanism;
/**
* Attempts to retrieve an ItemStack of an item or block with the declared identifier.
*
* Mekanism identifiers follow an easy-to-remember pattern. All identifiers
* are identical to the String returned by 'getItemName().' None include spaces,
* and all start with a capital letter. The name that shows up in-game can be
* stripped down to identifier form by removing spaces and all non-alphabetic
* characters (,./'=-_). Below is an example:
*
* ItemStack enrichedAlloy = ItemRetriever.getItem("EnrichedAlloy");
*
* The same also works for blocks.
*
* ItemStack refinedObsidian = ItemRetriever.getItem("RefinedObsidian");
*
* Note that for items or blocks that have specific metadata you will need to create
* a new ItemStack with that specified value, as this will only return an ItemStack
* with the meta value '0.'
*
* Make sure you run this in or after FMLPostInitializationEvent runs, because most
* items are registered when FMLInitializationEvent runs. However, some items ARE
* registered later in order to hook into other mods. In a rare circumstance you may
* have to add "after:Mekanism" in the @Mod 'dependencies' annotation.
*
* @param identifier - a String to be searched in the 'Mekanism' class
* @return an ItemStack of the declared identifier, otherwise null.
*/
public static ItemStack getItem(String identifier)
{
try {
if(Mekanism == null)
{
Mekanism = Class.forName("mekanism.common.Mekanism");
}
Object ret = Mekanism.getField(identifier).get(null);
if(ret instanceof Item)
{
return new ItemStack((Item)ret, 1);
}
else if(ret instanceof Block)
{
return new ItemStack((Block)ret, 1);
}
else {
return null;
}
} catch(Exception e) {
System.err.println("Error retrieving item with identifier '" + identifier + "': " + e.getMessage());
return null;
}
}
}

View file

@ -0,0 +1,282 @@
package mekanism.api;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
public class ListUtils
{
public static <V> List<V> inverse(List<V> list)
{
List<V> toReturn = new ArrayList<V>();
for(int i = list.size() - 1; i >= 0; i--)
{
toReturn.add(list.get(i));
}
return toReturn;
}
public static <V> List<V> cap(List<V> list, int cap)
{
List<V> toReturn = new ArrayList<V>();
if(list.size() <= cap)
{
toReturn = copy(list);
}
else {
int count = 0;
for(V obj : list)
{
count++;
toReturn.add(obj);
if(count == cap)
{
break;
}
}
}
return toReturn;
}
public static <V> List<V> copy(List<V> list)
{
List<V> toReturn = new ArrayList<V>();
for(V obj : list)
{
toReturn.add(obj);
}
return toReturn;
}
public static <V> List<V> merge(List<V> listOne, List<V> listTwo)
{
List<V> newList = new ArrayList<V>();
for(V obj : listOne)
{
newList.add(obj);
}
for(V obj : listTwo)
{
newList.add(obj);
}
return newList;
}
public static <V> List<V> capRemains(List<V> list, int cap)
{
List<V> toReturn = new ArrayList<V>();
if(list.size() <= cap)
{
return toReturn;
}
else {
List<V> inverse = inverse(list);
int iterNeeded = list.size() - cap;
int count = 0;
for(V obj : list)
{
count++;
toReturn.add(obj);
if(count == iterNeeded)
{
break;
}
}
return toReturn;
}
}
public static <V> ArrayList<List<V>> split(List<V> list, int divide)
{
int remain = list.size() % divide;
int size = (list.size() - remain) / divide;
ArrayList<List<V>> toReturn = new ArrayList<List<V>>();
for(int i = 0; i < divide; i++)
{
toReturn.add(i, new ArrayList<V>());
}
for(List<V> iterSet : toReturn)
{
List<V> removed = new ArrayList<V>();
int toAdd = size;
if(remain > 0)
{
remain--;
toAdd++;
}
for(V obj : list)
{
if(toAdd == 0)
{
break;
}
iterSet.add(obj);
removed.add(obj);
toAdd--;
}
for(V obj : removed)
{
list.remove(obj);
}
}
return toReturn;
}
public static <V> V getTop(List<V> list)
{
for(V obj : list)
{
return obj;
}
return null;
}
public static <V> List<V> asList(Set<V> set)
{
return (List<V>)Arrays.asList(set.toArray());
}
public static <V> List<V> asList(V... values)
{
return (List<V>)Arrays.asList(values);
}
public static double[] splitDouble(int size, double num)
{
double[] split = new double[size];
for(int i = 0; i < size; i++)
{
double remain = num%size;
double ret = (num-remain)/size;
ret += remain;
split[i] = ret;
num -= remain;
}
return split;
}
public static double[] percent(double[] values)
{
double[] ret = new double[values.length];
double total = 0;
for(double d : values) total += d;
for(int i = 0; i < values.length; i++)
{
ret[i] = values[i]/total;
}
return ret;
}
public static int[] calcPercentInt(double[] percent, int val)
{
int[] ret = new int[percent.length];
for(int i = 0; i < percent.length; i++)
{
ret[i] = (int)Math.round(val*percent[i]);
}
int newTotal = 0;
for(int i : ret) newTotal += i;
int diff = val-newTotal;
if(diff != val)
{
for(int i = 0; i < ret.length; i++)
{
int num = ret[i];
if(diff < 0 && num == 0)
{
continue;
}
if(diff > 0)
{
ret[i]++;
diff--;
}
else if(diff < 0)
{
ret[i]--;
diff++;
}
if(diff == 0)
{
return ret;
}
}
}
return ret;
}
public static int[] splitInt(int size, int num)
{
int[] split = new int[size];
for(int i = 0; i < size; i++)
{
int remain = num%size;
int ret = (num-remain)/size;
ret += remain;
split[i] = ret;
num -= remain;
}
return split;
}
public static double[] percent(int[] values)
{
double[] ret = new double[values.length];
double total = 0;
for(double d : values) total += d;
for(int i = 0; i < values.length; i++)
{
ret[i] = values[i]/total;
}
return ret;
}
}

View file

@ -0,0 +1,45 @@
package mekanism.api;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.oredict.OreDictionary;
public class MekanismAPI
{
//Add a BlockInfo value here if you don't want a certain block to be picked up by cardboard boxes
private static Set<BlockInfo> cardboardBoxIgnore = new HashSet<BlockInfo>();
public static boolean isBlockCompatible(Item item, int meta)
{
for(BlockInfo i : cardboardBoxIgnore)
{
if(i.block == Block.getBlockFromItem(item) && (i.meta == OreDictionary.WILDCARD_VALUE || i.meta == meta))
{
return false;
}
}
return true;
}
public static void addBoxBlacklist(Block block, int meta)
{
cardboardBoxIgnore.add(new BlockInfo(block, meta));
}
public static void removeBoxBlacklist(Block block, int meta)
{
cardboardBoxIgnore.remove(new BlockInfo(block, meta));
}
public static Set<BlockInfo> getBoxIgnore()
{
return cardboardBoxIgnore;
}
public static class BoxBlacklistEvent extends Event {}
}

View file

@ -0,0 +1,191 @@
package mekanism.api;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MathHelper;
/**
* Pos3D - a way of performing operations on objects in a three dimensional environment.
* @author aidancbrady
*
*/
public class Pos3D
{
public double xPos;
public double yPos;
public double zPos;
public Pos3D()
{
this(0, 0, 0);
}
public Pos3D(double x, double y, double z)
{
xPos = x;
yPos = y;
zPos = z;
}
public Pos3D(Coord4D coord)
{
xPos = coord.xCoord;
yPos = coord.yCoord;
zPos = coord.zCoord;
}
/**
* Creates a Pos3D with an entity's posX, posY, and posZ values.
* @param entity - entity to create the Pos3D from
*/
public Pos3D(Entity entity)
{
this(entity.posX, entity.posY, entity.posZ);
}
/**
* Creates a Pos3D with a TileEntity's xCoord, yCoord and zCoord values.
* @param tileEntity - TileEntity to create the Pos3D from
*/
public Pos3D(TileEntity tileEntity)
{
this(tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord);
}
/**
* Creates and returns a Pos3D with values representing the difference between this and the Pos3D in the parameters.
* @param pos - Pos3D to subtract
* @return difference of the two Pos3Ds
*/
public Pos3D diff(Pos3D pos)
{
return new Pos3D(xPos-pos.xPos, yPos-pos.yPos, zPos-pos.zPos);
}
/**
* Creates a new Pos3D from the motion of an entity.
* @param entity
* @return
*/
public static Pos3D fromMotion(Entity entity)
{
return new Pos3D(entity.motionX, entity.motionY, entity.motionZ);
}
/**
* Translates this Pos3D by the defined values.
* @param x - amount to translate on the x axis
* @param y - amount to translate on the y axis
* @param z - amount to translate on the z axis
* @return the translated Pos3D
*/
public Pos3D translate(double x, double y, double z)
{
xPos += x;
yPos += y;
zPos += z;
return this;
}
/**
* Performs the same operation as translate(x, y, z), but with a Pos3D value instead.
* @param pos - Pos3D value to translate by
* @return translated Pos3D
*/
public Pos3D translate(Pos3D pos)
{
return translate(pos.xPos, pos.yPos, pos.zPos);
}
/**
* Returns the distance between this and the defined Pos3D.
* @param pos - the Pos3D to find the distance to
* @return the distance between this and the defined Pos3D
*/
public double distance(Pos3D pos)
{
double subX = xPos - pos.xPos;
double subY = yPos - pos.yPos;
double subZ = zPos - pos.zPos;
return MathHelper.sqrt_double(subX * subX + subY * subY + subZ * subZ);
}
/**
* Rotates this Pos3D by the defined yaw value.
* @param yaw - yaw to rotate by
* @return rotated Pos3D
*/
public Pos3D rotateYaw(double yaw)
{
double yawRadians = Math.toRadians(yaw);
double x = xPos;
double z = zPos;
if(yaw != 0)
{
xPos = x * Math.cos(yawRadians) - z * Math.sin(yawRadians);
zPos = x * Math.sin(yawRadians) + z * Math.cos(yawRadians);
}
return this;
}
/**
* Scales this Pos3D by the defined x, y, an z values.
* @param x - x value to scale by
* @param y - y value to scale by
* @param z - z value to scale by
* @return scaled Pos3D
*/
public Pos3D scale(double x, double y, double z)
{
xPos *= x;
yPos *= y;
zPos *= z;
return this;
}
/**
* Performs the same operation as scale(x, y, z), but with a value representing all three dimensions.
* @param scale - value to scale by
* @return scaled Pos3D
*/
public Pos3D scale(double scale)
{
return scale(scale, scale, scale);
}
@Override
public Pos3D clone()
{
return new Pos3D(xPos, yPos, zPos);
}
@Override
public String toString()
{
return "[Pos3D: " + xPos + ", " + yPos + ", " + zPos + "]";
}
@Override
public boolean equals(Object obj)
{
return obj instanceof Pos3D &&
((Pos3D)obj).xPos == xPos &&
((Pos3D)obj).yPos == yPos &&
((Pos3D)obj).zPos == zPos;
}
@Override
public int hashCode()
{
int code = 1;
code = 31 * code + new Double(xPos).hashCode();
code = 31 * code + new Double(yPos).hashCode();
code = 31 * code + new Double(zPos).hashCode();
return code;
}
}

View file

@ -0,0 +1,50 @@
package mekanism.api;
import mekanism.api.gas.GasStack;
import mekanism.api.gas.GasTank;
import net.minecraft.item.ItemStack;
public class PressurizedProducts
{
private ItemStack itemOutput;
private GasStack gasOutput;
public PressurizedProducts(ItemStack item, GasStack gas)
{
itemOutput = item;
gasOutput = gas;
}
public void fillTank(GasTank tank)
{
tank.receive(gasOutput, true);
}
public void addProducts(ItemStack[] inventory, int index)
{
if(inventory[index] == null)
{
inventory[index] = itemOutput.copy();
}
else if(inventory[index].isItemEqual(itemOutput))
{
inventory[index].stackSize += itemOutput.stackSize;
}
}
public ItemStack getItemOutput()
{
return itemOutput;
}
public GasStack getGasOutput()
{
return gasOutput;
}
public PressurizedProducts copy()
{
return new PressurizedProducts(itemOutput.copy(), gasOutput.copy());
}
}

View file

@ -0,0 +1,139 @@
package mekanism.api;
import mekanism.api.gas.GasStack;
import mekanism.api.gas.GasTank;
import mekanism.common.util.StackUtils;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTank;
/**
* An input of a gas, a fluid and an item for the pressurized reaction chamber
*/
public class PressurizedReactants
{
private ItemStack theSolid;
private FluidStack theFluid;
private GasStack theGas;
public PressurizedReactants(ItemStack solid, FluidStack fluid, GasStack gas)
{
theSolid = solid;
theFluid = fluid;
theGas = gas;
}
/**
* If this is a valid PressurizedReactants
*/
public boolean isValid()
{
return theSolid != null && theFluid != null && theGas != null;
}
/**
* Draws the needed amount of gas from each tank.
* @param item - ItemStack to draw from
* @param fluidTank - fluid tank to draw from
* @param gasTank - gas tank to draw from
*/
public void use(ItemStack item, FluidTank fluidTank, GasTank gasTank)
{
if(meets(new PressurizedReactants(item, fluidTank.getFluid(), gasTank.getGas())))
{
item.stackSize -= theSolid.stackSize;
fluidTank.drain(theFluid.amount, true);
gasTank.draw(theGas.amount, true);
}
}
/**
* Whether or not this PressurizedReactants's ItemStack entry's item type is equal to the item type of the given item.
* @param stack - stack to check
* @return if the stack's item type is contained in this PressurizedReactants
*/
public boolean containsType(ItemStack stack)
{
if(stack == null || stack.stackSize == 0)
{
return false;
}
return StackUtils.equalsWildcard(stack, theSolid);
}
/**
* Whether or not this PressurizedReactants's FluidStack entry's fluid type is equal to the fluid type of the given fluid.
* @param stack - stack to check
* @return if the stack's fluid type is contained in this PressurizedReactants
*/
public boolean containsType(FluidStack stack)
{
if(stack == null || stack.amount == 0)
{
return false;
}
return stack.isFluidEqual(theFluid);
}
/**
* Whether or not this PressurizedReactants's GasStack entry's gas type is equal to the gas type of the given gas.
* @param stack - stack to check
* @return if the stack's gas type is contained in this PressurizedReactants
*/
public boolean containsType(GasStack stack)
{
if(stack == null || stack.amount == 0)
{
return false;
}
return stack.isGasEqual(theGas);
}
public boolean meetsInput(ItemStack itemStack, FluidStack fluidStack, GasStack gasStack)
{
return meets(new PressurizedReactants(itemStack, fluidStack, gasStack));
}
/**
* Actual implementation of meetsInput(), performs the checks.
* @param input - input to check
* @return if the input meets this input's requirements
*/
private boolean meets(PressurizedReactants input)
{
if(input == null || !input.isValid())
{
return false;
}
if(!(StackUtils.equalsWildcard(input.theSolid, theSolid) && input.theFluid.isFluidEqual(theFluid) && input.theGas.isGasEqual(theGas)))
{
return false;
}
return input.theSolid.stackSize >= theSolid.stackSize && input.theFluid.amount >= theFluid.amount && input.theGas.amount >= theGas.amount;
}
public PressurizedReactants copy()
{
return new PressurizedReactants(theSolid.copy(), theFluid.copy(), theGas.copy());
}
public ItemStack getSolid()
{
return theSolid;
}
public FluidStack getFluid()
{
return theFluid;
}
public GasStack getGas()
{
return theGas;
}
}

View file

@ -0,0 +1,25 @@
package mekanism.api;
public class PressurizedRecipe
{
public PressurizedReactants reactants;
public double extraEnergy;
public PressurizedProducts products;
public int ticks;
public PressurizedRecipe(PressurizedReactants pressurizedReactants, double energy, PressurizedProducts pressurizedProducts, int duration)
{
reactants = pressurizedReactants;
extraEnergy = energy;
products = pressurizedProducts;
ticks = duration;
}
public PressurizedRecipe copy()
{
return new PressurizedRecipe(reactants.copy(), extraEnergy, products.copy(), ticks);
}
}

View file

@ -0,0 +1,258 @@
package mekanism.api;
import java.lang.reflect.Method;
import mekanism.api.gas.GasStack;
import mekanism.api.infuse.InfusionInput;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
/**
* Use this handy class to add recipes to Mekanism machinery.
* @author AidanBrady
*
*/
public final class RecipeHelper
{
/**
* Add an Enrichment Chamber recipe.
* @param input - input ItemStack
* @param output - output ItemStack
*/
public static void addEnrichmentChamberRecipe(ItemStack input, ItemStack output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addEnrichmentChamberRecipe", ItemStack.class, ItemStack.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add an Osmium Compressor recipe.
* @param input - input ItemStack
* @param output - output ItemStack
*/
public static void addOsmiumCompressorRecipe(ItemStack input, ItemStack output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addOsmiumCompressorRecipe", ItemStack.class, ItemStack.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add a Combiner recipe.
* @param input - input ItemStack
* @param output - output ItemStack
*/
public static void addCombinerRecipe(ItemStack input, ItemStack output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addCombinerRecipe", ItemStack.class, ItemStack.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add a Crusher recipe.
* @param input - input ItemStack
* @param output - output ItemStack
*/
public static void addCrusherRecipe(ItemStack input, ItemStack output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addCrusherRecipe", ItemStack.class, ItemStack.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add a Purification Chamber recipe.
* @param input - input ItemStack
* @param output - output ItemStack
*/
public static void addPurificationChamberRecipe(ItemStack input, ItemStack output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addPurificationChamberRecipe", ItemStack.class, ItemStack.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add a Chemical Oxidizer recipe.
* @param input - input ItemStack
* @param output - output GasStack
*/
public static void addChemicalOxidizerRecipe(ItemStack input, GasStack output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addChemicalOxidizerRecipe", ItemStack.class, GasStack.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add a Chemical Infuser recipe.
* @param input - input ChemicalInput
* @param output - output GasStack
*/
public static void addChemicalInfuserRecipe(ChemicalPair input, GasStack output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addChemicalInfuserRecipe", ChemicalPair.class, GasStack.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add a Precision Sawmill recipe.
* @param input - input ItemStack
* @param output - output ChanceOutput
*/
public static void addPrecisionSawmillRecipe(ItemStack input, ChanceOutput output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addPrecisionSawmillRecipe", ItemStack.class, ChanceOutput.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add a Chemical Injection Chamber recipe.
* @param input - input AdvancedInput
* @param output - output ItemStack
*/
public static void addChemicalInjectionChamberRecipe(AdvancedInput input, ItemStack output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addChemicalInjectionChamberRecipe", AdvancedInput.class, ItemStack.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add an Electrolytic Separator recipe.
* @param input - input FluidStack
* @param output - output ChemicalPair
*/
public static void addElectrolyticSeparatorRecipe(FluidStack input, ChemicalPair output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addElectrolyticSeparatorRecipe", FluidStack.class, ChemicalPair.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add a Chemical Dissolution Chamber recipe.
* @param input - input ItemStack
* @param output - output GasStack
*/
public static void addChemicalDissolutionChamberRecipe(ItemStack input, GasStack output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addChemicalDissolutionChamberRecipe", ItemStack.class, GasStack.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add a Chemical Washer recipe.
* @param input - input GasStack
* @param output - output GasStack
*/
public static void addChemicalWasherRecipe(GasStack input, GasStack output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addChemicalWasherRecipe", GasStack.class, GasStack.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add a Chemical Crystallizer recipe.
* @param input - input GasStack
* @param output - output ItemStack
*/
public static void addChemicalCrystallizerRecipe(GasStack input, ItemStack output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addChemicalCrystallizerRecipe", GasStack.class, ItemStack.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add a Metallurgic Infuser recipe.
* @param input - input Infusion
* @param output - output ItemStack
*/
public static void addMetallurgicInfuserRecipe(InfusionInput input, ItemStack output)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addMetallurgicInfuserRecipe", InfusionInput.class, ItemStack.class);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
/**
* Add a Pressurized Reaction Chamber recipe.
* @param input - input PressurizedReactants
* @param output - output PressurizedProducts
* @param extraEnergy - extra energy needed by the recipe
* @param ticks - amount of ticks it takes for this recipe to complete
*/
public static void addPRCRecipe(PressurizedReactants input, PressurizedProducts output, double extraEnergy, int ticks)
{
try {
Class recipeClass = Class.forName("mekanism.common.recipe.RecipeHandler");
Method m = recipeClass.getMethod("addPRCRecipe", PressurizedReactants.class, PressurizedProducts.class, Double.TYPE, Integer.TYPE);
m.invoke(null, input, output);
} catch(Exception e) {
System.err.println("Error while adding recipe: " + e.getMessage());
}
}
}

View file

@ -0,0 +1,42 @@
package mekanism.api;
import net.minecraft.creativetab.CreativeTabs;
/**
* Class used to indirectly reference the Mekanism creative tab.
* @author AidanBrady
*
*/
public final class TabProxy
{
/** The 'Mekanism' class where the tab instance is stored. */
public static Class Mekanism;
/**
* Attempts to get the Mekanism creative tab instance from the 'Mekanism' class. Will return
* the tab if the mod is loaded, but otherwise will return the defined 'preferred' creative tab. This way
* you don't need to worry about NPEs!
* @return Mekanism creative tab if can, otherwise preferred tab
*/
public static CreativeTabs tabMekanism(CreativeTabs preferred)
{
try {
if(Mekanism == null)
{
Mekanism = Class.forName("mekanism.common.Mekanism");
}
Object ret = Mekanism.getField("tabMekanism").get(null);
if(ret instanceof CreativeTabs)
{
return (CreativeTabs)ret;
}
return preferred;
} catch(Exception e) {
System.err.println("Error retrieving Mekanism creative tab.");
return preferred;
}
}
}

View file

@ -0,0 +1,60 @@
package mekanism.api.energy;
import net.minecraft.item.ItemStack;
public class EnergizedItemManager
{
/**
* Discharges an IEnergizedItem with the defined amount of energy.
* @param itemStack - ItemStack to discharge
* @param amount - amount of energy to discharge from the item, usually the total amount of energy needed in a TileEntity
* @return amount of energy discharged
*/
public static double discharge(ItemStack itemStack, double amount)
{
if(itemStack != null)
{
if(itemStack.getItem() instanceof IEnergizedItem)
{
IEnergizedItem energizedItem = (IEnergizedItem)itemStack.getItem();
if(energizedItem.canSend(itemStack))
{
double energyToUse = Math.min(energizedItem.getMaxTransfer(itemStack), Math.min(energizedItem.getEnergy(itemStack), amount));
energizedItem.setEnergy(itemStack, energizedItem.getEnergy(itemStack) - energyToUse);
return energyToUse;
}
}
}
return 0;
}
/**
* Charges an IEnergizedItem with the defined amount of energy.
* @param itemStack - ItemStack to charge
* @param amount - amount of energy to charge the item with, usually the total amount of energy stored in a TileEntity
* @return amount of energy charged
*/
public static double charge(ItemStack itemStack, double amount)
{
if(itemStack != null)
{
if(itemStack.getItem() instanceof IEnergizedItem)
{
IEnergizedItem energizedItem = (IEnergizedItem)itemStack.getItem();
if(energizedItem.canReceive(itemStack))
{
double energyToSend = Math.min(energizedItem.getMaxTransfer(itemStack), Math.min(energizedItem.getMaxEnergy(itemStack) - energizedItem.getEnergy(itemStack), amount));
energizedItem.setEnergy(itemStack, energizedItem.getEnergy(itemStack) + energyToSend);
return energyToSend;
}
}
}
return 0;
}
}

View file

@ -0,0 +1,18 @@
package mekanism.api.energy;
import net.minecraftforge.common.util.ForgeDirection;
/**
* Implement this if your TileEntity is capable of outputting energy to cables, overriding Mekanism's default implementation.
* @author AidanBrady
*
*/
public interface ICableOutputter
{
/**
* Whether or not this block can output to a cable on a specific side.
* @param side - side to check
* @return if the block can output
*/
public boolean canOutputTo(ForgeDirection side);
}

View file

@ -0,0 +1,59 @@
package mekanism.api.energy;
import net.minecraft.item.ItemStack;
/**
* Implement this in an item's class if it should be able to store electricity.
* @author aidancbrady
*
*/
public interface IEnergizedItem
{
/**
* Gets and returns the amount of energy stored in this item.
* @param itemStack - the ItemStack to check
* @return energy stored
*/
public double getEnergy(ItemStack itemStack);
/**
* Sets this item's stored energy value to a new amount.
* @param itemStack - the ItemStack who's energy value is to be change
* @param amount - new amount of energy
*/
public void setEnergy(ItemStack itemStack, double amount);
/**
* Gets and returns this item's maximum amount of energy that can be stored.
* @param itemStack - the ItemStack to check
* @return maximum energy
*/
public double getMaxEnergy(ItemStack itemStack);
/**
* Gets and returns how much energy this item can transfer to and from charging slots.
* @param itemStack - the ItemStack to check
* @return transfer amount
*/
public double getMaxTransfer(ItemStack itemStack);
/**
* Gets and returns whether or not this item can receive energy from a charging slot.
* @param itemStack - the ItemStack to check
* @return if the item can receive energy
*/
public boolean canReceive(ItemStack itemStack);
/**
* Gets and returns whether or not this item can send energy to a charging slot.
* @param itemStack - the ItemStack to check
* @return if the item can send energy
*/
public boolean canSend(ItemStack itemStack);
/**
* Returns whether or not this item contains metadata-specific subtypes instead of using metadata for damage display.
* @return if the item contains metadata-specific subtypes
*/
public boolean isMetadataSpecific(ItemStack itemStack);
}

View file

@ -0,0 +1,25 @@
package mekanism.api.energy;
import net.minecraftforge.common.util.ForgeDirection;
/**
* Implement this if your TileEntity can accept energy at a floating-point double value from Universal Cables.
* @author AidanBrady
*
*/
public interface IStrictEnergyAcceptor extends IStrictEnergyStorage
{
/**
* Transfer a certain amount of energy to this acceptor.
* @param amount - amount to transfer
* @return energy used
*/
public double transferEnergyToAcceptor(ForgeDirection side, double amount);
/**
* Whether or not this tile entity accepts energy from a certain side.
* @param side - side to check
* @return if tile entity accepts energy
*/
public boolean canReceiveEnergy(ForgeDirection side);
}

View file

@ -0,0 +1,27 @@
package mekanism.api.energy;
/**
* Mekanism-specific energy storage for TileEntities, already implemented in IStrictEnergyAcceptor.
* @author aidancbrady
*
*/
public interface IStrictEnergyStorage
{
/**
* Gets the amount of energy this TileEntity is currently storing.
* @return stored energy
*/
public double getEnergy();
/**
* Sets the amount of stored energy of this TileEntity to a new amount.
* @param energy - new energy value
*/
public void setEnergy(double energy);
/**
* Gets the maximum amount of energy this TileEntity can store.
* @return maximum energy
*/
public double getMaxEnergy();
}

View file

@ -0,0 +1,59 @@
package mekanism.api.gas;
import java.util.HashMap;
import net.minecraftforge.fluids.FluidContainerRegistry;
import buildcraft.api.fuels.IronEngineFuel;
import buildcraft.api.fuels.IronEngineFuel.Fuel;
import cpw.mods.fml.common.ModAPIManager;
public class FuelHandler
{
public static HashMap<String, FuelGas> fuels = new HashMap<String, FuelGas>();
public static void addGas(Gas gas, int burnTicks, double energyPerMilliBucket)
{
fuels.put( gas.getName(), new FuelGas( burnTicks, energyPerMilliBucket ) );
}
public static FuelGas getFuel(Gas gas)
{
if ( fuels.containsKey( gas.getName() ) )
{
return fuels.get( gas.getName() );
}
if ( ModAPIManager.INSTANCE.hasAPI( "BuildCraftAPI|fuel" ) && gas.hasFluid() )
{
Fuel bcFuel = IronEngineFuel.getFuelForFluid( gas.getFluid() );
if ( bcFuel != null )
{
FuelGas fuel = new FuelGas( bcFuel );
fuels.put( gas.getName(), fuel );
return fuel;
}
}
return null;
}
public static class FuelGas
{
public int burnTicks;
public double energyPerTick;
public FuelGas(int duration, double energyDensity) {
burnTicks = duration;
energyPerTick = energyDensity / duration;
}
public FuelGas(Fuel bcFuel) {
burnTicks = bcFuel.totalBurningTime / FluidContainerRegistry.BUCKET_VOLUME;
energyPerTick = bcFuel.powerPerCycle * 1;
}
}
}

View file

@ -0,0 +1,221 @@
package mekanism.api.gas;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.IIcon;
import net.minecraft.util.StatCollector;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
/**
* Gas - a class used to set specific properties of gasses when used or seen in-game.
* @author aidancbrady
*
*/
public class Gas
{
private String name;
private String unlocalizedName;
private Fluid fluid;
private IIcon icon;
private boolean visible = true;
private boolean from_fluid = false;
/**
* Creates a new Gas object with a defined name or key value.
* @param s - name or key to associate this Gas with
*/
public Gas(String s)
{
unlocalizedName = name = s;
}
/**
* Creates a new Gas object that corresponds to the given Fluid
*/
public Gas(Fluid f)
{
unlocalizedName = name = f.getName();
icon = f.getStillIcon();
fluid = f;
from_fluid = true;
}
/**
* Gets the name (key) of this Gas. This is NOT a translated or localized display name.
* @return this Gas's name or key
*/
public String getName()
{
return name;
}
/**
* Whether or not this is a visible gas.
* @return if this gas is visible
*/
public boolean isVisible()
{
return visible;
}
/**
* Sets this gas's "visible" state to a new value. Setting it to 'false' will treat this gas as an internal gas, and it will not be displayed or accessed by other mods.
* @param v - new visible state
* @return this Gas object
*/
public Gas setVisible(boolean v)
{
visible = v;
return this;
}
/**
* Gets the unlocalized name of this Gas.
* @return this Gas's unlocalized name
*/
public String getUnlocalizedName()
{
return "gas." + unlocalizedName;
}
/**
* Translates this Gas's unlocalized name and returns it as localized.
* @return this Gas's localized name
*/
public String getLocalizedName()
{
return StatCollector.translateToLocal(getUnlocalizedName());
}
/**
* Sets the unlocalized name of this Gas.
* @param s - unlocalized name to set
* @return this Gas object
*/
public Gas setUnlocalizedName(String s)
{
unlocalizedName = s;
return this;
}
/**
* Gets the IIcon associated with this Gas.
* @return associated IIcon
*/
public IIcon getIcon()
{
if(from_fluid)
{
return this.getFluid().getIcon();
}
return icon;
}
/**
* Sets this gas's icon.
* @param i - IIcon to associate with this Gas
* @return this Gas object
*/
public Gas setIcon(IIcon i)
{
icon = i;
if(hasFluid())
{
fluid.setIcons(getIcon());
}
from_fluid = false;
return this;
}
/**
* Gets the ID associated with this gas.
* @return the associated gas ID
*/
public int getID()
{
return GasRegistry.getGasID(this);
}
/**
* Writes this Gas to a defined tag compound.
* @param nbtTags - tag compound to write this Gas to
* @return the tag compound this gas was written to
*/
public NBTTagCompound write(NBTTagCompound nbtTags)
{
nbtTags.setString("gasName", getName());
return nbtTags;
}
/**
* Returns the Gas stored in the defined tag compound.
* @param nbtTags - tag compound to get the Gas from
* @return Gas stored in the tag compound
*/
public static Gas readFromNBT(NBTTagCompound nbtTags)
{
if(nbtTags == null || nbtTags.hasNoTags())
{
return null;
}
return GasRegistry.getGas(nbtTags.getString("gasName"));
}
/**
* Whether or not this Gas has an associated fluid.
* @return if this gas has a fluid
*/
public boolean hasFluid()
{
return fluid != null;
}
/**
* Gets the fluid associated with this Gas.
* @return fluid associated with this gas
*/
public Fluid getFluid()
{
return fluid;
}
/**
* Registers a new fluid out of this Gas or gets one from the FluidRegistry.
* @return this Gas object
*/
public Gas registerFluid()
{
if(fluid == null)
{
if(FluidRegistry.getFluid(getName()) == null)
{
fluid = new Fluid(getName()).setGaseous(true);
FluidRegistry.registerFluid(fluid);
}
else {
fluid = FluidRegistry.getFluid(getName());
}
}
return this;
}
@Override
public String toString()
{
return name;
}
}

View file

@ -0,0 +1,477 @@
package mekanism.api.gas;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import mekanism.api.Coord4D;
import mekanism.api.ListUtils;
import mekanism.api.transmitters.DynamicNetwork;
import mekanism.api.transmitters.IGridTransmitter;
import mekanism.api.transmitters.ITransmitterNetwork;
import mekanism.api.transmitters.TransmissionType;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.ForgeDirection;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.Event;
/**
* A DynamicNetwork extension created specifically for the transfer of Gasses. By default this is server-only, but if ticked on
* the client side and if it's posted events are handled properly, it has the capability to visually display gasses network-wide.
* @author aidancbrady
*
*/
public class GasNetwork extends DynamicNetwork<IGasHandler, GasNetwork>
{
public int transferDelay = 0;
public boolean didTransfer;
public boolean prevTransfer;
public float gasScale;
public Gas refGas;
public GasStack gasStored;
public int prevStored;
public int prevTransferAmount = 0;
public GasNetwork(IGridTransmitter<GasNetwork>... varPipes)
{
transmitters.addAll(Arrays.asList(varPipes));
updateCapacity();
register();
}
public GasNetwork(Collection<IGridTransmitter<GasNetwork>> collection)
{
transmitters.addAll(collection);
updateCapacity();
register();
}
public GasNetwork(Set<GasNetwork> networks)
{
for(GasNetwork net : networks)
{
if(net != null)
{
if(FMLCommonHandler.instance().getEffectiveSide().isClient())
{
if(net.refGas != null && net.gasScale > gasScale)
{
gasScale = net.gasScale;
refGas = net.refGas;
gasStored = net.gasStored;
net.gasScale = 0;
net.refGas = null;
net.gasStored = null;
}
}
else {
if(net.gasStored != null)
{
if(gasStored == null)
{
gasStored = net.gasStored;
}
else {
gasStored.amount += net.gasStored.amount;
}
net.gasStored = null;
}
}
addAllTransmitters(net.transmitters);
net.deregister();
}
}
gasScale = getScale();
updateCapacity();
fullRefresh();
register();
}
@Override
public void onNetworksCreated(List<GasNetwork> networks)
{
if(gasStored != null && FMLCommonHandler.instance().getEffectiveSide().isServer())
{
int[] caps = new int[networks.size()];
int cap = 0;
for(GasNetwork network : networks)
{
caps[networks.indexOf(network)] = network.getCapacity();
cap += network.getCapacity();
}
gasStored.amount = Math.min(cap, gasStored.amount);
int[] values = ListUtils.calcPercentInt(ListUtils.percent(caps), gasStored.amount);
for(GasNetwork network : networks)
{
int index = networks.indexOf(network);
if(values[index] > 0)
{
network.gasStored = new GasStack(gasStored.getGas(), values[index]);
network.refGas = gasStored.getGas();
}
}
}
gasScale = 0;
refGas = null;
gasStored = null;
}
public synchronized int getGasNeeded()
{
return getCapacity()-(gasStored != null ? gasStored.amount : 0);
}
public synchronized int tickEmit(GasStack stack)
{
List availableAcceptors = Arrays.asList(getAcceptors(stack.getGas()).toArray());
Collections.shuffle(availableAcceptors);
int toSend = stack.amount;
int prevSending = toSend;
if(!availableAcceptors.isEmpty())
{
int divider = availableAcceptors.size();
int remaining = toSend % divider;
int sending = (toSend-remaining)/divider;
for(Object obj : availableAcceptors)
{
if(obj instanceof IGasHandler)
{
IGasHandler acceptor = (IGasHandler)obj;
int currentSending = sending;
if(remaining > 0)
{
currentSending++;
remaining--;
}
toSend -= acceptor.receiveGas(acceptorDirections.get(acceptor).getOpposite(), new GasStack(stack.getGas(), currentSending));
}
}
}
int sent = prevSending-toSend;
if(sent > 0 && FMLCommonHandler.instance().getEffectiveSide().isServer())
{
didTransfer = true;
transferDelay = 2;
}
return sent;
}
public synchronized int emit(GasStack stack)
{
if(gasStored != null && gasStored.getGas() != stack.getGas())
{
return 0;
}
int toUse = Math.min(getGasNeeded(), stack.amount);
if(gasStored == null)
{
gasStored = stack.copy();
gasStored.amount = toUse;
}
else {
gasStored.amount += toUse;
}
return toUse;
}
@Override
public void onUpdate()
{
super.onUpdate();
if(FMLCommonHandler.instance().getEffectiveSide().isServer())
{
prevTransferAmount = 0;
if(transferDelay == 0)
{
didTransfer = false;
}
else {
transferDelay--;
}
int stored = gasStored != null ? gasStored.amount : 0;
if(stored != prevStored)
{
needsUpdate = true;
}
prevStored = stored;
if(didTransfer != prevTransfer || needsUpdate)
{
MinecraftForge.EVENT_BUS.post(new GasTransferEvent(this, gasStored, didTransfer));
needsUpdate = false;
}
prevTransfer = didTransfer;
if(gasStored != null)
{
prevTransferAmount = tickEmit(gasStored);
gasStored.amount -= prevTransferAmount;
if(gasStored.amount <= 0)
{
gasStored = null;
}
}
}
}
@Override
public void clientTick()
{
super.clientTick();
gasScale = Math.max(gasScale, getScale());
if(didTransfer && gasScale < 1)
{
gasScale = Math.max(getScale(), Math.min(1, gasScale+0.02F));
}
else if(!didTransfer && gasScale > 0)
{
gasScale = Math.max(getScale(), Math.max(0, gasScale-0.02F));
if(gasScale == 0)
{
gasStored = null;
}
}
}
@Override
public synchronized Set<IGasHandler> getAcceptors(Object... data)
{
Gas type = (Gas)data[0];
Set<IGasHandler> toReturn = new HashSet<IGasHandler>();
for(IGasHandler acceptor : possibleAcceptors.values())
{
if(acceptorDirections.get(acceptor) == null)
{
continue;
}
if(acceptor.canReceiveGas(acceptorDirections.get(acceptor).getOpposite(), type))
{
toReturn.add(acceptor);
}
}
return toReturn;
}
@Override
public synchronized void refresh()
{
Set<IGridTransmitter<GasNetwork>> iterTubes = (Set<IGridTransmitter<GasNetwork>>)transmitters.clone();
Iterator<IGridTransmitter<GasNetwork>> it = iterTubes.iterator();
boolean networkChanged = false;
while(it.hasNext())
{
IGridTransmitter<GasNetwork> conductor = (IGridTransmitter<GasNetwork>)it.next();
if(conductor == null || conductor.getTile().isInvalid())
{
it.remove();
networkChanged = true;
transmitters.remove(conductor);
}
else {
conductor.setTransmitterNetwork(this);
}
}
if(networkChanged)
{
updateCapacity();
}
}
@Override
public synchronized void refresh(IGridTransmitter<GasNetwork> transmitter)
{
IGasHandler[] acceptors = GasTransmission.getConnectedAcceptors(transmitter.getTile());
clearAround(transmitter);
for(IGasHandler acceptor : acceptors)
{
ForgeDirection side = ForgeDirection.getOrientation(Arrays.asList(acceptors).indexOf(acceptor));
if(side != null && acceptor != null && !(acceptor instanceof IGridTransmitter) && transmitter.canConnectToAcceptor(side, true))
{
possibleAcceptors.put(Coord4D.get((TileEntity)acceptor), acceptor);
acceptorDirections.put(acceptor, ForgeDirection.getOrientation(Arrays.asList(acceptors).indexOf(acceptor)));
}
}
}
public static class GasTransferEvent extends Event
{
public final GasNetwork gasNetwork;
public final GasStack transferType;
public final boolean didTransfer;
public GasTransferEvent(GasNetwork network, GasStack type, boolean did)
{
gasNetwork = network;
transferType = type;
didTransfer = did;
}
}
public float getScale()
{
return Math.min(1, (gasStored == null || getCapacity() == 0 ? 0 : (float)gasStored.amount/getCapacity()));
}
@Override
public String toString()
{
return "[GasNetwork] " + transmitters.size() + " transmitters, " + possibleAcceptors.size() + " acceptors.";
}
@Override
public boolean canMerge(List<ITransmitterNetwork<?, ?>> networks)
{
Gas found = null;
for(ITransmitterNetwork<?, ?> network : networks)
{
if(network instanceof GasNetwork)
{
GasNetwork net = (GasNetwork)network;
if(net.gasStored != null)
{
if(found != null && found != net.gasStored.getGas())
{
return false;
}
found = net.gasStored.getGas();
}
}
}
return true;
}
@Override
protected GasNetwork create(IGridTransmitter<GasNetwork>... varTransmitters)
{
GasNetwork network = new GasNetwork(varTransmitters);
network.refGas = refGas;
if(gasStored != null)
{
if(network.gasStored == null)
{
network.gasStored = gasStored;
}
else {
network.gasStored.amount += gasStored.amount;
}
}
network.gasScale = network.getScale();
gasScale = 0;
refGas = null;
gasStored = null;
return network;
}
@Override
protected GasNetwork create(Collection<IGridTransmitter<GasNetwork>> collection)
{
GasNetwork network = new GasNetwork(collection);
network.refGas = refGas;
if(gasStored != null)
{
if(network.gasStored == null)
{
network.gasStored = gasStored;
}
else {
network.gasStored.amount += gasStored.amount;
}
}
network.gasScale = network.getScale();
return network;
}
@Override
protected GasNetwork create(Set<GasNetwork> networks)
{
return new GasNetwork(networks);
}
@Override
public TransmissionType getTransmissionType()
{
return TransmissionType.GAS;
}
@Override
public String getNeededInfo()
{
return Integer.toString(getGasNeeded());
}
@Override
public String getStoredInfo()
{
return gasStored != null ? gasStored.getGas().getLocalizedName() + " (" + gasStored.amount + ")" : "None";
}
@Override
public String getFlowInfo()
{
return Integer.toString(prevTransferAmount) + "/t";
}
}

View file

@ -0,0 +1,113 @@
package mekanism.api.gas;
import java.util.ArrayList;
import java.util.List;
import net.minecraftforge.fluids.Fluid;
public class GasRegistry
{
private static ArrayList<Gas> registeredGasses = new ArrayList<Gas>();
/**
* Register a new gas into GasRegistry.
* @param gas - Gas to register
* @return the gas that has been registered, pulled right out of GasRegistry
*/
public static Gas register(Gas gas)
{
if(gas == null)
{
return null;
}
registeredGasses.add(gas);
return getGas(gas.getName());
}
/**
* Gets the gas associated with the defined ID.
* @param id - ID to check
* @return gas associated with defined ID
*/
public static Gas getGas(int id)
{
if(id == -1)
{
return null;
}
return registeredGasses.get(id);
}
/**
* Gets the gas associated with the defined fluid.
* @param f - fluid to check
* @return the gas associated with the fluid
*/
public static Gas getGas(Fluid f)
{
for(Gas gas : getRegisteredGasses())
{
if(gas.hasFluid() && gas.getFluid() == f)
{
return gas;
}
}
return null;
}
/**
* Whether or not GasRegistry contains a gas with the specified name
* @param name - name to check
* @return if GasRegistry contains a gas with the defined name
*/
public static boolean containsGas(String name)
{
return getGas(name) != null;
}
/**
* Gets the list of all gasses registered in GasRegistry.
* @return a cloned list of all registered gasses
*/
public static List<Gas> getRegisteredGasses()
{
return (List<Gas>)registeredGasses.clone();
}
/**
* Gets the gas associated with the specified name.
* @param name - name of the gas to get
* @return gas associated with the name
*/
public static Gas getGas(String name)
{
for(Gas gas : registeredGasses)
{
if(gas.getName().toLowerCase().equals(name.toLowerCase()))
{
return gas;
}
}
return null;
}
/**
* Gets the gas ID of a specified gas.
* @param gas - gas to get the ID from
* @return gas ID
*/
public static int getGasID(Gas gas)
{
if(gas == null || !containsGas(gas.getName()))
{
return -1;
}
return registeredGasses.indexOf(gas);
}
}

View file

@ -0,0 +1,119 @@
package mekanism.api.gas;
import net.minecraft.nbt.NBTTagCompound;
/**
* GasStack - a specified amount of a defined Gas with certain properties.
* @author aidancbrady
*
*/
public class GasStack
{
private Gas type;
public int amount;
/**
* Creates a new GasStack with a defined gas ID and quantity.
* @param id - gas ID to associate this GasStack to, will perform a GasRegistry lookup in the constructor
* @param quantity - amount of gas to be referenced in this GasStack
*/
public GasStack(int id, int quantity)
{
type = GasRegistry.getGas(id);
amount = quantity;
}
/**
* Creates a new GasStack with a defined Gas type and quantity.
* @param gas - gas type of the stack
* @param quantity - amount of gas to be referenced in this GasStack
*/
public GasStack(Gas gas, int quantity)
{
type = gas;
amount = quantity;
}
private GasStack() {}
/**
* Gets the Gas type of this GasStack.
* @return this GasStack's Gas type
*/
public Gas getGas()
{
return type;
}
/**
* Writes this GasStack to a defined tag compound.
* @param nbtTags - tag compound to write to
* @return tag compound with this GasStack's data
*/
public NBTTagCompound write(NBTTagCompound nbtTags)
{
type.write(nbtTags);
nbtTags.setInteger("amount", amount);
return nbtTags;
}
/**
* Reads this GasStack's data from a defined tag compound.
* @param nbtTags - tag compound to read from
*/
public void read(NBTTagCompound nbtTags)
{
type = Gas.readFromNBT(nbtTags);
amount = nbtTags.getInteger("amount");
}
/**
* Returns the GasStack stored in the defined tag compound, or null if it doesn't exist.
* @param nbtTags - tag compound to read from
* @return GasStack stored in the tag compound
*/
public static GasStack readFromNBT(NBTTagCompound nbtTags)
{
if(nbtTags == null || nbtTags.hasNoTags())
{
return null;
}
GasStack stack = new GasStack();
stack.read(nbtTags);
if(stack.getGas() == null)
{
return null;
}
return stack;
}
/**
* Returns a copied form of this GasStack.
* @return copied GasStack
*/
public GasStack copy()
{
return new GasStack(type, amount);
}
/**
* Whether or not this GasStack's gas type is equal to the other defined GasStack.
* @param stack - GasStack to check
* @return if the GasStacks contain the same gas type
*/
public boolean isGasEqual(GasStack stack)
{
return stack != null && getGas() == stack.getGas();
}
@Override
public String toString()
{
return "[" + type + ", " + amount + "]";
}
}

View file

@ -0,0 +1,241 @@
package mekanism.api.gas;
import net.minecraft.nbt.NBTTagCompound;
/**
* An optional way of managing and/or storing gasses. Would be very useful in TileEntity and Entity gas storage.
* @author aidancbrady
*
*/
public class GasTank
{
public GasStack stored;
private int maxGas;
private GasTank() {}
/**
* Creates a tank with a defined capacity.
* @param max - the maximum amount of gas this GasTank can hold
*/
public GasTank(int max)
{
maxGas = max;
}
/**
* Sets this tank's GasStack value to a new value. Will cap the amount to this GasTank's capacity.
* @param stack - value to set this tank's GasStack value to
*/
public void setGas(GasStack stack)
{
stored = stack;
if(stored != null)
{
stored.amount = Math.min(getMaxGas(), stored.amount);
}
}
/**
* Draws a specified amount of gas out of this tank.
* @param amount - amount to draw
* @param doDraw - if the gas should actually be removed from this tank
* @return gas taken from this GasTank as a GasStack value
*/
public GasStack draw(int amount, boolean doDraw)
{
if(stored == null || amount <= 0)
{
return null;
}
GasStack ret = new GasStack(getGas().getGas(), Math.min(getStored(), amount));
if(ret.amount > 0)
{
if(doDraw)
{
stored.amount -= ret.amount;
if(stored.amount <= 0)
{
stored = null;
}
}
return ret;
}
return null;
}
/**
* Adds a specified amount of gas to this tank.
* @param amount - the GasStack for this tank to receive
* @param doReceive - if the gas should actually be added to this tank
* @return the amount of gas accepted by this tank
*/
public int receive(GasStack amount, boolean doReceive)
{
if(amount == null || (stored != null && stored.amount == getMaxGas()))
{
return 0;
}
int toFill = Math.min(getMaxGas()-getStored(), amount.amount);
if(doReceive)
{
if(stored == null)
{
stored = amount.copy();
}
else {
stored.amount = Math.min(getMaxGas(), getStored()+amount.amount);
}
}
return toFill;
}
/**
* If this GasTank can receive the specified type of gas. Will return false if this tank does not need anymore gas.
* @param gas - gas to check
* @return if this GasTank can accept the defined gas
*/
public boolean canReceive(Gas gas)
{
if(getNeeded() == 0 || stored != null && (gas != null && gas != stored.getGas()))
{
return false;
}
return true;
}
/**
* If this GasTank can receive the specified type of gas. Will return TRUE if this tank does not need anymore gas.
* @param gas - gas to check
* @return if this GasTank can accept the defined gas
*/
public boolean canReceiveType(Gas gas)
{
if(stored != null && (gas != null && gas != stored.getGas()))
{
return false;
}
return true;
}
/**
* If this GasTank can be drawn of the specified type of gas. Will return false if this tank does not contain any gas.
* @param gas - gas to check
* @return if this GasTank can be drawn of the defined gas
*/
public boolean canDraw(Gas gas)
{
if(stored == null || (gas != null && gas != stored.getGas()))
{
return false;
}
return true;
}
/**
* Gets the amount of gas needed by this GasTank.
* @return
*/
public int getNeeded()
{
return getMaxGas()-getStored();
}
/**
* Gets the maximum amount of gas this tank can hold.
* @return - max gas
*/
public int getMaxGas()
{
return maxGas;
}
/**
* Gets the GasStack held by this GasTank.
* @return - GasStakc held by this tank
*/
public GasStack getGas()
{
return stored;
}
/**
* Gets the type of gas currently stored in this GasTank.
* @return gas type contained
*/
public Gas getGasType()
{
return stored != null ? stored.getGas() : null;
}
/**
* Gets the amount of gas stored by this GasTank.
* @return amount of gas stored
*/
public int getStored()
{
return stored != null ? stored.amount : 0;
}
/**
* Writes this tank to a defined tag compound.
* @param nbtTags - tag compound to write to
* @return tag compound with this tank's data
*/
public NBTTagCompound write(NBTTagCompound nbtTags)
{
if(stored != null)
{
nbtTags.setTag("stored", stored.write(new NBTTagCompound()));
}
nbtTags.setInteger("maxGas", maxGas);
return nbtTags;
}
/**
* Reads this tank's data from a defined tag compound.
* @param nbtTags - tag compound to read from
*/
public void read(NBTTagCompound nbtTags)
{
if(nbtTags.hasKey("stored"))
{
stored = GasStack.readFromNBT(nbtTags.getCompoundTag("stored"));
}
maxGas = nbtTags.getInteger("maxGas");
}
/**
* Returns the tank stored in the defined tag compound, or null if it doesn't exist.
* @param nbtTags - tag compound to read from
* @return tank stored in the tag compound
*/
public static GasTank readFromNBT(NBTTagCompound nbtTags)
{
if(nbtTags == null || nbtTags.hasNoTags())
{
return null;
}
GasTank tank = new GasTank();
tank.read(nbtTags);
return tank;
}
}

View file

@ -0,0 +1,141 @@
package mekanism.api.gas;
import mekanism.api.Coord4D;
import mekanism.api.transmitters.IGridTransmitter;
import mekanism.api.transmitters.TransmissionType;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
/**
* A handy class containing several utilities for efficient gas transfer.
* @author AidanBrady
*
*/
public final class GasTransmission
{
/**
* Gets all the tubes around a tile entity.
* @param tileEntity - center tile entity
* @return array of TileEntities
*/
public static TileEntity[] getConnectedTubes(TileEntity tileEntity)
{
TileEntity[] tubes = new TileEntity[] {null, null, null, null, null, null};
for(ForgeDirection orientation : ForgeDirection.VALID_DIRECTIONS)
{
TileEntity tube = Coord4D.get(tileEntity).getFromSide(orientation).getTileEntity(tileEntity.getWorldObj());
if(TransmissionType.checkTransmissionType(tube, TransmissionType.GAS, tileEntity))
{
tubes[orientation.ordinal()] = tube;
}
}
return tubes;
}
/**
* Gets all the acceptors around a tile entity.
* @param tileEntity - center tile entity
* @return array of IGasAcceptors
*/
public static IGasHandler[] getConnectedAcceptors(TileEntity tileEntity)
{
IGasHandler[] acceptors = new IGasHandler[] {null, null, null, null, null, null};
for(ForgeDirection orientation : ForgeDirection.VALID_DIRECTIONS)
{
TileEntity acceptor = Coord4D.get(tileEntity).getFromSide(orientation).getTileEntity(tileEntity.getWorldObj());
if(acceptor instanceof IGasHandler)
{
acceptors[orientation.ordinal()] = (IGasHandler)acceptor;
}
}
return acceptors;
}
/**
* Gets all the tube connections around a tile entity.
* @param tileEntity - center tile entity
* @return array of ITubeConnections
*/
public static ITubeConnection[] getConnections(TileEntity tileEntity)
{
ITubeConnection[] connections = new ITubeConnection[] {null, null, null, null, null, null};
for(ForgeDirection orientation : ForgeDirection.VALID_DIRECTIONS)
{
TileEntity connection = Coord4D.get(tileEntity).getFromSide(orientation).getTileEntity(tileEntity.getWorldObj());
if(canConnect(connection, orientation))
{
connections[orientation.ordinal()] = (ITubeConnection)connection;
}
}
return connections;
}
/**
* Whether or not a TileEntity can connect to a specified tile on a specified side.
* @param tileEntity - TileEntity to attempt connection to
* @param side - side to attempt connection on
* @return if this tile and side are connectable
*/
public static boolean canConnect(TileEntity tileEntity, ForgeDirection side)
{
if(tileEntity instanceof ITubeConnection && (!(tileEntity instanceof IGasTransmitter) || TransmissionType.checkTransmissionType(tileEntity, TransmissionType.GAS, tileEntity)))
{
if(((ITubeConnection)tileEntity).canTubeConnect(side.getOpposite()))
{
return true;
}
}
return false;
}
/**
* Removes a specified amount of gas from an IGasItem.
* @param itemStack - ItemStack of the IGasItem
* @param type - type of gas to remove from the IGasItem, null if it doesn't matter
* @param amount - amount of gas to remove from the ItemStack
* @return the GasStack removed by the IGasItem
*/
public static GasStack removeGas(ItemStack itemStack, Gas type, int amount)
{
if(itemStack != null && itemStack.getItem() instanceof IGasItem)
{
IGasItem item = (IGasItem)itemStack.getItem();
if(type != null && item.getGas(itemStack) != null && item.getGas(itemStack).getGas() != type || !item.canProvideGas(itemStack, type))
{
return null;
}
return item.removeGas(itemStack, amount);
}
return null;
}
/**
* Adds a specified amount of gas to an IGasItem.
* @param itemStack - ItemStack of the IGasItem
* @param stack - stack to add to the IGasItem
* @return amount of gas accepted by the IGasItem
*/
public static int addGas(ItemStack itemStack, GasStack stack)
{
if(itemStack != null && itemStack.getItem() instanceof IGasItem && ((IGasItem)itemStack.getItem()).canReceiveGas(itemStack, stack.getGas()))
{
return ((IGasItem)itemStack.getItem()).addGas(itemStack, stack.copy());
}
return 0;
}
}

View file

@ -0,0 +1,41 @@
package mekanism.api.gas;
import net.minecraftforge.common.util.ForgeDirection;
/**
* Implement this if your tile entity accepts gas from an external source.
* @author AidanBrady
*
*/
public interface IGasHandler
{
/**
* Transfer a certain amount of gas to this block.
* @param stack - gas to add
* @return gas added
*/
public int receiveGas(ForgeDirection side, GasStack stack);
/**
* Draws a certain amount of gas from this block.
* @param amount - amount to draw
* @return gas drawn
*/
public GasStack drawGas(ForgeDirection side, int amount);
/**
* Whether or not this block can accept gas from a certain side.
* @param side - side to check
* @param type - type of gas to check
* @return if block accepts gas
*/
public boolean canReceiveGas(ForgeDirection side, Gas type);
/**
* Whether or not this block can be drawn of gas from a certain side.
* @param side - side to check
* @param type - type of gas to check
* @return if block can be drawn of gas
*/
public boolean canDrawGas(ForgeDirection side, Gas type);
}

View file

@ -0,0 +1,81 @@
package mekanism.api.gas;
import net.minecraft.item.ItemStack;
/**
* Implement this in your item class if it can store or transfer certain gasses.
* @author AidanBrady
*
*/
public interface IGasItem
{
/**
* Gets the rate of transfer this item can handle.
* @return
*/
public int getRate(ItemStack itemstack);
/**
* Adds a defined amount of a certain gas to an item.
* @param itemstack - the itemstack to add gas to
* @param type - the type of gas to add
* @param amount - the amount of gas to add
* @return the gas that was accepted by the item
*/
public int addGas(ItemStack itemstack, GasStack stack);
/**
* Removes the defined amount of a certain gas from the item.
* @param itemstack - the itemstack to remove gas from
* @param type - the type of gas to remove
* @param amount - the amount of gas to remove
* @return the gas that was removed by the item
*/
public GasStack removeGas(ItemStack itemstack, int amount);
/**
* Whether or not this storage tank be given a specific gas.
* @param itemstack - the itemstack to check
* @param type - the type of gas the tank can possibly receive
* @return if the item be charged
*/
public boolean canReceiveGas(ItemStack itemstack, Gas type);
/**
* Whether or not this item can give a gas receiver a certain type of gas.
* @param itemstack - the itemstack to check
* @param type - the type of gas the tank can provide
* @return if the item can provide gas
*/
public boolean canProvideGas(ItemStack itemstack, Gas type);
/**
* Get the gas of a declared type.
* @param type - type of gas
* @param data - ItemStack parameter if necessary
* @return gas stored
*/
public GasStack getGas(ItemStack itemstack);
/**
* Set the gas of a declared type to a new amount;
* @param type - type of gas
* @param data - ItemStack parameter if necessary
* @param amount - amount to store
*/
public void setGas(ItemStack itemstack, GasStack stack);
/**
* Gets the maximum amount of gas this tile entity can store.
* @param type - type of gas
* @param data - ItemStack parameter if necessary
* @return maximum gas
*/
public int getMaxGas(ItemStack itemstack);
/**
* Returns whether or not this item contains metadata-specific subtypes instead of using metadata for damage display.
* @return if the item contains metadata-specific subtypes
*/
public boolean isMetadataSpecific(ItemStack itemstack);
}

View file

@ -0,0 +1,9 @@
package mekanism.api.gas;
import mekanism.api.transmitters.IGridTransmitter;
import net.minecraft.tileentity.TileEntity;
public interface IGasTransmitter extends IGridTransmitter<GasNetwork>
{
public boolean canTransferGasToTube(TileEntity tile);
}

View file

@ -0,0 +1,18 @@
package mekanism.api.gas;
import net.minecraftforge.common.util.ForgeDirection;
/**
* Implement this if your block can connect to Pressurized Tubes.
* @author AidanBrady
*
*/
public interface ITubeConnection
{
/**
* Whether or not a tube can connect to a certain orientation.
* @param side - orientation to check
* @return if a tube can connect
*/
public boolean canTubeConnect(ForgeDirection side);
}

View file

@ -0,0 +1,38 @@
package mekanism.api.gas;
import net.minecraft.util.StatCollector;
public class OreGas extends Gas
{
private String oreName;
private OreGas cleanGas;
public OreGas(String s, String name)
{
super(s);
oreName = name;
}
public boolean isClean()
{
return getCleanGas() == null;
}
public OreGas getCleanGas()
{
return cleanGas;
}
public OreGas setCleanGas(OreGas gas)
{
cleanGas = gas;
return this;
}
public String getOreName()
{
return StatCollector.translateToLocal(oreName);
}
}

View file

@ -0,0 +1,21 @@
package mekanism.api.infuse;
/**
* InfuseObject - an object associated with an ItemStack that can modify a Metallurgic Infuser's internal infuse.
* @author AidanBrady
*
*/
public class InfuseObject
{
/** The type of infuse this item stores */
public InfuseType type;
/** How much infuse this item stores */
public int stored;
public InfuseObject(InfuseType infusion, int i)
{
type = infusion;
stored = i;
}
}

View file

@ -0,0 +1,113 @@
package mekanism.api.infuse;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.item.ItemStack;
/**
* Use this class to add a new object that registers as an infuse object.
* @author AidanBrady
*
*/
public class InfuseRegistry
{
/** The (private) map of ItemStacks and their related InfuseObjects. */
private static Map<ItemStack, InfuseObject> infuseObjects = new HashMap<ItemStack, InfuseObject>();
/** The (private) map of infuse names and their corresponding InfuseTypes. */
private static Map<String, InfuseType> infuseTypes = new HashMap<String, InfuseType>();
/**
* Registers an InfuseType into the registry. Call this in PreInit!
* @param infuse
*/
public static void registerInfuseType(InfuseType infuse)
{
if(infuseTypes.containsKey(infuse.name))
{
return;
}
infuseTypes.put(infuse.name, infuse);
}
/**
* Gets an InfuseType from it's name, or null if it doesn't exist.
* @param name - the name of the InfuseType to get
* @return the name's corresponding InfuseType
*/
public static InfuseType get(String name)
{
if(name.equals("null"))
{
return null;
}
return infuseTypes.get(name);
}
/**
* Whether or not the registry contains a correspondent InfuseType to a name.
* @param name - the name to check
* @return if the name has a coorespondent InfuseType
*/
public static boolean contains(String name)
{
return get(name) != null;
}
/**
* Registers a block or item that serves as an infuse object. An infuse object will store a certain type and amount of infuse,
* and will deliver this amount to the Metallurgic Infuser's buffer of infuse. The item's stack size will be decremented when
* it is placed in the Metallurgic Infuser's infuse slot, and the machine can accept the type and amount of infuse stored in the
* object.
* @param itemStack - stack the infuse object is linked to -- stack size is ignored
* @param infuseObject - the infuse object with the type and amount data
*/
public static void registerInfuseObject(ItemStack itemStack, InfuseObject infuseObject)
{
if(getObject(itemStack) != null)
{
return;
}
infuseObjects.put(itemStack, infuseObject);
}
/**
* Gets the InfuseObject data from an ItemStack.
* @param itemStack - the ItemStack to check
* @return the ItemStack's InfuseObject
*/
public static InfuseObject getObject(ItemStack itemStack)
{
for(Map.Entry<ItemStack, InfuseObject> obj : infuseObjects.entrySet())
{
if(itemStack.isItemEqual(obj.getKey()))
{
return obj.getValue();
}
}
return null;
}
/**
* Gets the private map for InfuseObjects.
* @return private InfuseObject map
*/
public static final Map<ItemStack, InfuseObject> getObjectMap()
{
return infuseObjects;
}
/**
* Gets the private map for InfuseTypes.
* @return private InfuseType map
*/
public static final Map<String, InfuseType> getInfuseMap()
{
return infuseTypes;
}
}

View file

@ -0,0 +1,47 @@
package mekanism.api.infuse;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
/**
* The types of infuse currently available in Mekanism.
* @author AidanBrady
*
*/
public final class InfuseType
{
/** The name of this infusion */
public String name;
/** The location of this infuse's GUI texture */
public ResourceLocation texture;
/** The infuse's GUI texture X offset. */
public int texX;
/** The infuse's GUI texture Y offset. */
public int texY;
/** The unlocalized name of this type. */
public String unlocalizedName;
public InfuseType(String s, ResourceLocation location, int x, int y)
{
name = s;
texture = location;
texX = x;
texY = y;
}
public InfuseType setUnlocalizedName(String name)
{
unlocalizedName = name;
return this;
}
public String getLocalizedName()
{
return StatCollector.translateToLocal(unlocalizedName);
}
}

View file

@ -0,0 +1,32 @@
package mekanism.api.infuse;
import net.minecraft.item.ItemStack;
/**
* An infusion input, containing the type of and amount of infuse the operation requires, as well as the input ItemStack.
* @author AidanBrady
*
*/
public class InfusionInput
{
/** The type of this infusion */
public InfuseType infusionType;
/** How much infuse it takes to perform this operation */
public int infuseAmount;
/** The input ItemStack */
public ItemStack inputStack;
public InfusionInput(InfuseType infusiontype, int required, ItemStack itemstack)
{
infusionType = infusiontype;
infuseAmount = required;
inputStack = itemstack;
}
public static InfusionInput getInfusion(InfuseType type, int stored, ItemStack itemstack)
{
return new InfusionInput(type, stored, itemstack);
}
}

View file

@ -0,0 +1,38 @@
package mekanism.api.infuse;
import net.minecraft.item.ItemStack;
/**
* An infusion output, containing a reference to it's input as well as the output resource.
* @author AidanBrady
*
*/
public class InfusionOutput
{
/** The input infusion */
public InfusionInput infusionInput;
/** The output resource of this infusion */
public ItemStack resource;
public InfusionOutput(InfusionInput input, ItemStack itemstack)
{
infusionInput = input;
resource = itemstack;
}
public static InfusionOutput getInfusion(InfusionInput input, ItemStack itemstack)
{
return new InfusionOutput(input, itemstack);
}
public int getInfuseRequired()
{
return infusionInput.infuseAmount;
}
public InfusionOutput copy()
{
return new InfusionOutput(infusionInput, resource);
}
}

View file

@ -0,0 +1,526 @@
package mekanism.api.transmitters;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import mekanism.api.Coord4D;
import mekanism.api.IClientTicker;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.ForgeDirection;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.Event;
public abstract class DynamicNetwork<A, N extends DynamicNetwork<A, N>> implements ITransmitterNetwork<A, N>, IClientTicker, INetworkDataHandler
{
public LinkedHashSet<IGridTransmitter<N>> transmitters = new LinkedHashSet<IGridTransmitter<N>>();
public HashMap<Coord4D, A> possibleAcceptors = new HashMap<Coord4D, A>();
public HashMap<A, ForgeDirection> acceptorDirections = new HashMap<A, ForgeDirection>();
private List<DelayQueue> updateQueue = new ArrayList<DelayQueue>();
protected AxisAlignedBB packetRange = null;
protected int ticksSinceCreate = 0;
protected int capacity = 0;
protected double meanCapacity = 0;
protected boolean fixed = false;
protected boolean needsUpdate = false;
protected abstract ITransmitterNetwork<A, N> create(IGridTransmitter<N>... varTransmitters);
protected abstract ITransmitterNetwork<A, N> create(Collection<IGridTransmitter<N>> collection);
protected abstract ITransmitterNetwork<A, N> create(Set<N> networks);
protected void clearAround(IGridTransmitter<N> transmitter)
{
for(ForgeDirection side : ForgeDirection.VALID_DIRECTIONS)
{
Coord4D coord = Coord4D.get(transmitter.getTile()).getFromSide(side);
possibleAcceptors.remove(coord);
acceptorDirections.remove(coord.getTileEntity(transmitter.getTile().getWorldObj()));
}
}
public void addAllTransmitters(Set<IGridTransmitter<N>> newTransmitters)
{
transmitters.addAll(newTransmitters);
updateCapacity();
}
public boolean isFirst(IGridTransmitter<N> transmitter)
{
return transmitters.iterator().next().equals(transmitter);
}
@Override
public void fullRefresh()
{
possibleAcceptors.clear();
acceptorDirections.clear();
for(IGridTransmitter<N> transmitter : transmitters)
{
refresh(transmitter);
}
refresh();
}
public AxisAlignedBB getPacketRange()
{
if(packetRange == null)
{
return genPacketRange();
}
return packetRange;
}
public int getDimension()
{
if(getSize() == 0)
{
return 0;
}
return transmitters.iterator().next().getTile().getWorldObj().provider.dimensionId;
}
protected AxisAlignedBB genPacketRange()
{
if(getSize() == 0)
{
deregister();
return null;
}
Coord4D initCoord = Coord4D.get(transmitters.iterator().next().getTile());
int minX = initCoord.xCoord;
int minY = initCoord.yCoord;
int minZ = initCoord.zCoord;
int maxX = initCoord.xCoord;
int maxY = initCoord.yCoord;
int maxZ = initCoord.zCoord;
for(IGridTransmitter transmitter : transmitters)
{
Coord4D coord = Coord4D.get(transmitter.getTile());
if(coord.xCoord < minX) minX = coord.xCoord;
if(coord.yCoord < minY) minY = coord.yCoord;
if(coord.zCoord < minZ) minZ = coord.zCoord;
if(coord.xCoord > maxX) maxX = coord.xCoord;
if(coord.yCoord > maxY) maxY = coord.yCoord;
if(coord.zCoord > maxZ) maxZ = coord.zCoord;
}
minX -= 40;
minY -= 40;
minZ -= 40;
maxX += 40;
maxY += 40;
maxZ += 40;
return AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
}
@Override
public void removeTransmitter(IGridTransmitter<N> transmitter)
{
transmitters.remove(transmitter);
updateCapacity();
if(transmitters.size() == 0)
{
deregister();
}
}
@Override
public void register()
{
try {
IGridTransmitter<N> aTransmitter = transmitters.iterator().next();
if(aTransmitter instanceof TileEntity)
{
if(!((TileEntity)aTransmitter).getWorldObj().isRemote)
{
TransmitterNetworkRegistry.getInstance().registerNetwork(this);
}
else {
MinecraftForge.EVENT_BUS.post(new ClientTickUpdate(this, (byte)1));
}
}
} catch(NoSuchElementException e) {}
}
@Override
public void deregister()
{
transmitters.clear();
if(FMLCommonHandler.instance().getEffectiveSide().isServer())
{
TransmitterNetworkRegistry.getInstance().removeNetwork(this);
}
else {
MinecraftForge.EVENT_BUS.post(new ClientTickUpdate(this, (byte)0));
}
}
@Override
public int getSize()
{
return transmitters.size();
}
@Override
public int getAcceptorSize()
{
return possibleAcceptors.size();
}
public synchronized void updateCapacity() {
updateMeanCapacity();
capacity = (int)meanCapacity * transmitters.size();
}
/**
* Override this if things can have variable capacity along the network.
* @return An 'average' value of capacity. Calculate it how you will.
*/
protected synchronized void updateMeanCapacity()
{
if(transmitters.size() > 0)
{
meanCapacity = transmitters.iterator().next().getCapacity();
}
else {
meanCapacity = 0;
}
}
public int getCapacity()
{
return capacity;
}
public double getMeanCapacity()
{
return meanCapacity;
}
@Override
public void tick()
{
boolean didFix = false;
if(!fixed)
{
ticksSinceCreate++;
if(transmitters.size() == 0)
{
deregister();
return;
}
if(ticksSinceCreate > 1200)
{
ticksSinceCreate = 0;
fixMessedUpNetwork(transmitters.iterator().next());
didFix = true;
}
}
if(!didFix)
{
onUpdate();
}
}
public void onUpdate()
{
if(FMLCommonHandler.instance().getEffectiveSide().isServer())
{
Iterator<DelayQueue> i = updateQueue.iterator();
try {
while(i.hasNext())
{
DelayQueue q = i.next();
if(q.delay > 0)
{
q.delay--;
}
else {
needsUpdate = true;
i.remove();
}
}
} catch(Exception e) {}
}
}
@Override
public synchronized void fixMessedUpNetwork(IGridTransmitter<N> transmitter)
{
if(transmitter instanceof TileEntity)
{
NetworkFinder finder = new NetworkFinder(((TileEntity)transmitter).getWorldObj(), getTransmissionType(), Coord4D.get((TileEntity)transmitter));
List<Coord4D> partNetwork = finder.exploreNetwork();
Set<IGridTransmitter<N>> newTransporters = new HashSet<IGridTransmitter<N>>();
for(Coord4D node : partNetwork)
{
TileEntity nodeTile = node.getTileEntity(((TileEntity)transmitter).getWorldObj());
if(TransmissionType.checkTransmissionType(nodeTile, getTransmissionType(), (TileEntity)transmitter))
{
((IGridTransmitter<N>)nodeTile).removeFromTransmitterNetwork();
newTransporters.add((IGridTransmitter<N>)nodeTile);
}
}
ITransmitterNetwork<A, N> newNetwork = create(newTransporters);
newNetwork.fullRefresh();
newNetwork.setFixed(true);
deregister();
}
}
@Override
public synchronized void split(IGridTransmitter<N> splitPoint)
{
if(splitPoint instanceof TileEntity)
{
removeTransmitter(splitPoint);
TileEntity[] connectedBlocks = new TileEntity[6];
boolean[] dealtWith = {false, false, false, false, false, false};
List<ITransmitterNetwork<A, N>> newNetworks = new ArrayList<ITransmitterNetwork<A, N>>();
for(ForgeDirection side : ForgeDirection.VALID_DIRECTIONS)
{
TileEntity sideTile = Coord4D.get((TileEntity)splitPoint).getFromSide(side).getTileEntity(((TileEntity)splitPoint).getWorldObj());
if(sideTile != null)
{
connectedBlocks[side.ordinal()] = sideTile;
}
}
for(int count = 0; count < connectedBlocks.length; count++)
{
TileEntity connectedBlockA = connectedBlocks[count];
if(TransmissionType.checkTransmissionType(connectedBlockA, getTransmissionType()) && !dealtWith[count])
{
NetworkFinder finder = new NetworkFinder(((TileEntity)splitPoint).getWorldObj(), getTransmissionType(), Coord4D.get(connectedBlockA), Coord4D.get((TileEntity)splitPoint));
List<Coord4D> partNetwork = finder.exploreNetwork();
for(int check = count; check < connectedBlocks.length; check++)
{
if(check == count)
{
continue;
}
TileEntity connectedBlockB = connectedBlocks[check];
if(TransmissionType.checkTransmissionType(connectedBlockB, getTransmissionType()) && !dealtWith[check])
{
if(partNetwork.contains(Coord4D.get(connectedBlockB)))
{
dealtWith[check] = true;
}
}
}
Set<IGridTransmitter<N>> newNetCables = new HashSet<IGridTransmitter<N>>();
for(Coord4D node : finder.iterated)
{
TileEntity nodeTile = node.getTileEntity(((TileEntity)splitPoint).getWorldObj());
if(TransmissionType.checkTransmissionType(nodeTile, getTransmissionType()))
{
if(nodeTile != splitPoint)
{
newNetCables.add((IGridTransmitter<N>)nodeTile);
}
}
}
newNetworks.add(create(newNetCables));
}
}
if(newNetworks.size() > 0)
{
onNetworksCreated((List)newNetworks);
for(ITransmitterNetwork<A, N> network : newNetworks)
{
network.fullRefresh();
}
}
deregister();
}
}
@Override
public void onNetworksCreated(List<N> networks) {}
@Override
public void setFixed(boolean value)
{
fixed = value;
}
@Override
public boolean needsTicks()
{
return getSize() > 0;
}
@Override
public void clientTick()
{
ticksSinceCreate++;
if(ticksSinceCreate == 5 && getSize() > 0)
{
TileEntity tile = (TileEntity)transmitters.iterator().next();
MinecraftForge.EVENT_BUS.post(new NetworkClientRequest(tile));
}
}
@Override
public boolean canMerge(List<ITransmitterNetwork<?, ?>> networks)
{
return true;
}
public static class ClientTickUpdate extends Event
{
public DynamicNetwork network;
public byte operation; /*0 remove, 1 add*/
public ClientTickUpdate(DynamicNetwork net, byte b)
{
network = net;
operation = b;
}
}
public static class NetworkClientRequest extends Event
{
public TileEntity tileEntity;
public NetworkClientRequest(TileEntity tile)
{
tileEntity = tile;
}
}
public void addUpdate(EntityPlayer player)
{
updateQueue.add(new DelayQueue(player));
}
public static class NetworkFinder
{
public TransmissionType transmissionType;
public World worldObj;
public Coord4D start;
public List<Coord4D> iterated = new ArrayList<Coord4D>();
public List<Coord4D> toIgnore = new ArrayList<Coord4D>();
public NetworkFinder(World world, TransmissionType type, Coord4D location, Coord4D... ignore)
{
worldObj = world;
start = location;
transmissionType = type;
if(ignore != null)
{
for(int i = 0; i < ignore.length; i++)
{
toIgnore.add(ignore[i]);
}
}
}
public void loopAll(Coord4D location)
{
if(TransmissionType.checkTransmissionType(location.getTileEntity(worldObj), transmissionType))
{
iterated.add(location);
}
else {
toIgnore.add(location);
}
for(ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS)
{
Coord4D obj = location.getFromSide(direction);
if(!iterated.contains(obj) && !toIgnore.contains(obj))
{
TileEntity tileEntity = obj.getTileEntity(worldObj);
if(!(tileEntity instanceof IBlockableConnection) || ((IBlockableConnection)tileEntity).canConnectMutual(direction.getOpposite()))
{
if(TransmissionType.checkTransmissionType(tileEntity, transmissionType, location.getTileEntity(worldObj)))
{
loopAll(obj);
}
}
}
}
}
public List<Coord4D> exploreNetwork()
{
loopAll(start);
return iterated;
}
}
public static class DelayQueue
{
public EntityPlayer player;
public int delay;
public DelayQueue(EntityPlayer p)
{
player = p;
delay = 5;
}
}
}

View file

@ -0,0 +1,10 @@
package mekanism.api.transmitters;
import net.minecraftforge.common.util.ForgeDirection;
public interface IBlockableConnection
{
public boolean canConnectMutual(ForgeDirection side);
public boolean canConnect(ForgeDirection side);
}

View file

@ -0,0 +1,66 @@
package mekanism.api.transmitters;
import mekanism.api.Coord4D;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
public interface IGridTransmitter<N extends DynamicNetwork<?, N>> extends ITransmitter
{
/**
* Gets the network currently in use by this transmitter segment.
* @return network this transmitter is using
*/
public N getTransmitterNetwork();
/**
* Gets the network currently in use by this transmitter segment.
* @param createIfNull - If true, the transmitter will try and connect to an
* adjacent network, merging several if necessary, or creating a new one
* if none is available
* @return network this transmitter is using
*/
public N getTransmitterNetwork(boolean createIfNull);
/**
* Sets this transmitter segment's network to a new value.
* @param network - network to set to
*/
public void setTransmitterNetwork(N network);
/**
* Refreshes the transmitter's network.
*/
public void refreshTransmitterNetwork();
/**
* Called when the chunk this transmitter is in is loaded.
*/
public void chunkLoad();
/**
* Remove this transmitter from its network.
*/
public void removeFromTransmitterNetwork();
public boolean canConnectToAcceptor(ForgeDirection side, boolean ignoreActive);
/**
* Call this if you're worried a transmitter's network is messed up and you want
* it to try and fix itself.
*/
public void fixTransmitterNetwork();
public boolean areTransmitterNetworksEqual(TileEntity tileEntity);
public int getTransmitterNetworkSize();
public int getTransmitterNetworkAcceptorSize();
public String getTransmitterNetworkNeeded();
public String getTransmitterNetworkFlow();
public int getCapacity();
public TileEntity getTile();
}

View file

@ -0,0 +1,10 @@
package mekanism.api.transmitters;
public interface INetworkDataHandler
{
public String getNeededInfo();
public String getStoredInfo();
public String getFlowInfo();
}

View file

@ -0,0 +1,11 @@
package mekanism.api.transmitters;
public interface ITransmitter
{
/**
* Get the transmitter's transmission type
*
* @return TransmissionType this transmitter uses
*/
public TransmissionType getTransmissionType();
}

View file

@ -0,0 +1,39 @@
package mekanism.api.transmitters;
import java.util.List;
import java.util.Set;
public interface ITransmitterNetwork<A, N extends DynamicNetwork<A, N>>
{
public void tick();
public int getSize();
public int getAcceptorSize();
public Set<A> getAcceptors(Object... data);
public void removeTransmitter(IGridTransmitter<N> transmitter);
public void refresh();
public void fullRefresh();
public void refresh(IGridTransmitter<N> transmitter);
public void split(IGridTransmitter<N> splitPoint);
public void fixMessedUpNetwork(IGridTransmitter<N> transmitter);
public void register();
public void deregister();
public void setFixed(boolean value);
public TransmissionType getTransmissionType();
public boolean canMerge(List<ITransmitterNetwork<?, ?>> networks);
public void onNetworksCreated(List<N> networks);
}

View file

@ -0,0 +1,43 @@
package mekanism.api.transmitters;
import mekanism.api.gas.IGasTransmitter;
import net.minecraft.tileentity.TileEntity;
public enum TransmissionType
{
ENERGY,
FLUID,
GAS,
ITEM;
public static boolean checkTransmissionType(TileEntity sideTile, TransmissionType type)
{
return checkTransmissionType(sideTile, type, null);
}
public static boolean checkTransmissionType(TileEntity sideTile, TransmissionType type, TileEntity currentPipe)
{
return type.checkTransmissionType(sideTile, currentPipe);
}
public boolean checkTransmissionType(TileEntity sideTile, TileEntity currentTile)
{
if(sideTile instanceof ITransmitter)
{
if(((ITransmitter)sideTile).getTransmissionType() == this)
{
return true;
}
}
if(this == GAS && currentTile instanceof IGasTransmitter)
{
if(((IGasTransmitter)currentTile).canTransferGasToTube(sideTile))
{
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,160 @@
package mekanism.api.transmitters;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.world.ChunkEvent;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
import cpw.mods.fml.common.gameevent.TickEvent.ServerTickEvent;
import cpw.mods.fml.relauncher.Side;
public class TransmitterNetworkRegistry
{
private static TransmitterNetworkRegistry INSTANCE = new TransmitterNetworkRegistry();
private static boolean loaderRegistered = false;
private HashSet<ITransmitterNetwork> networks = new HashSet<ITransmitterNetwork>();
public static void initiate()
{
if(!loaderRegistered)
{
loaderRegistered = true;
MinecraftForge.EVENT_BUS.register(new NetworkLoader());
FMLCommonHandler.instance().bus().register(INSTANCE);
}
}
public static TransmitterNetworkRegistry getInstance()
{
return INSTANCE;
}
public void registerNetwork(ITransmitterNetwork network)
{
networks.add(network);
}
public void removeNetwork(ITransmitterNetwork network)
{
if(networks.contains(network))
{
networks.remove(network);
}
}
public void pruneEmptyNetworks()
{
HashSet<ITransmitterNetwork> copySet = new HashSet<ITransmitterNetwork>(networks);
for(ITransmitterNetwork e : copySet)
{
if(e.getSize() == 0)
{
removeNetwork(e);
}
}
}
@SubscribeEvent
public void onTick(ServerTickEvent event)
{
if(event.phase == Phase.END && event.side == Side.SERVER)
{
tickEnd();
}
}
public void tickEnd()
{
Set<ITransmitterNetwork> iterNetworks = (Set<ITransmitterNetwork>)networks.clone();
for(ITransmitterNetwork net : iterNetworks)
{
if(networks.contains(net))
{
net.tick();
}
}
}
@Override
public String toString()
{
return "Network Registry:\n" + networks;
}
public String[] toStrings()
{
String[] strings = new String[networks.size()];
int i = 0;
for(ITransmitterNetwork<?, ?> network : networks)
{
strings[i] = network.toString();
++i;
}
return strings;
}
public static class NetworkLoader
{
@SubscribeEvent
public void onChunkLoad(ChunkEvent.Load event)
{
if(event.getChunk() != null && !event.world.isRemote)
{
int x = event.getChunk().xPosition;
int z = event.getChunk().zPosition;
IChunkProvider cProvider = event.getChunk().worldObj.getChunkProvider();
Chunk[] neighbors = new Chunk[5];
neighbors[0] = event.getChunk();
if(cProvider.chunkExists(x + 1, z)) neighbors[1] = cProvider.provideChunk(x + 1, z);
if(cProvider.chunkExists(x - 1, z)) neighbors[2] = cProvider.provideChunk(x - 1, z);
if(cProvider.chunkExists(x, z + 1)) neighbors[3] = cProvider.provideChunk(x, z + 1);
if(cProvider.chunkExists(x, z - 1)) neighbors[4] = cProvider.provideChunk(x, z - 1);
for(Chunk c : neighbors)
{
refreshChunk(c);
}
}
}
public synchronized void refreshChunk(Chunk c)
{
try {
if(c != null)
{
Map copy = (Map)((HashMap)c.chunkTileEntityMap).clone();
for(Iterator iter = copy.values().iterator(); iter.hasNext();)
{
Object obj = iter.next();
if(obj instanceof IGridTransmitter)
{
((IGridTransmitter)obj).refreshTransmitterNetwork();
((IGridTransmitter)obj).chunkLoad();
}
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
}

View file

@ -0,0 +1,49 @@
package mekanism.common.util;
import java.util.ArrayList;
import java.util.List;
import mekanism.api.Coord4D;
import mekanism.api.ListUtils;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public final class MinerUtils
{
public static List<Block> specialSilkIDs = ListUtils.asList(Blocks.ice);
public static List<ItemStack> getDrops(World world, Coord4D obj, boolean silk)
{
Block block = obj.getBlock(world);
if(block == null)
{
return new ArrayList<ItemStack>();
}
if(block.isAir(world, obj.xCoord, obj.yCoord, obj.zCoord))
{
return new ArrayList<ItemStack>();
}
int meta = obj.getMetadata(world);
if(!silk)
{
return block.getDrops(world, obj.xCoord, obj.yCoord, obj.zCoord, meta, 0);
}
else {
List<ItemStack> ret = new ArrayList<ItemStack>();
ret.add(new ItemStack(block, 1, meta));
if(specialSilkIDs.contains(block) || (block.getDrops(world, obj.xCoord, obj.yCoord, obj.zCoord, meta, 0) != null && block.getDrops(world, obj.xCoord, obj.yCoord, obj.zCoord, meta, 0).size() > 0))
{
return ret;
}
}
return new ArrayList<ItemStack>();
}
}

View file

@ -0,0 +1,114 @@
package mekanism.common.util;
import java.util.Arrays;
import mekanism.api.Coord4D;
import mekanism.api.transmitters.IGridTransmitter;
import mekanism.api.transmitters.TransmissionType;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidTankInfo;
import net.minecraftforge.fluids.IFluidHandler;
public final class PipeUtils
{
public static final FluidTankInfo[] EMPTY = new FluidTankInfo[] {};
/**
* Gets all the pipes around a tile entity.
* @param tileEntity - center tile entity
* @return array of TileEntities
*/
public static TileEntity[] getConnectedPipes(TileEntity tileEntity)
{
TileEntity[] pipes = new TileEntity[] {null, null, null, null, null, null};
for(ForgeDirection orientation : ForgeDirection.VALID_DIRECTIONS)
{
TileEntity pipe = Coord4D.get(tileEntity).getFromSide(orientation).getTileEntity(tileEntity.getWorldObj());
if(TransmissionType.checkTransmissionType(pipe, TransmissionType.FLUID))
{
pipes[orientation.ordinal()] = pipe;
}
}
return pipes;
}
/**
* Gets all the adjacent connections to a TileEntity.
* @param tileEntity - center TileEntity
* @return boolean[] of adjacent connections
*/
public static boolean[] getConnections(TileEntity tileEntity)
{
boolean[] connectable = new boolean[] {false, false, false, false, false, false};
TileEntity[] connectedPipes = PipeUtils.getConnectedPipes(tileEntity);
IFluidHandler[] connectedAcceptors = PipeUtils.getConnectedAcceptors(tileEntity);
for(IFluidHandler container : connectedAcceptors)
{
if(container != null)
{
int side = Arrays.asList(connectedAcceptors).indexOf(container);
FluidTankInfo[] infoArray = container.getTankInfo(ForgeDirection.getOrientation(side).getOpposite());
if(infoArray != null && infoArray.length > 0)
{
boolean notNull = false;
for(FluidTankInfo info : container.getTankInfo(ForgeDirection.getOrientation(side).getOpposite()))
{
if(info != null)
{
notNull = true;
break;
}
}
if(notNull)
{
connectable[side] = true;
}
}
}
}
for(TileEntity tile : connectedPipes)
{
if(tile != null)
{
int side = Arrays.asList(connectedPipes).indexOf(tile);
connectable[side] = true;
}
}
return connectable;
}
/**
* Gets all the acceptors around a tile entity.
* @param tileEntity - center tile entity
* @return array of IFluidHandlers
*/
public static IFluidHandler[] getConnectedAcceptors(TileEntity tileEntity)
{
IFluidHandler[] acceptors = new IFluidHandler[] {null, null, null, null, null, null};
for(ForgeDirection orientation : ForgeDirection.VALID_DIRECTIONS)
{
TileEntity acceptor = Coord4D.get(tileEntity).getFromSide(orientation).getTileEntity(tileEntity.getWorldObj());
if(acceptor instanceof IFluidHandler && !(acceptor instanceof IGridTransmitter))
{
acceptors[orientation.ordinal()] = (IFluidHandler)acceptor;
}
}
return acceptors;
}
}

View file

@ -0,0 +1,149 @@
package mekanism.common.util;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.oredict.OreDictionary;
public final class StackUtils
{
public static List<ItemStack> split(ItemStack stack)
{
if(stack == null || stack.stackSize == 0)
{
return null;
}
List<ItemStack> ret = new ArrayList<ItemStack>();
if(stack.stackSize == 1)
{
ret.add(stack);
return ret;
}
int remain = stack.stackSize % 2;
int split = (int)((float)(stack.stackSize)/2F);
ret.add(size(stack, split+remain));
ret.add(size(stack, split));
return ret;
}
public static Item getItem(ItemStack stack)
{
if(stack == null)
{
return null;
}
return stack.getItem();
}
public static boolean diffIgnoreNull(ItemStack stack1, ItemStack stack2)
{
if(stack1 == null || stack2 == null)
{
return false;
}
return stack1.getItem() != stack2.getItem() || stack1.getItemDamage() != stack2.getItemDamage();
}
public static boolean equalsWildcard(ItemStack wild, ItemStack check)
{
return wild.getItem() == check.getItem() && (wild.getItemDamage() == OreDictionary.WILDCARD_VALUE || wild.getItemDamage() == check.getItemDamage());
}
public static List<ItemStack> even(ItemStack stack1, ItemStack stack2)
{
ArrayList<ItemStack> ret = new ArrayList<ItemStack>();
if(getSize(stack1) == getSize(stack2) || Math.abs(getSize(stack1)-getSize(stack2)) == 1)
{
ret.add(stack1);
ret.add(stack2);
return ret;
}
if(getSize(stack1) > getSize(stack2))
{
int diff = getSize(stack1)-getSize(stack2);
List<ItemStack> split = split(size(stack1, diff));
ret.add(subtract(stack1, split.get(0)));
ret.add(add(stack2, split.get(0)));
}
else if(getSize(stack2) > getSize(stack1))
{
int diff = getSize(stack2)-getSize(stack1);
List<ItemStack> split = split(size(stack2, diff));
ret.add(subtract(stack2, split.get(0)));
ret.add(add(stack1, split.get(0)));
}
return ret;
}
public static ItemStack add(ItemStack stack1, ItemStack stack2)
{
if(stack1 == null)
{
return stack2;
}
else if(stack2 == null)
{
return stack1;
}
return size(stack1, getSize(stack1)+getSize(stack2));
}
public static ItemStack subtract(ItemStack stack1, ItemStack stack2)
{
if(stack1 == null)
{
return null;
}
else if(stack2 == null)
{
return stack1;
}
return size(stack1, getSize(stack1)-getSize(stack2));
}
public static ItemStack size(ItemStack stack, int size)
{
if(size <= 0 || stack == null)
{
return null;
}
ItemStack ret = stack.copy();
ret.stackSize = size;
return ret;
}
public static ItemStack copy(ItemStack stack)
{
if(stack == null)
{
return null;
}
return stack.copy();
}
public static int getSize(ItemStack stack)
{
return stack != null ? stack.stackSize : 0;
}
}

View file

@ -0,0 +1,8 @@
package micdoodle8.mods.galacticraft.api.block;
import net.minecraft.world.World;
public interface IPartialSealedBlock
{
public boolean isSealed(World world, int x, int y, int z);
}

View file

@ -0,0 +1,22 @@
package mods.immibis.core.api.multipart;
/**
* An object that allows extra parts to be added to multipart tiles.
* For example, you can add covers to InfiniTubes transport conduits
* because they use a MicroblockCoverSystem.
*
* This interface's existence is a bit unintuitive, but it was
*/
public interface ICoverSystem extends IPartContainer {
/**
* Converts the block containing this cover system into
* a block containing only parts from this cover system,
* or to air if the cover system has no parts.
*
* Call it when, for example, all wires in a RedLogic wire block are destroyed,
* to replace it with a microblock container block if there were any microblocks
* in the wire block.
*/
public void convertToContainerBlock();
}

View file

@ -0,0 +1,10 @@
package mods.immibis.core.api.multipart;
public interface IMultipartTile extends IPartContainer {
/**
* Returns an ICoverSystem object, or null if this tile does not support a cover system
* @see mods.immibis.core.api.multipart.ICoverSystem
*/
public ICoverSystem getCoverSystem();
}

View file

@ -0,0 +1,90 @@
package mods.immibis.core.api.multipart;
import java.util.List;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraftforge.common.util.ForgeDirection;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
/**
* Contains common methods from ICoverSystem and IMultipartTile.
*/
public interface IPartContainer {
/**
* Gets the speed at which a player breaks a part.
* See Block.getPlayerRelativeBlockHardness.
* @param ply The player.
* @param The part.
* @return The speed.
*/
float getPlayerRelativePartHardness(EntityPlayer ply, int part);
/**
* Called when the player middle-clicks on a part.
* @param rayTrace The location under the player's crosshair.
* @param part The part number they middle-clicked on.
* @return The itemstack to pick.
*/
public ItemStack pickPart(MovingObjectPosition rayTrace, int part);
/**
* Checks if a given face of this block is solid.
* Used to determine the result of Block.isBlockSolidOnSide.
*/
public boolean isSolidOnSide(ForgeDirection side);
/**
* Renders all the parts.
* @param render The render context.
*/
@SideOnly(Side.CLIENT)
public void render(RenderBlocks render);
/**
* Renders one part.
* @param render The render context.
* @param part The part number.
*/
@SideOnly(Side.CLIENT)
public void renderPart(RenderBlocks render, int part);
/**
* Returns all collision boxes that intersect the given mask, in world coordinates.
* @param mask The mask AABB, in world coordinates.
* @param list The list to add the returned boxes to.
*/
public void getCollidingBoundingBoxes(AxisAlignedBB mask, List<AxisAlignedBB> list);
/**
* Called when a player finishes breaking a part.
* @param ply The player breaking the part.
* @param subhit The part being broken.
* @return The item stacks dropped, or null if none.
*/
public List<ItemStack> removePartByPlayer(EntityPlayer ply, int part);
/**
* Returns the AABB of a part, in tile-local coordinates.
* Currently used for drawing the selection box.
* May return null, in which case no selection box is drawn.
*
* @param part The part ID to check.
* @return The AABB of the part, or null.
*/
public AxisAlignedBB getPartAABBFromPool(int part);
/**
* Finds the closest intercept of the given ray with parts in this container.
* @param src The start of the ray, in world coordinates.
* @param dst The end of the ray, in world coordinates.
* @return A ray-trace result, or null if the ray does not intersect any parts.
*/
public MovingObjectPosition collisionRayTrace(Vec3 src, Vec3 dst);
}

View file

@ -0,0 +1,29 @@
package mods.railcraft.api.crafting;
import java.util.List;
import net.minecraft.item.ItemStack;
/**
*
* @author CovertJaguar <http://www.railcraft.info>
*/
public interface IBlastFurnaceCraftingManager {
/**
* Adds a new Blast Furnace Recipe.
*
* @param input the input, if null the function will silently abort
* @param matchDamage if true, it will compare item damage, if false, just
* the item ID
* @param matchNBT if true, it will compare nbt
* @param cookTime the time it takes to cook the recipe
* @param output the output
*/
void addRecipe(ItemStack input, boolean matchDamage, boolean matchNBT, int cookTime, ItemStack output);
List<ItemStack> getFuels();
IBlastFurnaceRecipe getRecipe(ItemStack stack);
List<? extends IBlastFurnaceRecipe> getRecipes();
}

View file

@ -0,0 +1,21 @@
package mods.railcraft.api.crafting;
import net.minecraft.item.ItemStack;
/**
*
* @author CovertJaguar <http://www.railcraft.info>
*/
public interface IBlastFurnaceRecipe
{
public int getCookTime();
public ItemStack getInput();
public ItemStack getOutput();
int getOutputStackSize();
boolean isRoomForOutput(ItemStack outputSlot);
}

View file

@ -0,0 +1,18 @@
package mods.railcraft.api.crafting;
import java.util.List;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
/**
*
* @author CovertJaguar <http://www.railcraft.info>
*/
public interface ICokeOvenCraftingManager {
void addRecipe(ItemStack input, boolean matchDamage, boolean matchNBT, ItemStack output, FluidStack liquidOutput, int cookTime);
ICokeOvenRecipe getRecipe(ItemStack stack);
List<? extends ICokeOvenRecipe> getRecipes();
}

View file

@ -0,0 +1,20 @@
package mods.railcraft.api.crafting;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
/**
*
* @author CovertJaguar <http://www.railcraft.info>
*/
public interface ICokeOvenRecipe
{
public int getCookTime();
public ItemStack getInput();
public FluidStack getFluidOutput();
public ItemStack getOutput();
}

View file

@ -0,0 +1,17 @@
package mods.railcraft.api.crafting;
import java.util.List;
import net.minecraft.item.ItemStack;
/**
*
* @author CovertJaguar <http://www.railcraft.info>
*/
public interface IRockCrusherCraftingManager {
IRockCrusherRecipe createNewRecipe(ItemStack input, boolean matchDamage, boolean matchNBT);
IRockCrusherRecipe getRecipe(ItemStack input);
List<? extends IRockCrusherRecipe> getRecipes();
}

View file

@ -0,0 +1,45 @@
package mods.railcraft.api.crafting;
import java.util.List;
import java.util.Map;
import net.minecraft.item.ItemStack;
/**
*
* @author CovertJaguar <http://www.railcraft.info>
*/
public interface IRockCrusherRecipe {
public ItemStack getInput();
/**
* Adds a new entry to the output list.
*
* @param output the stack to output
* @param chance the change to output this stack
*/
void addOutput(ItemStack output, float chance);
/**
* Returns a list containing each output entry and its chance of being
* included.
*
* @return
*/
public List<Map.Entry<ItemStack, Float>> getOutputs();
/**
* Returns a list of all possible outputs. This is basically a condensed
* version of getOutputs() without the chances.
*
* @return
*/
public List<ItemStack> getPossibleOuputs();
/**
* Returns a list of outputs after it has passed through the randomizer.
*
* @return
*/
public List<ItemStack> getRandomizedOuputs();
}

Some files were not shown because too many files have changed in this diff Show more