Compare commits

...

19 Commits

Author SHA1 Message Date
Ghzdude 6425ef6ecd Fix NPE when posting changes for storage busses (#405) 2024-02-24 10:25:51 +08:00
Yang Xizhi 7ebb2a0fbb allow custom slot jei check and fix fluid color in cell workbanch (#401) 2024-02-18 23:06:07 -06:00
Neeve 20a1fec6fb Recache OreDict Buses on RegEx changes & adjust visibility logic (#395) 2024-02-05 13:05:31 +11:00
Yang Xizhi 0fffc829ab Fix invalid pattern outputs throwing NPE in crafting grid (#393) 2024-02-01 19:14:33 +11:00
NotMyWing 88635d9a8d Do not check white-/blacklist on extract
Slightly rollbacks #384, since extractables are filtered in getAvailableItems
Allows extracting inaccessible items from cells and overriding SB behavior via reporting non-extractables
2024-02-01 18:33:13 +11:00
Neeve 0fd0ed1b1c Fix Fluid Cells having no upgrades (#392) 2024-01-31 19:37:05 +11:00
Neeve 87f884228e Fix ME Storage Buses reporting contents regardless of settings (#384) 2024-01-30 16:10:52 +11:00
Serenibyss 3495d3dfd4 Use LoadingCache instead of HashMap for CableBusBakedModel (#385) 2024-01-30 14:19:50 +11:00
ZHAY10086 0acb03b83d Add zh_cn.lang entries for Sticky Card (#381) 2024-01-21 13:55:57 +11:00
Serenibyss 9adb0359dd Fix player UUID lookup server issue (#380) 2024-01-20 23:44:34 +11:00
Serenibyss ac259dce6a Fix Network Tool not working (#377) 2024-01-16 15:56:12 +11:00
Neeve 7a6d49412e Fix minor slot merge/update regressions (#376) 2024-01-16 15:55:13 +11:00
Yang Xizhi 10f47a560a Fix transformers causing NCDF on specific servers (#374) 2024-01-16 12:36:22 +11:00
Serenibyss a8f0bbe06b Add Sticky Card (#371)
Co-authored-by: NotMyWing <winwyv@gmail.com>
2024-01-16 12:27:13 +11:00
Serenibyss dd3cdfcec5 Fix landing/running particles for cable bus (#372)
Co-authored-by: NotMyWing <winwyv@gmail.com>
2024-01-15 13:40:01 -06:00
Neeve 503f14f0a6 Fix minor slot stack size regression (#375) 2024-01-15 13:39:04 -06:00
Neeve 30af345ceb Update mod base name (#373) 2024-01-16 01:13:04 +11:00
Serenibyss e8af0f228b Update ME IO Port tasks on grid changes (#370) 2024-01-15 18:01:53 +11:00
Serenibyss 0291ceff30 Fix Toast server crash (#367) 2024-01-14 13:15:45 +11:00
49 changed files with 654 additions and 124 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ aebuild=7
includeMCVersionJar = false
# The name of your jar when you produce builds, not including any versioning info
modArchivesBaseName = appliedenergistics2
modArchivesBaseName = ae2-uel
# Will update your build.gradle automatically whenever an update is available
autoUpdateBuildScript = false
+5 -1
View File
@@ -81,7 +81,11 @@ public enum Settings
PLACE_BLOCK( EnumSet.of( YesNo.YES, YesNo.NO ) ),
SCHEDULING_MODE( EnumSet.allOf( SchedulingMode.class ) );
SCHEDULING_MODE( EnumSet.allOf( SchedulingMode.class ) ),
STICKY_MODE( EnumSet.of( YesNo.YES, YesNo.NO ) ),
;
private final EnumSet<? extends Enum<?>> values;
@@ -40,6 +40,7 @@ public enum Upgrades {
REDSTONE(0),
CRAFTING(0),
MAGNET(0),
STICKY(0),
/**
* Diamond Tier Upgrades.
@@ -100,6 +100,8 @@ public interface IMaterials {
IItemDefinition cardCrafting();
IItemDefinition cardSticky();
IItemDefinition enderDust();
IItemDefinition flour();
@@ -89,4 +89,12 @@ public interface IMEInventoryHandler<T extends IAEStack<T>> extends IMEInventory
* @return true, if this inventory is valid for this pass.
*/
boolean validForPass( int i );
/**
* Gets whether an inventory is "Sticky" i.e. only it and other sticky storages that have partitions with certain
* items are allowed to be put into sticky storages.
*/
default boolean isSticky() {
return false;
}
}
@@ -29,8 +29,10 @@ import appeng.block.AEBaseTileBlock;
import appeng.client.UnlistedProperty;
import appeng.client.render.cablebus.CableBusBakedModel;
import appeng.client.render.cablebus.CableBusRenderState;
import appeng.client.render.cablebus.FacadeRenderState;
import appeng.core.AppEng;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketCableBusLandingParticle;
import appeng.core.sync.packets.PacketClick;
import appeng.helpers.AEGlassMaterial;
import appeng.integration.abstraction.IAEFacade;
@@ -70,10 +72,12 @@ import net.minecraft.util.math.RayTraceResult.Type;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.property.ExtendedBlockState;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@@ -298,6 +302,90 @@ public class BlockCableBus extends AEBaseTileBlock implements IAEFacade {
return true;
}
@Override
public boolean addRunningEffects(IBlockState state, World world, BlockPos pos, Entity entity) {
if (world.isRemote) {
addRunningParticle(world, pos, entity);
}
return true;
}
@SideOnly(Side.CLIENT)
private void addRunningParticle(World world, BlockPos pos, Entity entity) {
final ICableBusContainer cb = this.cb(world, pos);
final IBakedModel model = Minecraft.getMinecraft().getBlockRendererDispatcher().getModelForState(this.getDefaultState());
if (!(model instanceof CableBusBakedModel cableBusModel)) {
return;
}
final CableBusRenderState renderState = cb.getRenderState();
final TextureAtlasSprite texture = getSpriteForParticle(renderState, cableBusModel);
if (texture != null) {
final double d0 = entity.posX + (world.rand.nextFloat() - 0.5f) * entity.width;
final double d1 = entity.getEntityBoundingBox().minY + 0.1f;
final double d2 = entity.posZ + (world.rand.nextFloat() - 0.5f) * entity.width;
final ParticleDigging particle = new DestroyFX(world, d0, d1, d2, -entity.motionX * 4.0f, 1.5f, -entity.motionZ * 4.0f, this.getDefaultState()).setBlockPos(pos);
particle.setParticleTexture(texture);
Minecraft.getMinecraft().effectRenderer.addEffect(particle);
}
}
@Override
public boolean addLandingEffects(IBlockState state, WorldServer world, BlockPos pos, IBlockState iblockstate, EntityLivingBase entity, int numberOfParticles) {
// for reasons only notch can explain, this method is only called on the server, so we have to sync
// a packet to all tracking players for landing particle effects
if (!world.isRemote) {
final PacketCableBusLandingParticle packet = new PacketCableBusLandingParticle(pos, entity, numberOfParticles);
final NetworkRegistry.TargetPoint point = new NetworkRegistry.TargetPoint(world.provider.getDimension(), pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 32);
NetworkHandler.instance().sendToAllTracking(packet, point);
}
return true;
}
@SideOnly(Side.CLIENT)
public void addLandingParticle(BlockPos pos, double entityX, double entityY, double entityZ, int numberOfParticles) {
final World world = Minecraft.getMinecraft().world;
final ICableBusContainer cb = this.cb(world, pos);
final IBakedModel model = Minecraft.getMinecraft().getBlockRendererDispatcher().getModelForState(this.getDefaultState());
if (!(model instanceof CableBusBakedModel cableBusModel)) {
return;
}
final TextureAtlasSprite texture = getSpriteForParticle(cb.getRenderState(), cableBusModel);
if (texture != null) {
final Vec3d startVec = new Vec3d(entityX, entityY, entityZ);
final Vec3d endVec = startVec.add(0.0f, -4.0f, 0.0f);
RayTraceResult result = world.rayTraceBlocks(startVec, endVec, true, false, true);
final double speed = 0.15f;
if (result != null && result.typeOfHit == Type.BLOCK && numberOfParticles != 0) {
for (int i = 0; i < numberOfParticles; i++) {
final double d0 = world.rand.nextGaussian() * speed;
final double d1 = world.rand.nextGaussian() * speed;
final double d2 = world.rand.nextGaussian() * speed;
final ParticleDigging particle = new DestroyFX(world, entityX, entityY, entityZ, d0, d1, d2, this.getDefaultState()).setBlockPos(pos);
particle.setParticleTexture(texture);
Minecraft.getMinecraft().effectRenderer.addEffect(particle);
}
}
}
}
@SideOnly(Side.CLIENT)
private TextureAtlasSprite getSpriteForParticle(CableBusRenderState renderState, CableBusBakedModel cableBusModel) {
final FacadeRenderState frs = renderState.getFacades().get(EnumFacing.UP);
if (frs != null) {
final IBlockState state = frs.getSourceBlock();
final IBakedModel model = Minecraft.getMinecraft().getBlockRendererDispatcher().getModelForState(state);
return model.getParticleTexture();
}
return Platform.pickRandom(cableBusModel.getParticleTextures(renderState));
}
@Override
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos) {
if (Platform.isServer()) {
+15 -1
View File
@@ -54,6 +54,7 @@ import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Items;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumHand;
@@ -82,6 +83,7 @@ import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import static appeng.client.KeyBindings.WCT;
import static appeng.client.KeyBindings.WFT;
@@ -372,4 +374,16 @@ public class ClientHelper extends ServerHelper {
public boolean isActionKey(ActionKey key, int pressedKeyCode) {
return this.bindings.get(key).isActiveAndMatches(pressedKeyCode);
}
}
@Override
public EntityPlayer getPlayerByUUID(UUID uuid) {
if (Platform.isClient()) {
if (Minecraft.getMinecraft().player.getUniqueID().equals(uuid)) {
return Minecraft.getMinecraft().player;
}
return null;
} else {
return super.getPlayerByUUID(uuid);
}
}
}
@@ -1,10 +1,14 @@
package appeng.client.gui;
import appeng.api.storage.data.IAEItemStack;
import appeng.client.gui.implementations.*;
import appeng.client.gui.implementations.GuiCraftAmount;
import appeng.client.gui.implementations.GuiCraftConfirm;
import appeng.client.gui.implementations.GuiCraftingCPU;
import appeng.client.gui.implementations.GuiExpandedProcessingPatternTerm;
import appeng.client.gui.implementations.GuiPatternTerm;
import appeng.client.gui.implementations.GuiUpgradeable;
import appeng.container.interfaces.IJEIGhostIngredients;
import appeng.container.slot.SlotFake;
import appeng.fluids.client.gui.widgets.GuiFluidSlot;
import appeng.container.slot.IJEITargetSlot;
import mezz.jei.api.gui.IAdvancedGuiHandler;
import mezz.jei.api.gui.IGhostIngredientHandler;
import net.minecraft.client.gui.GuiScreen;
@@ -78,12 +82,12 @@ public class AEGuiHandler implements IAdvancedGuiHandler<AEBaseGui>, IGhostIngre
return (guiSloty * 3) + guiSlotx + (currentScroll * 3);
}
@SuppressWarnings("unchecked")
@Override
@Nonnull
public <I> List<Target<I>> getTargets(@Nonnull AEBaseGui gui, @Nonnull I ingredient, boolean doStart) {
ArrayList<Target<I>> targets = new ArrayList<>();
if (gui instanceof IJEIGhostIngredients) {
IJEIGhostIngredients g = (IJEIGhostIngredients) gui;
if (gui instanceof IJEIGhostIngredients g) {
List<Target<?>> phantomTargets = g.getPhantomTargets(ingredient);
targets.addAll((List<Target<I>>) (Object) phantomTargets);
}
@@ -91,13 +95,8 @@ public class AEGuiHandler implements IAdvancedGuiHandler<AEBaseGui>, IGhostIngre
if (gui instanceof GuiUpgradeable || gui instanceof GuiPatternTerm || gui instanceof GuiExpandedProcessingPatternTerm) {
IJEIGhostIngredients ghostGui = ((IJEIGhostIngredients) gui);
for (Target<I> target : targets) {
if (ghostGui.getFakeSlotTargetMap().get(target) instanceof SlotFake) {
if (((SlotFake) ghostGui.getFakeSlotTargetMap().get(target)).getStack().isEmpty()) {
target.accept(ingredient);
break;
}
} else if (ghostGui.getFakeSlotTargetMap().get(target) instanceof GuiFluidSlot) {
if (((GuiFluidSlot) ghostGui.getFakeSlotTargetMap().get(target)).getFluidStack() == null) {
if (ghostGui.getFakeSlotTargetMap().get(target) instanceof IJEITargetSlot jeiSlot) {
if (jeiSlot.needAccept()) {
target.accept(ingredient);
break;
}
@@ -47,6 +47,7 @@ import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidUtil;
import org.lwjgl.input.Mouse;
import javax.annotation.Nonnull;
import java.awt.*;
import java.io.IOException;
import java.util.List;
@@ -54,7 +55,7 @@ import java.util.*;
public class GuiUpgradeable extends AEBaseGui implements IJEIGhostIngredients {
private final Map<Target<?>, Object> mapTargetSlot = new HashMap<>();
protected final Map<Target<?>, Object> mapTargetSlot = new HashMap<>();
protected final ContainerUpgradeable cvb;
protected final IUpgradeableHost bc;
@@ -218,24 +219,25 @@ public class GuiUpgradeable extends AEBaseGui implements IJEIGhostIngredients {
List<Target<?>> targets = new ArrayList<>();
List<IJEITargetSlot> slots = new ArrayList<>();
if (this.inventorySlots.inventorySlots.size() > 0) {
if (!this.inventorySlots.inventorySlots.isEmpty()) {
for (Slot slot : this.inventorySlots.inventorySlots) {
if (slot instanceof SlotFake && (!itemStack.isEmpty() || this instanceof GuiCellWorkbench && fluidStack != null)) {
slots.add((IJEITargetSlot) slot);
}
}
}
if (this.getGuiSlots().size() > 0) {
if (!this.getGuiSlots().isEmpty()) {
for (GuiCustomSlot slot : this.getGuiSlots()) {
if (slot instanceof GuiFluidSlot && fluidStack != null) {
slots.add((IJEITargetSlot) slot);
}
}
}
for (Object slot : slots) {
for (IJEITargetSlot slot : slots) {
ItemStack finalItemStack = itemStack;
FluidStack finalFluidStack = fluidStack;
Target<Object> targetItem = new Target<Object>() {
Target<Object> targetItem = new Target<>() {
@Nonnull
@Override
public Rectangle getArea() {
if (slot instanceof SlotFake && ((SlotFake) slot).isSlotEnabled()) {
@@ -247,20 +249,20 @@ public class GuiUpgradeable extends AEBaseGui implements IJEIGhostIngredients {
}
@Override
public void accept(Object ingredient) {
public void accept(@Nonnull Object ingredient) {
PacketInventoryAction p = null;
try {
if (slot instanceof SlotFake && ((SlotFake) slot).isSlotEnabled()) {
if (finalItemStack.isEmpty() && finalFluidStack != null) {
p = new PacketInventoryAction(InventoryAction.PLACE_JEI_GHOST_ITEM, (IJEITargetSlot) slot, AEItemStack.fromItemStack(FluidUtil.getFilledBucket(finalFluidStack)));
p = new PacketInventoryAction(InventoryAction.PLACE_JEI_GHOST_ITEM, slot, AEItemStack.fromItemStack(FluidUtil.getFilledBucket(finalFluidStack)));
} else if (!finalItemStack.isEmpty()) {
p = new PacketInventoryAction(InventoryAction.PLACE_JEI_GHOST_ITEM, (IJEITargetSlot) slot, AEItemStack.fromItemStack(finalItemStack));
p = new PacketInventoryAction(InventoryAction.PLACE_JEI_GHOST_ITEM, slot, AEItemStack.fromItemStack(finalItemStack));
}
} else {
if (finalFluidStack == null) {
return;
}
p = new PacketInventoryAction(InventoryAction.PLACE_JEI_GHOST_ITEM, (IJEITargetSlot) slot, AEItemStack.fromItemStack(AEFluidStack.fromFluidStack(finalFluidStack).asItemStackRepresentation()));
p = new PacketInventoryAction(InventoryAction.PLACE_JEI_GHOST_ITEM, slot, AEItemStack.fromItemStack(AEFluidStack.fromFluidStack(finalFluidStack).asItemStackRepresentation()));
}
NetworkHandler.instance().sendToServer(p);
@@ -24,6 +24,10 @@ import appeng.api.parts.IPartModel;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
import appeng.block.networking.BlockCableBus;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.Weigher;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BakedQuad;
@@ -38,6 +42,7 @@ import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.common.property.IExtendedBlockState;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.Map.Entry;
@@ -45,8 +50,6 @@ import java.util.Map.Entry;
public class CableBusBakedModel implements IBakedModel {
static final Map<CableBusRenderState, List<BakedQuad>> CABLE_MODEL_CACHE = new HashMap<>();
private final CableBuilder cableBuilder;
private final FacadeBuilder facadeBuilder;
@@ -57,11 +60,24 @@ public class CableBusBakedModel implements IBakedModel {
private final TextureMap textureMap = Minecraft.getMinecraft().getTextureMapBlocks();
private final LoadingCache<CableBusRenderState, List<BakedQuad>> cableModelCache;
CableBusBakedModel(CableBuilder cableBuilder, FacadeBuilder facadeBuilder, Map<ResourceLocation, IBakedModel> partModels, TextureAtlasSprite particleTexture) {
this.cableBuilder = cableBuilder;
this.facadeBuilder = facadeBuilder;
this.partModels = partModels;
this.particleTexture = particleTexture;
this.cableModelCache = CacheBuilder.newBuilder()
.maximumWeight(5000)
.weigher((Weigher<CableBusRenderState, List<BakedQuad>>) (k, v) -> v.size())
.build(new CacheLoader<>() {
@Override
public List<BakedQuad> load(@Nonnull CableBusRenderState rs) {
final List<BakedQuad> model = new ArrayList<>();
addCableQuads(rs, model);
return model;
}
});
}
@Override
@@ -82,12 +98,7 @@ public class CableBusBakedModel implements IBakedModel {
if (layer == BlockRenderLayer.CUTOUT) {
// First, handle the cable at the center of the cable bus
final List<BakedQuad> cableModel = CABLE_MODEL_CACHE.computeIfAbsent(renderState, k ->
{
final List<BakedQuad> model = new ArrayList<>();
this.addCableQuads(renderState, model);
return model;
});
final List<BakedQuad> cableModel = cableModelCache.getUnchecked(renderState);
quads.addAll(cableModel);
// Then handle attachments
@@ -27,26 +27,21 @@ import com.google.common.collect.ImmutableMap;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.client.resource.IResourceType;
import net.minecraftforge.client.resource.ISelectiveResourceReloadListener;
import net.minecraftforge.client.resource.VanillaResourceType;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.TRSRTransformation;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
/**
* The built-in model for the cable bus block.
*/
public class CableBusModel implements IModel, ISelectiveResourceReloadListener {
public class CableBusModel implements IModel {
private final PartModels partModels;
@@ -106,12 +101,4 @@ public class CableBusModel implements IModel, ISelectiveResourceReloadListener {
public IModelState getDefaultState() {
return TRSRTransformation.identity();
}
@Override
public void onResourceManagerReload(IResourceManager resourceManager, Predicate<IResourceType> resourcePredicate) {
if (resourcePredicate.test(VanillaResourceType.MODELS)) {
CableBusBakedModel.CABLE_MODEL_CACHE.clear();
}
}
}
@@ -399,7 +399,7 @@ public abstract class AEBaseContainer extends Container {
return ItemStack.EMPTY; // don't insert duplicate encoded patterns to interfaces
}
int maxSize = Math.max(tis.getMaxStackSize(), d.getSlotStackLimit());
int maxSize = Math.min(tis.getMaxStackSize(), d.getSlotStackLimit());
int placeAble = maxSize - t.getCount();
@@ -435,7 +435,7 @@ public abstract class AEBaseContainer extends Container {
if (d.isItemValid(tis)) {
if (!d.getHasStack()) {
int maxSize = Math.max(tis.getMaxStackSize(), d.getSlotStackLimit());
int maxSize = Math.min(tis.getMaxStackSize(), d.getSlotStackLimit());
final ItemStack tmp = tis.copy();
if (tmp.getCount() > maxSize) {
@@ -964,26 +964,34 @@ public abstract class AEBaseContainer extends Container {
if (!draggedStack.isEmpty()) {
if (appEngSlot.isItemValid(draggedStack)) {
if (slotStack.getItem() == draggedStack.getItem() && slotStack.getMetadata() == draggedStack.getMetadata() && ItemStack.areItemStackTagsEqual(slotStack, draggedStack)) {
var maxSize = Math.max(appEngSlot.getSlotStackLimit(), draggedStack.getMaxStackSize());
var maxInsertable = Math.min(draggedStack.getCount(), maxSize - appEngSlot.getStack().getCount());
var toInsert = Math.min(maxInsertable, dragType == 0 ? maxInsertable : 1);
// Slot size or stack size, whichever is smaller.
var maxSize = Math.min(appEngSlot.getSlotStackLimit(), draggedStack.getMaxStackSize());
draggedStack.shrink(toInsert);
slotStack.grow(toInsert);
// The maximum number of items that can be inserted into the slot, non-negative.
var maxInsertable = Math.min(draggedStack.getCount(),
Math.max(0, maxSize - appEngSlot.getStack().getCount()));
slot.onSlotChanged();
return ItemStack.EMPTY;
if (maxInsertable != 0) {
var toInsert = Math.min(maxInsertable, dragType == 0 ? maxInsertable : 1);
draggedStack.shrink(toInsert);
slotStack.grow(toInsert);
slot.putStack(slot.getStack());
return ItemStack.EMPTY;
}
}
}
}
// Fixes taking and halving issues from oversized slots.
else if (dragType == 0 || dragType == 1) {
if (slot.canTakeStack(player) && !slotStack.isEmpty()) {
var result = slotStack.copy();
var toTake = Math.min(slotStack.getCount(), slotStack.getMaxStackSize());
this.invPlayer.setItemStack(slot.decrStackSize(dragType == 0 ? toTake : (toTake + 1) / 2));
slot.onTake(player, invPlayer.getItemStack());
return ItemStack.EMPTY;
slot.putStack(slot.getStack());
return result;
}
}
@@ -50,6 +50,9 @@ public class ContainerStorageBus extends ContainerUpgradeable {
@GuiSync(4)
public StorageFilter storageFilter = StorageFilter.EXTRACTABLE_ONLY;
@GuiSync(7)
public YesNo stickyMode = YesNo.NO;
public ContainerStorageBus(final InventoryPlayer ip, final PartStorageBus te) {
super(ip, te);
this.storageBus = te;
@@ -111,6 +114,7 @@ public class ContainerStorageBus extends ContainerUpgradeable {
this.setFuzzyMode((FuzzyMode) this.getUpgradeable().getConfigManager().getSetting(Settings.FUZZY_MODE));
this.setReadWriteMode((AccessRestriction) this.getUpgradeable().getConfigManager().getSetting(Settings.ACCESS));
this.setStorageFilter((StorageFilter) this.getUpgradeable().getConfigManager().getSetting(Settings.STORAGE_FILTER));
this.setStickyMode((YesNo) this.getUpgradeable().getConfigManager().getSetting(Settings.STICKY_MODE));
}
this.standardDetectAndSendChanges();
@@ -168,4 +172,12 @@ public class ContainerStorageBus extends ContainerUpgradeable {
private void setStorageFilter(final StorageFilter storageFilter) {
this.storageFilter = storageFilter;
}
public YesNo getStickyMode() {
return this.stickyMode;
}
private void setStickyMode(final YesNo stickyMode) {
this.stickyMode = stickyMode;
}
}
@@ -1,4 +1,9 @@
package appeng.container.slot;
public interface IJEITargetSlot {
default boolean needAccept() {
return false;
}
}
@@ -50,7 +50,6 @@ public class SlotFake extends AppEngSlot implements IJEITargetSlot {
if (!is.isEmpty()) {
is = is.copy();
}
super.putStack(is);
}
@@ -58,4 +57,10 @@ public class SlotFake extends AppEngSlot implements IJEITargetSlot {
public boolean canTakeStack(final EntityPlayer par1EntityPlayer) {
return false;
}
@Override
public boolean needAccept() {
return this.getStack().isEmpty();
}
}
@@ -25,6 +25,7 @@ import appeng.client.ActionKey;
import appeng.client.EffectType;
import appeng.core.sync.AppEngPacket;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
@@ -32,6 +33,7 @@ import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.Random;
import java.util.UUID;
public abstract class CommonHelper {
@@ -66,4 +68,5 @@ public abstract class CommonHelper {
public abstract boolean isActionKey(@Nonnull final ActionKey key, int pressedKeyCode);
public abstract EntityPlayer getPlayerByUUID(UUID uuid);
}
@@ -364,15 +364,19 @@ final class Registration {
// Storage Cells
Upgrades.FUZZY.registerItem(items.cell1k(), 1);
Upgrades.INVERTER.registerItem(items.cell1k(), 1);
Upgrades.STICKY.registerItem(items.cell1k(), 1);
Upgrades.FUZZY.registerItem(items.cell4k(), 1);
Upgrades.INVERTER.registerItem(items.cell4k(), 1);
Upgrades.STICKY.registerItem(items.cell4k(), 1);
Upgrades.FUZZY.registerItem(items.cell16k(), 1);
Upgrades.INVERTER.registerItem(items.cell16k(), 1);
Upgrades.STICKY.registerItem(items.cell16k(), 1);
Upgrades.FUZZY.registerItem(items.cell64k(), 1);
Upgrades.INVERTER.registerItem(items.cell64k(), 1);
Upgrades.STICKY.registerItem(items.cell64k(), 1);
Upgrades.FUZZY.registerItem(items.portableCell(), 1);
Upgrades.INVERTER.registerItem(items.portableCell(), 1);
@@ -383,14 +387,29 @@ final class Registration {
Upgrades.FUZZY.registerItem(AEApi.instance().definitions().materials().cardMagnet(), 1);
Upgrades.INVERTER.registerItem(AEApi.instance().definitions().materials().cardMagnet(), 1);
// Fluid Cells
Upgrades.INVERTER.registerItem(items.fluidCell1k(), 1);
Upgrades.STICKY.registerItem(items.fluidCell1k(), 1);
Upgrades.INVERTER.registerItem(items.fluidCell4k(), 1);
Upgrades.STICKY.registerItem(items.fluidCell4k(), 1);
Upgrades.INVERTER.registerItem(items.fluidCell16k(), 1);
Upgrades.STICKY.registerItem(items.fluidCell16k(), 1);
Upgrades.INVERTER.registerItem(items.fluidCell64k(), 1);
Upgrades.STICKY.registerItem(items.fluidCell64k(), 1);
// Storage Bus
Upgrades.FUZZY.registerItem(parts.storageBus(), 1);
Upgrades.INVERTER.registerItem(parts.storageBus(), 1);
Upgrades.CAPACITY.registerItem(parts.storageBus(), 5);
Upgrades.STICKY.registerItem(parts.storageBus(), 1);
// Storage Bus Fluids
Upgrades.INVERTER.registerItem(parts.fluidStorageBus(), 1);
Upgrades.CAPACITY.registerItem(parts.fluidStorageBus(), 5);
Upgrades.STICKY.registerItem(parts.fluidStorageBus(), 1);
// Formation Plane
Upgrades.FUZZY.registerItem(parts.formationPlane(), 1);
@@ -60,6 +60,10 @@ public class ApiClientHelper implements IClientHelper {
lines.add("[" + GuiText.Partitioned.getLocal() + "]" + " - " + list + ' ' + GuiText.Precise.getLocal());
}
if (handler.isSticky()) {
lines.add(GuiText.Sticky.getLocal());
}
if (Minecraft.getMinecraft().gameSettings.advancedItemTooltips || Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
IItemHandler inv = cellInventory.getConfigInventory();
cellInventory.getAvailableItems((IItemList) itemList);
@@ -90,6 +90,7 @@ public final class ApiMaterials implements IMaterials {
private final IItemDefinition cardFuzzy;
private final IItemDefinition cardInverter;
private final IItemDefinition cardCrafting;
private final IItemDefinition cardSticky;
private final IItemDefinition enderDust;
private final IItemDefinition flour;
@@ -208,6 +209,7 @@ public final class ApiMaterials implements IMaterials {
this.cardFuzzy = new DamagedItemDefinition("material.card.fuzzy", materials.createMaterial(MaterialType.CARD_FUZZY));
this.cardInverter = new DamagedItemDefinition("material.card.inverter", materials.createMaterial(MaterialType.CARD_INVERTER));
this.cardCrafting = new DamagedItemDefinition("material.card.crafting", materials.createMaterial(MaterialType.CARD_CRAFTING));
this.cardSticky = new DamagedItemDefinition("material.card.sticky", materials.createMaterial(MaterialType.CARD_STICKY));
this.enderDust = new DamagedItemDefinition("material.dust.ender", materials.createMaterial(MaterialType.ENDER_DUST));
this.flour = new DamagedItemDefinition("material.flour", materials.createMaterial(MaterialType.FLOUR));
@@ -425,6 +427,11 @@ public final class ApiMaterials implements IMaterials {
return this.cardCrafting;
}
@Override
public IItemDefinition cardSticky() {
return this.cardSticky;
}
@Override
public IItemDefinition enderDust() {
return this.enderDust;
@@ -195,6 +195,7 @@ public enum GuiText {
Partitioned,
Precise,
Fuzzy,
Sticky,
// Used in a terminal to indicate that an item is craftable
SmallFontCraft,
@@ -88,7 +88,11 @@ public class AppEngPacketHandlerBase {
PACKET_CRAFTING_TOAST(PacketCraftingToast.class),
PACKET_COLOR_APPLICATOR_SELECT_COLOR(PacketColorApplicatorSelectColor.class);
PACKET_COLOR_APPLICATOR_SELECT_COLOR(PacketColorApplicatorSelectColor.class),
PACKET_CABLE_BUS_LANDING_PARTICLE(PacketCableBusLandingParticle.class),
;
private final Class<? extends AppEngPacket> packetClass;
@@ -112,6 +112,10 @@ public class NetworkHandler {
this.ec.sendToAllAround(message.getProxy(), point);
}
public void sendToAllTracking(final AppEngPacket message, final NetworkRegistry.TargetPoint point) {
this.ec.sendToAllTracking(message.getProxy(), point);
}
public void sendToDimension(final AppEngPacket message, final int dimensionId) {
this.ec.sendToDimension(message.getProxy(), dimensionId);
}
@@ -0,0 +1,55 @@
package appeng.core.sync.packets;
import appeng.block.networking.BlockCableBus;
import appeng.core.sync.AppEngPacket;
import appeng.core.sync.network.INetworkInfo;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class PacketCableBusLandingParticle extends AppEngPacket {
private BlockPos pos;
private double entityX;
private double entityY;
private double entityZ;
private int numberOfParticles;
public PacketCableBusLandingParticle(final ByteBuf stream) {
this.pos = BlockPos.fromLong(stream.readLong());
this.entityX = stream.readDouble();
this.entityY = stream.readDouble();
this.entityZ = stream.readDouble();
this.numberOfParticles = stream.readInt();
}
public PacketCableBusLandingParticle(final BlockPos pos, final Entity entity, final int numberOfParticles) {
final ByteBuf data = Unpooled.buffer();
data.writeInt(this.getPacketID());
data.writeLong(pos.toLong());
data.writeDouble(entity.posX);
data.writeDouble(entity.posY);
data.writeDouble(entity.posZ);
data.writeInt(numberOfParticles);
this.configureWrite(data);
}
@Override
@SideOnly(Side.CLIENT)
public void clientPacketData(INetworkInfo network, AppEngPacket packet, EntityPlayer player) {
final World world = Minecraft.getMinecraft().world;
final IBlockState state = world.getBlockState(pos);
if (state.getBlock() instanceof BlockCableBus cb) {
cb.addLandingParticle(pos, entityX, entityY, entityZ, numberOfParticles);
}
}
}
@@ -22,10 +22,12 @@ package appeng.core.sync.packets;
import appeng.block.networking.BlockCableBus;
import appeng.core.sync.AppEngPacket;
import appeng.core.sync.network.INetworkInfo;
import appeng.items.tools.ToolNetworkTool;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
@@ -97,6 +99,11 @@ public class PacketClick extends AppEngPacket {
if (block instanceof BlockCableBus) {
((BlockCableBus) block).onBlockClickPacket(player.world, pos, player, this.hand, new Vec3d(this.hitX, this.hitY, this.hitZ));
}
} else {
final ItemStack is = player.inventory.getCurrentItem();
if (!is.isEmpty() && is.getItem() instanceof ToolNetworkTool tnt) {
tnt.serverSideToolLogic(is, player, hand, player.world, pos, side, hitX, hitY, hitZ);
}
}
}
}
@@ -11,6 +11,8 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import java.io.IOException;
@@ -39,11 +41,15 @@ public class PacketCraftingToast extends AppEngPacket {
@Override
public void clientPacketData(INetworkInfo network, AppEngPacket packet, EntityPlayer player) {
if (AEConfig.instance().isFeatureEnabled(AEFeature.CRAFTING_TOASTS)) {
Minecraft.getMinecraft()
.getToastGui().add(new CraftingStatusToast(stack.asItemStackRepresentation(), cancelled));
doCraftingToast();
}
}
@SideOnly(Side.CLIENT)
private void doCraftingToast() {
Minecraft.getMinecraft().getToastGui().add(new CraftingStatusToast(stack.asItemStackRepresentation(), cancelled));
}
@Override
public void serverPacketData(INetworkInfo manager, AppEngPacket packet, EntityPlayer player) {}
}
@@ -24,6 +24,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.io.ByteStreams;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.Launch;
import net.minecraftforge.fml.common.Loader;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
@@ -31,7 +32,11 @@ import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import java.io.IOException;
import java.io.InputStream;
@@ -48,7 +53,7 @@ public class AE2ELTransformer implements IClassTransformer {
if ("net.minecraftforge.common.ForgeHooks".equals(transformedName)) {
ClassReader cr = new ClassReader(basicClass);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
ClassWriter cw = new SafeClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
ClassVisitor cv = new PickBlockPatch(cw);
cr.accept(cv, ClassReader.EXPAND_FRAMES);
return cw.toByteArray();
@@ -188,4 +193,39 @@ public class AE2ELTransformer implements IClassTransformer {
}
private static class SafeClassWriter extends ClassWriter {
public SafeClassWriter(int flags) {
super(flags);
}
@Override
protected String getCommonSuperClass(final String type1, final String type2) {
Class<?> c, d;
// clueless
ClassLoader classLoader = Launch.classLoader;
try {
c = Class.forName(type1.replace('/', '.'), false, classLoader);
d = Class.forName(type2.replace('/', '.'), false, classLoader);
} catch (Exception e) {
throw new RuntimeException(e.toString());
}
if (c.isAssignableFrom(d)) {
return type1;
}
if (d.isAssignableFrom(c)) {
return type2;
}
if (c.isInterface() || d.isInterface()) {
return "java/lang/Object";
} else {
do {
c = c.getSuperclass();
} while (!c.isAssignableFrom(d));
return c.getName().replace('.', '/');
}
}
}
}
@@ -93,4 +93,10 @@ public class GuiFluidSlot extends GuiCustomSlot implements IJEITargetSlot {
this.fluids.setFluidInSlot(this.slot, stack);
NetworkHandler.instance().sendToServer(new PacketFluidSlot(Collections.singletonMap(this.getId(), this.getFluidStack())));
}
@Override
public boolean needAccept() {
return this.getFluidStack() == null;
}
}
@@ -22,6 +22,7 @@ package appeng.fluids.items;
import appeng.bootstrap.IItemRendering;
import appeng.bootstrap.ItemRenderingCustomizer;
import appeng.client.render.DummyFluidItemModel;
import net.minecraftforge.fluids.FluidStack;
/**
@@ -33,5 +34,9 @@ public class FluidDummyItemRendering extends ItemRenderingCustomizer {
@Override
public void customize(IItemRendering rendering) {
rendering.builtInModel("models/item/dummy_fluid_item", new DummyFluidItemModel());
rendering.color(((s, i) -> {
FluidStack fluid = ((FluidDummyItem) s.getItem()).getFluidStack(s);
return fluid != null ? fluid.getFluid().getColor() : 0xFFFFFFFF;
}));
}
}
@@ -80,6 +80,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -220,11 +221,13 @@ public class PartFluidStorageBus extends PartUpgradeable implements IGridTickabl
@Override
public void postChange(final IBaseMonitor<IAEFluidStack> monitor, final Iterable<IAEFluidStack> change, final IActionSource source) {
if (this.getProxy().isActive()) {
var filteredChanges = this.filterChanges(change);
AccessRestriction currentAccess = (AccessRestriction) ((ConfigManager) this.getConfigManager()).getSetting(Settings.ACCESS);
if (readOncePass) {
readOncePass = false;
try {
this.getProxy().getStorage().postAlterationOfStoredItems(AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class), change, this.source);
this.getProxy().getStorage().postAlterationOfStoredItems(AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class), filteredChanges, this.source);
} catch (final GridAccessException e) {
// :(
}
@@ -234,7 +237,7 @@ public class PartFluidStorageBus extends PartUpgradeable implements IGridTickabl
return;
}
try {
this.getProxy().getStorage().postAlterationOfStoredItems(AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class), change, source);
this.getProxy().getStorage().postAlterationOfStoredItems(AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class), filteredChanges, source);
} catch (final GridAccessException e) {
// :(
}
@@ -426,6 +429,7 @@ public class PartFluidStorageBus extends PartUpgradeable implements IGridTickabl
this.handler.setBaseAccess((AccessRestriction) this.getConfigManager().getSetting(Settings.ACCESS));
this.handler.setWhitelist(this.getInstalledUpgrades(Upgrades.INVERTER) > 0 ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST);
this.handler.setPriority(this.getPriority());
this.handler.setStorageFilter((StorageFilter) this.getConfigManager().getSetting(Settings.STORAGE_FILTER));
final IItemList<IAEFluidStack> priorityList = AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class).createList();
@@ -437,6 +441,10 @@ public class PartFluidStorageBus extends PartUpgradeable implements IGridTickabl
}
}
if (this.getInstalledUpgrades(Upgrades.STICKY) > 0) {
this.handler.setSticky(true);
}
if (this.getInstalledUpgrades(Upgrades.FUZZY) > 0) {
this.handler.setPartitionList(new FuzzyPriorityList<IAEFluidStack>(priorityList, (FuzzyMode) this.getConfigManager().getSetting(Settings.FUZZY_MODE)));
} else {
@@ -533,4 +541,26 @@ public class PartFluidStorageBus extends PartUpgradeable implements IGridTickabl
public GuiBridge getGuiBridge() {
return GuiBridge.GUI_STORAGEBUS_FLUID;
}
// TODO: 1/28/2024 Unify both methods.
/**
* Filters the changes to only include items that pass the storage filter.
* Optimally, this should be handled by the underlying monitor.
*
* @see appeng.parts.misc.PartStorageBus#filterChanges
*/
protected Iterable<IAEFluidStack> filterChanges(Iterable<IAEFluidStack> change) {
var storageFilter = this.getConfigManager().getSetting(Settings.STORAGE_FILTER);
if (storageFilter == StorageFilter.EXTRACTABLE_ONLY && handler != null) {
var filteredList = new ArrayList<IAEFluidStack>();
for (final IAEFluidStack stack : change) {
if (this.handler.passesBlackOrWhitelist(stack)) {
filteredList.add(stack);
}
}
return filteredList;
}
return change;
}
}
@@ -1,28 +0,0 @@
package appeng.helpers;
import appeng.util.Platform;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.server.MinecraftServer;
import net.minecraftforge.fml.server.FMLServerHandler;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public class PlayerHelper {
@Nullable
public static EntityPlayerMP getPlayerByUUID(UUID uuid) {
final MinecraftServer server;
if (Platform.isClientInstall()) {
server = Minecraft.getMinecraft().getIntegratedServer();
} else {
server = FMLServerHandler.instance().getServer();
}
if (server == null) {
return null;
}
return server.getPlayerList().getPlayerByUUID(uuid);
}
}
@@ -166,6 +166,8 @@ public final class ItemMaterial extends AEBaseItem implements IStorageComponent,
return Upgrades.MAGNET;
case CARD_QUANTUM_LINK:
return Upgrades.QUANTUM_LINK;
case CARD_STICKY:
return Upgrades.STICKY;
default:
return null;
}
@@ -120,7 +120,9 @@ public enum MaterialType {
CARD_PATTERN_EXPANSION(58, "material_card_pattern_expansion", EnumSet.of(AEFeature.ADVANCED_CARDS)),
CARD_QUANTUM_LINK(59, "material_card_quantum_link", EnumSet.of(AEFeature.ADVANCED_CARDS, AEFeature.QUANTUM_LINKING_CARD)),
CARD_MAGNET(60, "material_card_magnet", EnumSet.of(AEFeature.BASIC_CARDS));
CARD_MAGNET(60, "material_card_magnet", EnumSet.of(AEFeature.BASIC_CARDS)),
CARD_STICKY(61, "material_card_sticky", EnumSet.of(AEFeature.BASIC_CARDS)),
;
private final Set<AEFeature> features;
+3
View File
@@ -221,6 +221,9 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
// new craftables!
for (final ICraftingPatternDetails details : this.craftingMethods.keySet()) {
for (IAEItemStack out : details.getOutputs()) {
if (out == null) {
continue;
}
out = out.copy();
out.reset();
out.setCraftable(true);
@@ -41,12 +41,12 @@ import appeng.api.util.WorldCoord;
import appeng.container.ContainerNull;
import appeng.core.AEConfig;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.core.features.AEFeature;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketCraftingToast;
import appeng.crafting.*;
import appeng.helpers.PatternHelper;
import appeng.helpers.PlayerHelper;
import appeng.me.cache.CraftingGridCache;
import appeng.me.cluster.IAECluster;
import appeng.me.helpers.MachineSource;
@@ -57,6 +57,7 @@ import appeng.util.Platform;
import appeng.util.item.AEItemStack;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
@@ -395,10 +396,10 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
if (this.finalOutput == null) return;
if (!AEConfig.instance().isFeatureEnabled(AEFeature.CRAFTING_TOASTS)) return;
var player = PlayerHelper.getPlayerByUUID(this.requestingPlayerUUID);
if (player != null) {
var player = AppEng.proxy.getPlayerByUUID(this.requestingPlayerUUID);
if (player instanceof EntityPlayerMP playerMP) {
try {
NetworkHandler.instance().sendTo(new PacketCraftingToast(this.finalOutput, cancelled), player);
NetworkHandler.instance().sendTo(new PacketCraftingToast(this.finalOutput, cancelled), playerMP);
} catch (IOException ignored) {}
}
}
@@ -160,4 +160,8 @@ public class MEMonitorHandler<T extends IAEStack<T>> implements IMEMonitor<T> {
return this.getHandler().validForPass(i);
}
@Override
public boolean isSticky() {
return this.internalHandler.isSticky();
}
}
@@ -56,6 +56,7 @@ public class BasicCellInventoryHandler<T extends IAEStack<T>> extends MEInventor
boolean hasInverter = false;
boolean hasFuzzy = false;
boolean hasSticky = false;
for (int x = 0; x < upgrades.getSlots(); x++) {
final ItemStack is = upgrades.getStackInSlot(x);
@@ -69,6 +70,9 @@ public class BasicCellInventoryHandler<T extends IAEStack<T>> extends MEInventor
case INVERTER:
hasInverter = true;
break;
case STICKY:
hasSticky = true;
break;
default:
}
}
@@ -87,6 +91,10 @@ public class BasicCellInventoryHandler<T extends IAEStack<T>> extends MEInventor
this.setWhitelist(hasInverter ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST);
if (hasSticky) {
setSticky(true);
}
if (!priorityList.isEmpty()) {
if (hasFuzzy) {
this.setPartitionList(new FuzzyPriorityList<>(priorityList, fzMode));
@@ -40,7 +40,6 @@ public class DriveWatcher<T extends IAEStack<T>> extends MEInventoryHandler<T> {
private final ICellHandler handler;
private final TileDrive drive;
private final IActionSource source;
public DriveWatcher(final ICellInventoryHandler<T> i, final ItemStack is, final ICellHandler han, final TileDrive drive) {
super(i, i.getChannel());
this.is = is;
@@ -100,4 +99,13 @@ public class DriveWatcher<T extends IAEStack<T>> extends MEInventoryHandler<T> {
return extractable;
}
@Override
public boolean isSticky() {
if (this.getInternal() instanceof ICellInventoryHandler<?> cellInventoryHandler) {
return cellInventoryHandler.isSticky();
}
return super.isSticky();
}
}
@@ -22,6 +22,7 @@ package appeng.me.storage;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable;
import appeng.api.config.IncludeExclude;
import appeng.api.config.StorageFilter;
import appeng.api.networking.security.IActionSource;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEInventoryHandler;
@@ -38,11 +39,14 @@ public class MEInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHa
private int myPriority;
private IncludeExclude myWhitelist;
private AccessRestriction myAccess;
private StorageFilter storageFilter;
private IPartitionList<T> myPartitionList;
private AccessRestriction cachedAccessRestriction;
private boolean hasReadAccess;
private boolean hasWriteAccess;
private boolean isSticky;
private boolean gettingAvailableContent;
public MEInventoryHandler(final IMEInventory<T> i, final IStorageChannel<T> channel) {
if (i instanceof IMEInventoryHandler) {
@@ -76,7 +80,7 @@ public class MEInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHa
this.hasWriteAccess = this.cachedAccessRestriction.hasPermission(AccessRestriction.WRITE);
}
IPartitionList<T> getPartitionList() {
public IPartitionList<T> getPartitionList() {
return this.myPartitionList;
}
@@ -95,7 +99,7 @@ public class MEInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHa
@Override
public T extractItems(final T request, final Actionable type, final IActionSource src) {
if (!this.hasReadAccess) {
if (!this.canExtract(request)) {
return null;
}
@@ -104,11 +108,27 @@ public class MEInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHa
@Override
public IItemList<T> getAvailableItems(final IItemList<T> out) {
if (!this.hasReadAccess) {
if (this.gettingAvailableContent || !this.hasReadAccess) {
return out;
}
return this.internal.getAvailableItems(out);
this.gettingAvailableContent = true;
try {
if (this.storageFilter == StorageFilter.EXTRACTABLE_ONLY) {
var stackList = this.internal.getAvailableItems(this.getChannel().createList());
for (final T t : stackList) {
if (this.shouldItemBeAvailable(t)) {
out.add(t);
}
}
} else {
return this.internal.getAvailableItems(out);
}
} finally {
this.gettingAvailableContent = false;
}
return out;
}
@Override
@@ -135,13 +155,11 @@ public class MEInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHa
return false;
}
if (this.myWhitelist == IncludeExclude.BLACKLIST && this.myPartitionList.isListed(input)) {
if (!this.passesBlackOrWhitelist(input)) {
return false;
}
if (this.myPartitionList.isEmpty() || this.myWhitelist == IncludeExclude.BLACKLIST) {
return this.internal.canAccept(input);
}
return this.myPartitionList.isListed(input) && this.internal.canAccept(input);
return this.internal.canAccept(input);
}
@Override
@@ -166,4 +184,40 @@ public class MEInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHa
public IMEInventory<T> getInternal() {
return this.internal;
}
@Override
public boolean isSticky() {
return isSticky;
}
public void setSticky(boolean isSticky) {
this.isSticky = isSticky;
}
protected boolean canExtract(T request) {
return this.hasReadAccess;
}
private boolean shouldItemBeAvailable(T t) {
return this.hasReadAccess && this.passesBlackOrWhitelist(t);
}
public boolean passesBlackOrWhitelist(T input) {
if (this.myPartitionList.isEmpty()) {
return true;
}
return switch (this.myWhitelist) {
case WHITELIST -> this.myPartitionList.isListed(input);
case BLACKLIST -> !this.myPartitionList.isListed(input);
};
}
public StorageFilter getStorageFilter() {
return storageFilter;
}
public void setStorageFilter(StorageFilter storageFilter) {
this.storageFilter = storageFilter;
}
}
@@ -31,6 +31,7 @@ import appeng.api.storage.IStorageChannel;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList;
import appeng.me.cache.SecurityCache;
import net.minecraft.network.Packet;
import java.util.*;
@@ -45,19 +46,24 @@ public class NetworkInventoryHandler<T extends IAEStack<T>> implements IMEInvent
private final IStorageChannel<T> myChannel;
private final SecurityCache security;
private final NavigableMap<Integer, List<IMEInventoryHandler<T>>> priorityInventory;
private final NavigableMap<Integer, List<IMEInventoryHandler<T>>> stickyPriorityInventory;
private int myPass = 0;
public NetworkInventoryHandler(final IStorageChannel<T> chan, final SecurityCache security) {
this.myChannel = chan;
this.security = security;
this.priorityInventory = new TreeMap<>(PRIORITY_SORTER);
this.stickyPriorityInventory = new TreeMap<>(PRIORITY_SORTER);
}
public void addNewStorage(final IMEInventoryHandler<T> h) {
final int priority = h.getPriority();
List<IMEInventoryHandler<T>> list = this.priorityInventory.get(priority);
if (list == null) {
this.priorityInventory.put(priority, list = new ArrayList<>());
final List<IMEInventoryHandler<T>> list;
if (h.isSticky()) {
list = this.stickyPriorityInventory.computeIfAbsent(priority, $ -> new ArrayList<>());
} else {
list = this.priorityInventory.computeIfAbsent(priority, $ -> new ArrayList<>());
}
list.add(h);
@@ -74,6 +80,25 @@ public class NetworkInventoryHandler<T extends IAEStack<T>> implements IMEInvent
return input;
}
boolean stickyInventoryFound = false;
// For this pass we do return input if the item is able to go into a sticky inventory. We NEVER want to try and
// insert the item into a non-sticky inventory if it could already go into a sticky inventory.
for (final List<IMEInventoryHandler<T>> stickyInvList : this.stickyPriorityInventory.values()) {
Iterator<IMEInventoryHandler<T>> ii = stickyInvList.iterator();
while (ii.hasNext() && input != null) {
final IMEInventoryHandler<T> inv = ii.next();
if (inv.validForPass(1) && inv.canAccept(input) && (inv.isPrioritized(input) || inv.extractItems(input, Actionable.SIMULATE, src) != null)) {
input = inv.injectItems(input, type, src);
stickyInventoryFound = true;
}
}
}
if (stickyInventoryFound) {
this.surface(this, type);
return input;
}
for (final List<IMEInventoryHandler<T>> invList : this.priorityInventory.values()) {
Iterator<IMEInventoryHandler<T>> ii = invList.iterator();
while (ii.hasNext() && input != null) {
@@ -186,6 +211,16 @@ public class NetworkInventoryHandler<T extends IAEStack<T>> implements IMEInvent
}
}
for (List<IMEInventoryHandler<T>> invList : this.stickyPriorityInventory.descendingMap().values()) {
final Iterator<IMEInventoryHandler<T>> jj = invList.iterator();
while (jj.hasNext() && output.getStackSize() < req) {
final IMEInventoryHandler<T> inv = jj.next();
request.setStackSize(req - output.getStackSize());
output.add(inv.extractItems(request, mode, src));
}
}
this.surface(this, mode);
if (output.getStackSize() <= 0) {
@@ -201,15 +236,21 @@ public class NetworkInventoryHandler<T extends IAEStack<T>> implements IMEInvent
return out;
}
// for (Entry<Integer, IMEInventoryHandler<T>> h : priorityInventory.entries())
for (final List<IMEInventoryHandler<T>> i : this.priorityInventory.values()) {
out = iterateInventories(out, priorityInventory);
out = iterateInventories(out, stickyPriorityInventory);
this.surface(this, Actionable.SIMULATE);
return out;
}
private IItemList<T> iterateInventories(IItemList<T> out, final NavigableMap<Integer, List<IMEInventoryHandler<T>>> map) {
for (final List<IMEInventoryHandler<T>> i : map.values()) {
for (final IMEInventoryHandler<T> j : i) {
out = j.getAvailableItems(out);
}
}
this.surface(this, Actionable.SIMULATE);
return out;
}
@@ -48,6 +48,7 @@ public abstract class UpgradeInventory extends AppEngInternalInventory implement
private int patternExpansionUpgrades = 0;
private int magnetUpgrades = 0;
private int quantumUpgrades = 0;
private int stickyUpgrades = 0;
public UpgradeInventory(final IAEAppEngInventory parent, final int s) {
super(null, s, 1);
@@ -85,6 +86,8 @@ public abstract class UpgradeInventory extends AppEngInternalInventory implement
return this.magnetUpgrades;
case QUANTUM_LINK:
return this.quantumUpgrades;
case STICKY:
return this.stickyUpgrades;
default:
return 0;
}
@@ -94,7 +97,7 @@ public abstract class UpgradeInventory extends AppEngInternalInventory implement
private void updateUpgradeInfo() {
this.cached = true;
this.patternExpansionUpgrades = this.inverterUpgrades = this.capacityUpgrades = this.redstoneUpgrades = this.speedUpgrades = this.fuzzyUpgrades = this.craftingUpgrades = magnetUpgrades = quantumUpgrades = 0;
this.patternExpansionUpgrades = this.inverterUpgrades = this.capacityUpgrades = this.redstoneUpgrades = this.speedUpgrades = this.fuzzyUpgrades = this.craftingUpgrades = magnetUpgrades = quantumUpgrades = stickyUpgrades = 0;
for (final ItemStack is : this) {
if (is == null || is.getItem() == Items.AIR || !(is.getItem() instanceof IUpgradeModule)) {
@@ -129,6 +132,10 @@ public abstract class UpgradeInventory extends AppEngInternalInventory implement
break;
case QUANTUM_LINK:
this.quantumUpgrades++;
break;
case STICKY:
this.stickyUpgrades++;
break;
default:
break;
}
@@ -143,6 +150,7 @@ public abstract class UpgradeInventory extends AppEngInternalInventory implement
this.patternExpansionUpgrades = Math.min(this.patternExpansionUpgrades, this.getMaxInstalled(Upgrades.PATTERN_EXPANSION));
this.magnetUpgrades = Math.min(this.magnetUpgrades, this.getMaxInstalled(Upgrades.MAGNET));
this.quantumUpgrades = Math.min(this.quantumUpgrades, this.getMaxInstalled(Upgrades.QUANTUM_LINK));
this.stickyUpgrades = Math.min(this.stickyUpgrades, this.getMaxInstalled(Upgrades.STICKY));
}
@Override
@@ -111,8 +111,8 @@ public class PartOreDicStorageBus extends PartStorageBus {
this.handler.setBaseAccess((AccessRestriction) this.getConfigManager().getSetting(Settings.ACCESS));
this.handler.setWhitelist(this.getInstalledUpgrades(Upgrades.INVERTER) > 0 ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST);
this.handler.setPriority(this.priority);
this.handler.setPartitionList(this.getPriorityList());
this.handler.setStorageFilter((StorageFilter) this.getConfigManager().getSetting(Settings.STORAGE_FILTER));
if (inv instanceof IBaseMonitor) {
if (((AccessRestriction) ((ConfigManager) this.getConfigManager()).getSetting(Settings.ACCESS)).hasPermission(AccessRestriction.READ)) {
@@ -165,9 +165,7 @@ public class PartOreDicStorageBus extends PartStorageBus {
this.oreExp = oreMatch;
this.priorityList = new OreDictPriorityList<>(OreHelper.INSTANCE.getMatchingOre(oreExp), oreExp);
if (this.handler != null) {
handler.setPartitionList(this.priorityList);
}
this.resetCache(true);
this.getHost().markForSave();
}
}
@@ -80,6 +80,7 @@ import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -113,6 +114,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
this.getConfigManager().registerSetting(Settings.ACCESS, AccessRestriction.READ_WRITE);
this.getConfigManager().registerSetting(Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL);
this.getConfigManager().registerSetting(Settings.STORAGE_FILTER, StorageFilter.EXTRACTABLE_ONLY);
this.getConfigManager().registerSetting(Settings.STICKY_MODE, YesNo.NO);
this.mySrc = new MachineSource(this);
}
@@ -194,7 +196,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
return super.getInventoryByName(name);
}
private void resetCache(final boolean fullReset) {
protected void resetCache(final boolean fullReset) {
if (this.getHost() == null || this.getHost().getTile() == null || this.getHost().getTile().getWorld() == null || this.getHost().getTile().getWorld().isRemote) {
return;
}
@@ -220,11 +222,13 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
@Override
public void postChange(final IBaseMonitor<IAEItemStack> monitor, final Iterable<IAEItemStack> change, final IActionSource source) {
if (this.getProxy().isActive()) {
var filteredChanges = this.filterChanges(change);
AccessRestriction currentAccess = (AccessRestriction) ((ConfigManager) this.getConfigManager()).getSetting(Settings.ACCESS);
if (readOncePass) {
readOncePass = false;
try {
this.getProxy().getStorage().postAlterationOfStoredItems(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class), change, mySrc);
this.getProxy().getStorage().postAlterationOfStoredItems(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class), filteredChanges, mySrc);
} catch (final GridAccessException e) {
// :(
}
@@ -234,7 +238,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
return;
}
try {
this.getProxy().getStorage().postAlterationOfStoredItems(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class), change, source);
this.getProxy().getStorage().postAlterationOfStoredItems(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class), filteredChanges, source);
} catch (final GridAccessException e) {
// :(
}
@@ -315,7 +319,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
return TickRateModulation.SLEEP;
}
private void resetCache() {
protected void resetCache() {
final boolean fullReset = this.resetCacheLogic == 2;
this.resetCacheLogic = 0;
@@ -456,6 +460,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
this.handler.setBaseAccess((AccessRestriction) this.getConfigManager().getSetting(Settings.ACCESS));
this.handler.setWhitelist(this.getInstalledUpgrades(Upgrades.INVERTER) > 0 ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST);
this.handler.setPriority(this.priority);
this.handler.setStorageFilter((StorageFilter) this.getConfigManager().getSetting(Settings.STORAGE_FILTER));
final IItemList<IAEItemStack> priorityList = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class).createList();
@@ -467,6 +472,10 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
}
}
if (this.getInstalledUpgrades(Upgrades.STICKY) > 0) {
this.handler.setSticky(true);
}
if (this.getInstalledUpgrades(Upgrades.FUZZY) > 0) {
this.handler.setPartitionList(new FuzzyPriorityList<>(priorityList, (FuzzyMode) this.getConfigManager().getSetting(Settings.FUZZY_MODE)));
} else {
@@ -566,4 +575,26 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
public GuiBridge getGuiBridge() {
return GuiBridge.GUI_STORAGEBUS;
}
// TODO: 1/28/2024 Unify both methods.
/**
* Filters the changes to only include items that pass the storage filter.
* Optimally, this should be handled by the underlying monitor.
*
* @see appeng.fluids.parts.PartFluidStorageBus#filterChanges
*/
protected Iterable<IAEItemStack> filterChanges(Iterable<IAEItemStack> change) {
var storageFilter = this.getConfigManager().getSetting(Settings.STORAGE_FILTER);
if (storageFilter == StorageFilter.EXTRACTABLE_ONLY && handler != null) {
var filteredList = new ArrayList<IAEItemStack>();
for (final IAEItemStack stack : change) {
if (this.handler.passesBlackOrWhitelist(stack)) {
filteredList.add(stack);
}
}
return filteredList;
}
return change;
}
}
@@ -42,6 +42,7 @@ import net.minecraftforge.fml.common.FMLCommonHandler;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;
public class ServerHelper extends CommonHelper {
@@ -167,4 +168,17 @@ public class ServerHelper extends CommonHelper {
public boolean isActionKey(ActionKey key, int pressedKeyCode) {
return false;
}
@Override
public EntityPlayer getPlayerByUUID(UUID uuid) {
if (!Platform.isClient()) {
final MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
if (server != null) {
return server.getPlayerList().getPlayerByUUID(uuid);
}
}
return null;
}
}
@@ -178,6 +178,12 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
}
}
@Override
public void gridChanged() {
super.gridChanged();
updateTask();
}
public void updateRedstoneState() {
final YesNo currentState = this.world.getRedstonePowerFromNeighbors(this.pos) != 0 ? YesNo.YES : YesNo.NO;
if (this.lastRedstoneState != currentState) {
@@ -253,6 +253,7 @@ gui.appliedenergistics2.Renamer=Custom Name: (Enter to set)
gui.appliedenergistics2.Nothing=Nothing
gui.appliedenergistics2.CraftingToastDone=Crafting Done!
gui.appliedenergistics2.CraftingToastCancelled=Crafting Cancelled!
gui.appliedenergistics2.Sticky=Sticky
// GUI Tooltips
gui.tooltips.appliedenergistics2.Stash=Store Items
@@ -524,6 +525,7 @@ item.appliedenergistics2.material.silicon_print.name=Printed Silicon
item.appliedenergistics2.material.name_press.name=Inscriber Name Press
item.appliedenergistics2.material.sky_dust.name=Sky Stone Dust
item.appliedenergistics2.material.card_crafting.name=Crafting Card
item.appliedenergistics2.material.card_sticky.name=Sticky Card
item.appliedenergistics2.multi_part.annihilation_plane.name=ME Annihilation Plane
item.appliedenergistics2.multi_part.fluid_annihilation_plane.name=ME Fluid Annihilation Plane
@@ -253,6 +253,7 @@ gui.appliedenergistics2.Renamer=自定义名称(按下Enter以设定)
gui.appliedenergistics2.Nothing=无
gui.appliedenergistics2.CraftingToastDone=合成已完成!
gui.appliedenergistics2.CraftingToastCancelled=合成已取消!
gui.appliedenergistics2.Sticky=粘滞
// GUI Tooltips
gui.tooltips.appliedenergistics2.Stash=存储物品
@@ -524,6 +525,7 @@ item.appliedenergistics2.material.silicon_print.name=硅板
item.appliedenergistics2.material.name_press.name=名称压印模板
item.appliedenergistics2.material.sky_dust.name=陨石粉
item.appliedenergistics2.material.card_crafting.name=合成卡
item.appliedenergistics2.material.card_sticky.name=粘滞卡
item.appliedenergistics2.multi_part.annihilation_plane.name=ME破坏面板
item.appliedenergistics2.multi_part.fluid_annihilation_plane.name=ME流体破坏面板
@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "appliedenergistics2:items/material_card_sticky"
}
}
@@ -0,0 +1,31 @@
{
"conditions": [
{
"type": "forge:and",
"values": [
{
"type": "appliedenergistics2:material_exists",
"material": "material.card_sticky"
},
{
"type": "appliedenergistics2:material_exists",
"material": "material.basic_card"
}
]
}
],
"result": {
"type": "appliedenergistics2:part",
"part": "material.card_sticky"
},
"type": "appliedenergistics2:part_shapeless",
"ingredients": [
{
"item": "minecraft:slime_ball"
},
{
"type": "appliedenergistics2:part",
"part": "material.basic_card"
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B