Rebrand as BCx-modern, a 1.7.10 port of BCx
Position this mod as a port of BCx from the Minecraft 1.2.5 era. - Rename the mod to BCx-modern (modid bcxmodern) and the package to net.kanawo.bcxmodern; the main class is now BCxModern and takes its version from Tags.VERSION. - Move assets to assets/bcxmodern and rename the lang key and EMC save data to match. - Fill in mcmod.info (description, author agomizi1cm, credits, dependencies) and the LICENSE copyright holder. - Add a README. - Remove template leftovers: CODEOWNERS, LICENSE-template, the greeting Config, template comments, empty event handlers and the commented-out NEI dependency. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ecde802cdb
commit
28b1841c2a
27 files changed
+150
-194
No files matched your search
@@ -0,0 +1,294 @@
|
||||
package net.kanawo.bcxmodern.tile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import buildcraft.builders.TileBuilder;
|
||||
import buildcraft.core.blueprints.BptBuilderBase;
|
||||
import buildcraft.core.blueprints.BptBuilderBlueprint;
|
||||
import buildcraft.core.blueprints.RequirementItemStack;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import moze_intel.projecte.utils.EMCHelper;
|
||||
|
||||
/**
|
||||
* A Builder that pays for building materials with EMC.
|
||||
* <p>
|
||||
* The EMC is not stored in the tile but in its owner's balance in {@link EmcPool}, so all EMC Builders a player owns
|
||||
* in a world share it. The owner is the player who placed the builder, or for one built from a blueprint, the first
|
||||
* player who opens it.
|
||||
* <p>
|
||||
* BuildCraft only builds blocks whose materials are present in the builder's inventory, and consumes them by
|
||||
* shrinking the stacks it finds there. While {@link #build()} runs, this tile therefore appends virtual slots after
|
||||
* the real inventory, one per needed item that has an EMC value, sized to what the stored EMC can afford. After the
|
||||
* build step the amount taken from each virtual slot is charged at 1 EMC per EMC value. Real items in the material
|
||||
* slots come first in the inventory, so they are used before EMC.
|
||||
* <p>
|
||||
* Outside {@link #build()} the virtual slots are hidden, so GUIs, hoppers, pipes and robots only ever see the real
|
||||
* inventory.
|
||||
*/
|
||||
public class TileEMCBuilder extends TileBuilder {
|
||||
|
||||
/** NBT keys of the owner's UUID; SchematicEMCBuilder removes them from blueprints. */
|
||||
public static final String OWNER_MOST = "OwnerUUIDMost";
|
||||
public static final String OWNER_LEAST = "OwnerUUIDLeast";
|
||||
|
||||
private static final int EMC_SYNC_INTERVAL = 10;
|
||||
|
||||
private UUID owner;
|
||||
|
||||
/** Owner's balance as last received from the server. Client side only. */
|
||||
private double clientEmc;
|
||||
/** Owner's balance as last sent to clients. Server side only. */
|
||||
private double sentEmc = -1;
|
||||
private int ticksSinceEmcSync;
|
||||
|
||||
private final List<EmcSlot> emcSlots = new ArrayList<>();
|
||||
private boolean emcSlotsExposed;
|
||||
|
||||
/** A virtual material slot backed by stored EMC. */
|
||||
private static final class EmcSlot {
|
||||
|
||||
final long emcPerItem;
|
||||
final int initialSize;
|
||||
ItemStack stack;
|
||||
|
||||
EmcSlot(ItemStack stack, long emcPerItem) {
|
||||
this.stack = stack;
|
||||
this.emcPerItem = emcPerItem;
|
||||
this.initialSize = stack.stackSize;
|
||||
}
|
||||
|
||||
int consumed() {
|
||||
return stack == null ? initialSize : initialSize - stack.stackSize;
|
||||
}
|
||||
}
|
||||
|
||||
/** The owner's EMC balance; on the client, as last synced. */
|
||||
public double getStoredEmc() {
|
||||
if (worldObj.isRemote) {
|
||||
return clientEmc;
|
||||
}
|
||||
|
||||
return owner == null ? 0
|
||||
: EmcPool.get(worldObj)
|
||||
.get(owner);
|
||||
}
|
||||
|
||||
/** Makes the player the owner if the builder has none yet. Server side only. */
|
||||
public void claimOwner(EntityPlayer player) {
|
||||
if (owner == null) {
|
||||
owner = player.getUniqueID();
|
||||
markDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockPlacedBy(EntityLivingBase entity, ItemStack stack) {
|
||||
super.onBlockPlacedBy(entity, stack);
|
||||
|
||||
if (entity instanceof EntityPlayer) {
|
||||
owner = entity.getUniqueID();
|
||||
}
|
||||
}
|
||||
|
||||
/** Converts the whole stack into EMC for the owner. Server side only. */
|
||||
public void consumeForEmc(ItemStack stack) {
|
||||
long value = EMCHelper.getEmcValue(stack);
|
||||
|
||||
if (owner == null || value <= 0 || stack.stackSize <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
EmcPool.get(worldObj)
|
||||
.add(owner, (double) value * stack.stackSize);
|
||||
stack.stackSize = 0;
|
||||
sendNetworkUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEntity() {
|
||||
super.updateEntity();
|
||||
|
||||
if (worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The balance can also change through the owner's other EMC Builders, so poll it.
|
||||
if (++ticksSinceEmcSync >= EMC_SYNC_INTERVAL) {
|
||||
ticksSinceEmcSync = 0;
|
||||
|
||||
if (getStoredEmc() != sentEmc) {
|
||||
sendNetworkUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build() {
|
||||
BptBuilderBase bpt = getBlueprint();
|
||||
double emc = getStoredEmc();
|
||||
|
||||
if (!(bpt instanceof BptBuilderBlueprint) || emc <= 0) {
|
||||
super.build();
|
||||
return;
|
||||
}
|
||||
|
||||
// The needed item list is only filled once the builder has been initialized.
|
||||
bpt.initialize();
|
||||
prepareEmcSlots(((BptBuilderBlueprint) bpt).getNeededItems(), emc);
|
||||
|
||||
emcSlotsExposed = true;
|
||||
|
||||
try {
|
||||
super.build();
|
||||
} finally {
|
||||
emcSlotsExposed = false;
|
||||
chargeEmcSlots();
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareEmcSlots(List<RequirementItemStack> needs, double emc) {
|
||||
emcSlots.clear();
|
||||
|
||||
if (needs == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (RequirementItemStack need : needs) {
|
||||
if (need.stack == null || need.stack.getItem() == null || need.size <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
long value = EMCHelper.getEmcValue(need.stack);
|
||||
|
||||
if (value <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int affordable = (int) Math.min(Integer.MAX_VALUE, Math.floor(emc / value));
|
||||
int size = Math.min(Math.min(need.stack.getMaxStackSize(), need.size), affordable);
|
||||
|
||||
if (size <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemStack stack = need.stack.copy();
|
||||
stack.stackSize = size;
|
||||
emcSlots.add(new EmcSlot(stack, value));
|
||||
}
|
||||
}
|
||||
|
||||
private void chargeEmcSlots() {
|
||||
double cost = 0;
|
||||
|
||||
for (EmcSlot slot : emcSlots) {
|
||||
cost += (double) slot.consumed() * slot.emcPerItem;
|
||||
}
|
||||
|
||||
emcSlots.clear();
|
||||
|
||||
if (cost > 0) {
|
||||
EmcPool.get(worldObj)
|
||||
.add(owner, -cost);
|
||||
}
|
||||
}
|
||||
|
||||
private int realSize() {
|
||||
return super.getSizeInventory();
|
||||
}
|
||||
|
||||
private EmcSlot emcSlot(int i) {
|
||||
return emcSlotsExposed && i >= realSize() ? emcSlots.get(i - realSize()) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSizeInventory() {
|
||||
return emcSlotsExposed ? realSize() + emcSlots.size() : realSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStackInSlot(int i) {
|
||||
EmcSlot slot = emcSlot(i);
|
||||
return slot != null ? slot.stack : super.getStackInSlot(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack decrStackSize(int i, int amount) {
|
||||
EmcSlot slot = emcSlot(i);
|
||||
|
||||
if (slot == null) {
|
||||
return super.decrStackSize(i, amount);
|
||||
}
|
||||
|
||||
if (slot.stack == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ItemStack taken = slot.stack.splitStack(Math.min(amount, slot.stack.stackSize));
|
||||
|
||||
if (slot.stack.stackSize <= 0) {
|
||||
slot.stack = null;
|
||||
}
|
||||
|
||||
return taken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInventorySlotContents(int i, ItemStack stack) {
|
||||
EmcSlot slot = emcSlot(i);
|
||||
|
||||
if (slot == null) {
|
||||
super.setInventorySlotContents(i, stack);
|
||||
return;
|
||||
}
|
||||
|
||||
// Schematic.useItem only writes to a slot once its stack is used up (possibly leaving a container item
|
||||
// behind). Either way the whole virtual stack has been consumed; container items are not kept.
|
||||
slot.stack = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStackInSlotOnClosing(int i) {
|
||||
return emcSlot(i) != null ? null : super.getStackInSlotOnClosing(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemValidForSlot(int i, ItemStack stack) {
|
||||
return emcSlot(i) == null && super.isItemValidForSlot(i, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(NBTTagCompound nbt) {
|
||||
super.readFromNBT(nbt);
|
||||
owner = nbt.hasKey(OWNER_MOST) ? new UUID(nbt.getLong(OWNER_MOST), nbt.getLong(OWNER_LEAST)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(NBTTagCompound nbt) {
|
||||
super.writeToNBT(nbt);
|
||||
|
||||
if (owner != null) {
|
||||
nbt.setLong(OWNER_MOST, owner.getMostSignificantBits());
|
||||
nbt.setLong(OWNER_LEAST, owner.getLeastSignificantBits());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeData(ByteBuf stream) {
|
||||
super.writeData(stream);
|
||||
sentEmc = getStoredEmc();
|
||||
stream.writeDouble(sentEmc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readData(ByteBuf stream) {
|
||||
super.readData(stream);
|
||||
clientEmc = stream.readDouble();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user