Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 20a1fec6fb | |||
| 0fffc829ab | |||
| 88635d9a8d | |||
| 0fd0ed1b1c | |||
| 87f884228e | |||
| 3495d3dfd4 | |||
| 0acb03b83d |
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -387,6 +387,19 @@ 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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -537,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) {
|
||||
var filteredList = new ArrayList<IAEFluidStack>();
|
||||
for (final IAEFluidStack stack : change) {
|
||||
if (this.handler.passesBlackOrWhitelist(stack)) {
|
||||
filteredList.add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
return filteredList;
|
||||
}
|
||||
return change;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,12 +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) {
|
||||
@@ -77,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;
|
||||
}
|
||||
|
||||
@@ -96,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;
|
||||
}
|
||||
|
||||
@@ -105,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
|
||||
@@ -136,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
|
||||
@@ -176,4 +193,31 @@ public class MEInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHa
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -195,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;
|
||||
}
|
||||
@@ -221,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) {
|
||||
// :(
|
||||
}
|
||||
@@ -235,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) {
|
||||
// :(
|
||||
}
|
||||
@@ -316,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;
|
||||
|
||||
@@ -457,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();
|
||||
|
||||
@@ -571,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) {
|
||||
var filteredList = new ArrayList<IAEItemStack>();
|
||||
for (final IAEItemStack stack : change) {
|
||||
if (this.handler.passesBlackOrWhitelist(stack)) {
|
||||
filteredList.add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
return filteredList;
|
||||
}
|
||||
return change;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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流体破坏面板
|
||||
|
||||
Reference in New Issue
Block a user