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:
agomizi1cmandClaude Opus 5.5 committed 2026-10-27 10:13:59 +09:00
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();
}
}