Merge branch 'cit' into AE2-Omnifactory

This commit is contained in:
PrototypeTrousers
2022-08-12 23:01:54 -03:00
22 changed files with 1278 additions and 36 deletions
+12 -5
View File
@@ -474,7 +474,15 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
{
if( slot.getStack().isEmpty() )
{
InventoryAction action = InventoryAction.SPLIT_OR_PLACE_SINGLE;
InventoryAction action;
if( slot.getSlotStackLimit() == 1 )
{
action = InventoryAction.SPLIT_OR_PLACE_SINGLE;
}
else
{
action = InventoryAction.PICKUP_OR_SET_DOWN;
}
final PacketInventoryAction p = new PacketInventoryAction( action, slot.getSlotIndex(), ( (SlotDisconnected) slot ).getSlot().getId() );
NetworkHandler.instance().sendToServer( p );
}
@@ -640,14 +648,13 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
switch ( clickType )
{
case PICKUP: // pickup / set-down.
if( slot.getStack().isEmpty() && !player.inventory.getItemStack().isEmpty() )
if( mouseButton == 1 )
{
action = InventoryAction.SPLIT_OR_PLACE_SINGLE;
}
if( !slot.getStack().isEmpty() && player.inventory.getItemStack().getCount() <= 1 )
else
{
action = InventoryAction.PICKUP_OR_SET_DOWN;
this.haltDragging = true;
}
break;
case QUICK_MOVE:
@@ -861,7 +868,7 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
}
}
private void mouseWheelEvent( final int x, final int y, final int wheel )
protected void mouseWheelEvent( final int x, final int y, final int wheel )
{
final Slot slot = this.getSlot( x, y );
if( slot instanceof SlotME )
@@ -0,0 +1,575 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.implementations;
import java.awt.*;
import java.io.IOException;
import java.util.*;
import java.util.List;
import appeng.api.config.ActionItems;
import appeng.api.config.Settings;
import appeng.client.gui.widgets.GuiImgButton;
import appeng.container.implementations.ContainerInterfaceConfigurationTerminal;
import appeng.container.interfaces.IJEIGhostIngredients;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketInventoryAction;
import appeng.helpers.DualityInterface;
import appeng.helpers.InventoryAction;
import appeng.parts.reporting.PartInterfaceConfigurationTerminal;
import appeng.util.BlockPosUtils;
import appeng.util.item.AEItemStack;
import com.google.common.collect.HashMultimap;
import mezz.jei.api.gui.IGhostIngredientHandler;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import appeng.api.AEApi;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.client.gui.AEBaseGui;
import appeng.client.gui.widgets.GuiScrollbar;
import appeng.client.gui.widgets.MEGuiTextField;
import appeng.client.me.ClientDCInternalInv;
import appeng.client.me.SlotDisconnected;
import appeng.core.localization.GuiText;
import appeng.util.Platform;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.common.DimensionManager;
import org.lwjgl.input.Mouse;
import static appeng.client.render.BlockPosHighlighter.hilightBlock;
public class GuiInterfaceConfigurationTerminal extends AEBaseGui implements IJEIGhostIngredients
{
private static final int LINES_ON_PAGE = 6;
// TODO: copied from GuiMEMonitorable. It looks not changed, maybe unneeded?
private final int offsetX = 21;
private final HashMap<Long, ClientDCInternalInv> byId = new HashMap<>();
private final HashMultimap<String, ClientDCInternalInv> byName = HashMultimap.create();
private final HashMap<ClientDCInternalInv, BlockPos> blockPosHashMap = new HashMap<>();
private final HashMap<GuiButton, ClientDCInternalInv> guiButtonHashMap = new HashMap<>();
private final Map<ClientDCInternalInv, Integer> numUpgradesMap = new HashMap<>();
private final ArrayList<String> names = new ArrayList<>();
private final ArrayList<Object> lines = new ArrayList<>();
private final Set<Object> matchedStacks = new HashSet<>();
private final Map<String, Set<Object>> cachedSearches = new WeakHashMap<>();
private boolean refreshList = false;
private MEGuiTextField searchFieldInputs;
private PartInterfaceConfigurationTerminal partInterfaceTerminal;
private HashMap<ClientDCInternalInv, Integer> dimHashMap = new HashMap<>();
public Map<IGhostIngredientHandler.Target<?>, Object> mapTargetSlot = new HashMap<>();
public GuiInterfaceConfigurationTerminal( final InventoryPlayer inventoryPlayer, final PartInterfaceConfigurationTerminal te )
{
super( new ContainerInterfaceConfigurationTerminal( inventoryPlayer, te ) );
this.partInterfaceTerminal = te;
final GuiScrollbar scrollbar = new GuiScrollbar();
this.setScrollBar( scrollbar );
this.xSize = 208;
this.ySize = 235;
}
@Override
public void initGui()
{
super.initGui();
this.getScrollBar().setLeft( 189 );
this.getScrollBar().setHeight( 106 );
this.getScrollBar().setTop( 31 );
this.searchFieldInputs = new MEGuiTextField( this.fontRenderer, this.guiLeft + Math.max( 32, this.offsetX ), this.guiTop + 17, 65, 12 );
this.searchFieldInputs.setEnableBackgroundDrawing( false );
this.searchFieldInputs.setMaxStringLength( 25 );
this.searchFieldInputs.setTextColor( 0xFFFFFF );
this.searchFieldInputs.setVisible( true );
this.searchFieldInputs.setFocused( false );
this.searchFieldInputs.setText( partInterfaceTerminal.in );
}
@Override
public void onGuiClosed()
{
partInterfaceTerminal.saveSearchStrings( this.searchFieldInputs.getText().toLowerCase() );
super.onGuiClosed();
}
@Override
public void drawFG( final int offsetX, final int offsetY, final int mouseX, final int mouseY )
{
this.buttonList.clear();
this.fontRenderer.drawString( this.getGuiDisplayName( GuiText.InterfaceConfigurationTerminal.getLocal() ), 8, 6, 4210752 );
this.fontRenderer.drawString( GuiText.inventory.getLocal(), this.offsetX + 2, this.ySize - 96 + 3, 4210752 );
final int currentScroll = this.getScrollBar().getCurrentScroll();
this.inventorySlots.inventorySlots.removeIf( slot -> slot instanceof SlotDisconnected );
int offset = 30;
int linesDraw = 0;
for( int x = 0; x < LINES_ON_PAGE && linesDraw < LINES_ON_PAGE && currentScroll + x < this.lines.size(); x++ )
{
final Object lineObj = this.lines.get( currentScroll + x );
if( lineObj instanceof ClientDCInternalInv )
{
final ClientDCInternalInv inv = (ClientDCInternalInv) lineObj;
GuiButton guiButton = new GuiImgButton( guiLeft + 4, guiTop + offset, Settings.ACTIONS, ActionItems.HIGHLIGHT_INTERFACE );
guiButtonHashMap.put( guiButton, inv );
this.buttonList.add( guiButton );
int extraLines = numUpgradesMap.get( inv );
for( int row = 0; row < 1 + extraLines && linesDraw < LINES_ON_PAGE; ++row )
{
for( int z = 0; z < 9; z++ )
{
this.inventorySlots.inventorySlots.add( new SlotDisconnected( inv, z + ( row * 9 ), ( z * 18 + 22 ), offset ) );
if( this.matchedStacks.contains( inv.getInventory().getStackInSlot( z + ( row * 9 ) ) ) )
{
drawRect( z * 18 + 22, offset, z * 18 + 22 + 16, offset + 16, 0x2A00FF00 );
}
}
linesDraw++;
offset += 18;
}
}
else if( lineObj instanceof String )
{
String name = (String) lineObj;
final int rows = this.byName.get( name ).size();
if( rows > 1 )
{
name = name + " (" + rows + ')';
}
while ( name.length() > 2 && this.fontRenderer.getStringWidth( name ) > 155 )
{
name = name.substring( 0, name.length() - 1 );
}
this.fontRenderer.drawString( name, this.offsetX + 2, 5 + offset, 4210752 );
linesDraw++;
offset += 18;
}
}
if( searchFieldInputs.isMouseIn( mouseX, mouseY ) )
{
drawTooltip( Mouse.getEventX() * this.width / this.mc.displayWidth - offsetX, mouseY - guiTop, "Inputs OR names" );
}
}
@Override
protected void mouseClicked( final int xCoord, final int yCoord, final int btn ) throws IOException
{
this.searchFieldInputs.mouseClicked( xCoord, yCoord, btn );
if( btn == 1 && this.searchFieldInputs.isMouseIn( xCoord, yCoord ) )
{
this.searchFieldInputs.setText( "" );
this.refreshList();
}
super.mouseClicked( xCoord, yCoord, btn );
}
@Override
protected void actionPerformed( final GuiButton btn ) throws IOException
{
if( guiButtonHashMap.containsKey( btn ) )
{
BlockPos blockPos = blockPosHashMap.get( guiButtonHashMap.get( this.selectedButton ) );
BlockPos blockPos2 = mc.player.getPosition();
int playerDim = mc.world.provider.getDimension();
int interfaceDim = dimHashMap.get( guiButtonHashMap.get( this.selectedButton ) );
if( playerDim != interfaceDim )
{
try
{
mc.player.sendStatusMessage( new TextComponentString( "Interface located at dimension: " + interfaceDim + " [" + DimensionManager.getWorld( interfaceDim ).provider.getDimensionType().getName() + "] and cant be highlighted" ), false );
}
catch( Exception e )
{
mc.player.sendStatusMessage( new TextComponentString( "Interface is located in another dimension and cannot be highlighted" ), false );
}
}
else
{
hilightBlock( blockPos, System.currentTimeMillis() + 500 * BlockPosUtils.getDistance( blockPos, blockPos2 ), playerDim );
mc.player.sendStatusMessage( new TextComponentString( "The interface is now highlighted at " + "X: " + blockPos.getX() + " Y: " + blockPos.getY() + " Z: " + blockPos.getZ() ), false );
}
mc.player.closeScreen();
}
}
@Override
protected void mouseWheelEvent( final int x, final int y, final int wheel )
{
final Slot slot = this.getSlot( x, y );
if( slot instanceof SlotDisconnected )
{
final ItemStack stack = slot.getStack();
if( stack != ItemStack.EMPTY )
{
InventoryAction direction = wheel > 0 ? InventoryAction.PLACE_SINGLE : InventoryAction.PICKUP_SINGLE;
final PacketInventoryAction p = new PacketInventoryAction( direction, slot.getSlotIndex(), ( (SlotDisconnected) slot ).getSlot().getId() );
NetworkHandler.instance().sendToServer( p );
}
}
else
{
super.mouseWheelEvent( x, y, wheel );
}
}
@Override
public void drawBG( final int offsetX, final int offsetY, final int mouseX, final int mouseY )
{
this.bindTexture( "guis/interfaceconfigurationterminal.png" );
this.drawTexturedModalRect( offsetX, offsetY, 0, 0, this.xSize, this.ySize );
int offset = 29;
final int ex = this.getScrollBar().getCurrentScroll();
int linesDraw = 0;
for( int x = 0; x < LINES_ON_PAGE && linesDraw < LINES_ON_PAGE && ex + x < this.lines.size(); x++ )
{
final Object lineObj = this.lines.get( ex + x );
if( lineObj instanceof ClientDCInternalInv )
{
GlStateManager.color( 1, 1, 1, 1 );
final int width = 9 * 18;
int extraLines = numUpgradesMap.get( lineObj );
for( int row = 0; row < 1 + extraLines && linesDraw < LINES_ON_PAGE; ++row )
{
this.drawTexturedModalRect( offsetX + 20, offsetY + offset, 20, 170, width, 18 );
offset += 18;
linesDraw++;
}
}
else
{
offset += 18;
linesDraw++;
}
}
if( this.searchFieldInputs != null )
{
this.searchFieldInputs.drawTextBox();
}
}
@Override
protected void keyTyped( final char character, final int key ) throws IOException
{
if( !this.checkHotbarKeys( key ) )
{
if( character == ' ' && this.searchFieldInputs.getText().isEmpty() && this.searchFieldInputs.isFocused() )
{
return;
}
if( this.searchFieldInputs.textboxKeyTyped( character, key ) )
{
this.refreshList();
}
else
{
super.keyTyped( character, key );
}
}
}
public void postUpdate( final NBTTagCompound in )
{
if( in.getBoolean( "clear" ) )
{
this.byId.clear();
this.refreshList = true;
}
for( final Object oKey : in.getKeySet() )
{
final String key = (String) oKey;
if( key.startsWith( "=" ) )
{
try
{
final long id = Long.parseLong( key.substring( 1 ), Character.MAX_RADIX );
final NBTTagCompound invData = in.getCompoundTag( key );
final ClientDCInternalInv current = this.getById( id, invData.getLong( "sortBy" ), invData.getString( "un" ) );
blockPosHashMap.put( current, NBTUtil.getPosFromTag( invData.getCompoundTag( "pos" ) ) );
dimHashMap.put( current, invData.getInteger( "dim" ) );
numUpgradesMap.put( current, invData.getInteger( "numUpgrades" ) );
for( int x = 0; x < current.getInventory().getSlots(); x++ )
{
final String which = Integer.toString( x );
if( invData.hasKey( which ) )
{
current.getInventory().setStackInSlot( x, new ItemStack( invData.getCompoundTag( which ) ) );
}
}
}
catch( final NumberFormatException ignored )
{
}
}
}
if( this.refreshList )
{
this.refreshList = false;
// invalid caches on refresh
this.cachedSearches.clear();
this.refreshList();
}
}
/**
* Rebuilds the list of interfaces.
* <p>
* Respects a search term if present (ignores case) and adding only matching patterns.
*/
private void refreshList()
{
this.byName.clear();
this.buttonList.clear();
this.matchedStacks.clear();
final String searchFieldInputs = this.searchFieldInputs.getText().toLowerCase();
final Set<Object> cachedSearch = this.getCacheForSearchTerm( searchFieldInputs );
final boolean rebuild = cachedSearch.isEmpty();
for( final ClientDCInternalInv entry : this.byId.values() )
{
// ignore inventory if not doing a full rebuild and cache already marks it as miss.
if( !rebuild && !cachedSearch.contains( entry ) )
{
continue;
}
// Shortcut to skip any filter if search term is ""/empty
boolean found = searchFieldInputs.isEmpty();
// Search if the current inventory holds a pattern containing the search term.
if( !found )
{
int slot = 0;
for( final ItemStack itemStack : entry.getInventory() )
{
if( slot > 8 + numUpgradesMap.get( entry ) * 9 )
{
break;
}
if( this.itemStackMatchesSearchTerm( itemStack, searchFieldInputs ) )
{
found = true;
matchedStacks.add( itemStack );
}
slot++;
}
}
// if found, filter skipped or machine name matching the search term, add it
if( found || entry.getName().toLowerCase().contains( searchFieldInputs ) )
{
this.byName.put( entry.getName(), entry );
cachedSearch.add( entry );
}
else
{
cachedSearch.remove( entry );
}
}
this.names.clear();
this.names.addAll( this.byName.keySet() );
Collections.sort( this.names );
this.lines.clear();
this.lines.ensureCapacity( this.getMaxRows() );
for( final String n : this.names )
{
this.lines.add( n );
final ArrayList<ClientDCInternalInv> clientInventories = new ArrayList<>();
clientInventories.addAll( this.byName.get( n ) );
Collections.sort( clientInventories );
this.lines.addAll( clientInventories );
}
this.getScrollBar().setRange( 0, this.lines.size() - 1, 1 );
}
private boolean itemStackMatchesSearchTerm( final ItemStack itemStack, final String searchTerm )
{
if( itemStack.isEmpty() )
{
return false;
}
boolean foundMatchingItemStack = false;
final String displayName = Platform
.getItemDisplayName( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( itemStack ) )
.toLowerCase();
for( String term : searchTerm.split( " " ) )
{
if( term.length() > 1 && ( term.startsWith( "-" ) || term.startsWith( "!" ) ) )
{
term = term.substring( 1 );
if( displayName.contains( term ) )
{
return false;
}
}
else if( displayName.contains( term ) )
{
foundMatchingItemStack = true;
}
}
return foundMatchingItemStack;
}
/**
* Tries to retrieve a cache for a with search term as keyword.
* <p>
* If this cache should be empty, it will populate it with an earlier cache if available or at least the cache for
* the empty string.
*
* @param searchTerm the corresponding search
* @return a Set matching a superset of the search term
*/
private Set<Object> getCacheForSearchTerm( final String searchTerm )
{
if( !this.cachedSearches.containsKey( searchTerm ) )
{
this.cachedSearches.put( searchTerm, new HashSet<>() );
}
final Set<Object> cache = this.cachedSearches.get( searchTerm );
if( cache.isEmpty() && searchTerm.length() > 1 )
{
cache.addAll( this.getCacheForSearchTerm( searchTerm.substring( 0, searchTerm.length() - 1 ) ) );
return cache;
}
return cache;
}
/**
* The max amount of unique names and each inv row. Not affected by the filtering.
*
* @return max amount of unique names and each inv row
*/
private int getMaxRows()
{
return this.names.size() + this.byId.size();
}
private ClientDCInternalInv getById( final long id, final long sortBy, final String string )
{
ClientDCInternalInv o = this.byId.get( id );
if( o == null )
{
this.byId.put( id, o = new ClientDCInternalInv( DualityInterface.NUMBER_OF_CONFIG_SLOTS, id, sortBy, string, 64 ) );
this.refreshList = true;
}
return o;
}
@Override
public List<IGhostIngredientHandler.Target<?>> getPhantomTargets( Object ingredient )
{
if( !( ingredient instanceof ItemStack ) )
{
return Collections.emptyList();
}
List<IGhostIngredientHandler.Target<?>> targets = new ArrayList<>();
for( Slot slot : this.inventorySlots.inventorySlots )
{
if( slot instanceof SlotDisconnected )
{
ItemStack itemStack = (ItemStack) ingredient;
IGhostIngredientHandler.Target<Object> target = new IGhostIngredientHandler.Target<Object>()
{
@Override
public Rectangle getArea()
{
return new Rectangle( getGuiLeft() + slot.xPos, getGuiTop() + slot.yPos, 16, 16 );
}
@Override
public void accept( Object ingredient )
{
final PacketInventoryAction p;
try
{
p = new PacketInventoryAction( InventoryAction.PLACE_JEI_GHOST_ITEM, (SlotDisconnected) slot, AEItemStack.fromItemStack( itemStack ) );
NetworkHandler.instance().sendToServer( p );
}
catch( IOException e )
{
e.printStackTrace();
}
}
};
targets.add( target );
mapTargetSlot.putIfAbsent( target, slot );
}
}
return targets;
}
@Override
public Map<IGhostIngredientHandler.Target<?>, Object> getFakeSlotTargetMap()
{
return IJEIGhostIngredients.super.getFakeSlotTargetMap();
}
}
@@ -43,6 +43,14 @@ public class ClientDCInternalInv implements Comparable<ClientDCInternalInv>
this.sortBy = sortBy;
}
public ClientDCInternalInv( final int size, final long id, final long sortBy, final String unlocalizedName, int stackSize )
{
this.inventory = new AppEngInternalInventory( null, size, stackSize );
this.unlocalizedName = unlocalizedName;
this.id = id;
this.sortBy = sortBy;
}
public String getName()
{
final String s = I18n.translateToLocal( this.unlocalizedName + ".name" );
@@ -19,6 +19,7 @@
package appeng.client.me;
import appeng.container.slot.IJEITargetSlot;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
@@ -28,7 +29,7 @@ import appeng.items.misc.ItemEncodedPattern;
import appeng.util.Platform;
public class SlotDisconnected extends AppEngSlot
public class SlotDisconnected extends AppEngSlot implements IJEITargetSlot
{
private final ClientDCInternalInv mySlot;
@@ -0,0 +1,400 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.container.implementations;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import appeng.parts.reporting.PartInterfaceConfigurationTerminal;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.items.IItemHandler;
import appeng.api.config.Settings;
import appeng.api.config.YesNo;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridNode;
import appeng.api.networking.security.IActionHost;
import appeng.container.AEBaseContainer;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketCompressedNBT;
import appeng.helpers.DualityInterface;
import appeng.helpers.IInterfaceHost;
import appeng.helpers.InventoryAction;
import appeng.parts.misc.PartInterface;
import appeng.tile.inventory.AppEngInternalInventory;
import appeng.tile.misc.TileInterface;
import appeng.util.Platform;
import appeng.util.helpers.ItemHandlerUtil;
import appeng.util.inv.WrapperRangeItemHandler;
public final class ContainerInterfaceConfigurationTerminal extends AEBaseContainer
{
/**
* this stuff is all server side..
*/
private static long autoBase = Long.MIN_VALUE;
private final Map<IInterfaceHost, ConfigTracker> diList = new HashMap<>();
private final Map<Long, ConfigTracker> byId = new HashMap<>();
private IGrid grid;
private NBTTagCompound data = new NBTTagCompound();
public ContainerInterfaceConfigurationTerminal( final InventoryPlayer ip, final PartInterfaceConfigurationTerminal anchor )
{
super( ip, anchor );
if( Platform.isServer() )
{
this.grid = anchor.getActionableNode().getGrid();
}
this.bindPlayerInventory( ip, 14, 235 - /* height of player inventory */82 );
}
@Override
public void detectAndSendChanges()
{
if( Platform.isClient() )
{
return;
}
super.detectAndSendChanges();
if( this.grid == null )
{
return;
}
int total = 0;
boolean missing = false;
final IActionHost host = this.getActionHost();
if( host != null )
{
final IGridNode agn = host.getActionableNode();
if( agn != null && agn.isActive() )
{
for( final IGridNode gn : this.grid.getMachines( TileInterface.class ) )
{
if( gn.isActive() )
{
final IInterfaceHost ih = (IInterfaceHost) gn.getMachine();
if( ih.getInterfaceDuality().getConfigManager().getSetting( Settings.INTERFACE_TERMINAL ) == YesNo.NO )
{
continue;
}
final ConfigTracker t = this.diList.get( ih );
if( t == null )
{
missing = true;
}
else
{
final DualityInterface dual = ih.getInterfaceDuality();
if( !t.unlocalizedName.equals( dual.getTermName() ) )
{
missing = true;
}
}
total++;
}
}
for( final IGridNode gn : this.grid.getMachines( PartInterface.class ) )
{
if( gn.isActive() )
{
final IInterfaceHost ih = (IInterfaceHost) gn.getMachine();
if( ih.getInterfaceDuality().getConfigManager().getSetting( Settings.INTERFACE_TERMINAL ) == YesNo.NO )
{
continue;
}
final ConfigTracker t = this.diList.get( ih );
if( t == null )
{
missing = true;
}
else
{
final DualityInterface dual = ih.getInterfaceDuality();
if( !t.unlocalizedName.equals( dual.getTermName() ) )
{
missing = true;
}
}
total++;
}
}
}
}
if( total != this.diList.size() || missing )
{
this.regenList( this.data );
}
else
{
for( final Entry<IInterfaceHost, ConfigTracker> en : this.diList.entrySet() )
{
final ConfigTracker inv = en.getValue();
for( int x = 0; x < inv.server.getSlots(); x++ )
{
if( this.isDifferent( inv.server.getStackInSlot( x ), inv.client.getStackInSlot( x ) ) )
{
this.addItems( this.data, inv, x, 1 );
}
}
}
}
if( !this.data.hasNoTags() )
{
try
{
NetworkHandler.instance().sendTo( new PacketCompressedNBT( this.data ), (EntityPlayerMP) this.getPlayerInv().player );
}
catch( final IOException e )
{
// :P
}
this.data = new NBTTagCompound();
}
}
public ConfigTracker getSlotByID( long id )
{
return this.byId.get( id );
}
@Override
public void doAction( final EntityPlayerMP player, final InventoryAction action, final int slot, final long id )
{
final ConfigTracker inv = this.byId.get( id );
if( inv != null )
{
final boolean hasItemInHand = !player.inventory.getItemStack().isEmpty();
final IItemHandler theSlot = new WrapperRangeItemHandler( inv.server, slot, slot + 1 );
ItemStack inSlot = theSlot.getStackInSlot( 0 );
switch ( action )
{
case PICKUP_OR_SET_DOWN:
if( hasItemInHand )
{
ItemHandlerUtil.setStackInSlot( theSlot, 0, player.inventory.getItemStack().copy() );
}
else
{
ItemHandlerUtil.setStackInSlot( theSlot, 0, ItemStack.EMPTY );
}
break;
case PLACE_SINGLE:
if( inSlot.getMaxStackSize() > inSlot.getCount() )
{
inSlot.grow( 1 );
ItemHandlerUtil.setStackInSlot( theSlot, 0, inSlot );
}
break;
case PICKUP_SINGLE:
if( theSlot.getStackInSlot( 0 ).getCount() > 1 )
{
inSlot.shrink( 1 );
ItemHandlerUtil.setStackInSlot( theSlot, 0, inSlot );
}
break;
case SPLIT_OR_PLACE_SINGLE:
if( hasItemInHand )
{
if( ItemStack.areItemsEqual( inSlot, player.inventory.getItemStack() ) && ItemStack.areItemStackTagsEqual( inSlot, player.inventory.getItemStack() ) )
{
inSlot.grow( 1 );
ItemHandlerUtil.setStackInSlot( theSlot, 0, inSlot.copy() );
}
else
{
ItemStack configuredStack = player.inventory.getItemStack().copy();
configuredStack.setCount( 1 );
ItemHandlerUtil.setStackInSlot( theSlot, 0, configuredStack );
}
}
else if( !inSlot.isEmpty() )
{
inSlot.shrink( 1 );
ItemHandlerUtil.setStackInSlot( theSlot, 0, inSlot.copy() );
}
break;
case SHIFT_CLICK:
ItemHandlerUtil.setStackInSlot( theSlot, 0, ItemStack.EMPTY );
break;
case CREATIVE_DUPLICATE:
if( player.capabilities.isCreativeMode && hasItemInHand )
{
ItemHandlerUtil.setStackInSlot( theSlot, 0, player.inventory.getItemStack().copy() );
}
break;
default:
return;
}
this.updateHeld( player );
}
}
private void regenList( final NBTTagCompound data )
{
this.byId.clear();
this.diList.clear();
final IActionHost host = this.getActionHost();
if( host != null )
{
final IGridNode agn = host.getActionableNode();
if( agn != null && agn.isActive() )
{
for( final IGridNode gn : this.grid.getMachines( TileInterface.class ) )
{
final IInterfaceHost ih = (IInterfaceHost) gn.getMachine();
final DualityInterface dual = ih.getInterfaceDuality();
if( gn.isActive() && dual.getConfigManager().getSetting( Settings.INTERFACE_TERMINAL ) == YesNo.YES )
{
this.diList.put( ih, new ConfigTracker( dual, dual.getConfig(), dual.getTermName() ) );
}
}
for( final IGridNode gn : this.grid.getMachines( PartInterface.class ) )
{
final IInterfaceHost ih = (IInterfaceHost) gn.getMachine();
final DualityInterface dual = ih.getInterfaceDuality();
if( gn.isActive() && dual.getConfigManager().getSetting( Settings.INTERFACE_TERMINAL ) == YesNo.YES )
{
this.diList.put( ih, new ConfigTracker( dual, dual.getConfig(), dual.getTermName() ) );
}
}
}
}
data.setBoolean( "clear", true );
for( final Entry<IInterfaceHost, ConfigTracker> en : this.diList.entrySet() )
{
final ConfigTracker inv = en.getValue();
this.byId.put( inv.which, inv );
this.addItems( data, inv, 0, inv.server.getSlots() );
}
}
private boolean isDifferent( final ItemStack a, final ItemStack b )
{
if( a.isEmpty() && b.isEmpty() )
{
return false;
}
if( a.isEmpty() || b.isEmpty() )
{
return true;
}
return !ItemStack.areItemStacksEqual( a, b );
}
private void addItems( final NBTTagCompound data, final ConfigTracker inv, final int offset, final int length )
{
final String name = '=' + Long.toString( inv.which, Character.MAX_RADIX );
final NBTTagCompound tag = data.getCompoundTag( name );
if( tag.hasNoTags() )
{
tag.setLong( "sortBy", inv.sortBy );
tag.setString( "un", inv.unlocalizedName );
tag.setTag( "pos", NBTUtil.createPosTag( inv.pos ) );
tag.setInteger( "dim", inv.dim );
}
for( int x = 0; x < length; x++ )
{
final NBTTagCompound itemNBT = new NBTTagCompound();
final ItemStack is = inv.server.getStackInSlot( x + offset );
// "update" client side.
ItemHandlerUtil.setStackInSlot( inv.client, x + offset, is.isEmpty() ? ItemStack.EMPTY : is.copy() );
if( !is.isEmpty() )
{
is.writeToNBT( itemNBT );
}
tag.setTag( Integer.toString( x + offset ), itemNBT );
}
data.setTag( name, tag );
}
public static class ConfigTracker
{
private final long sortBy;
private final long which = autoBase++;
private final String unlocalizedName;
private final IItemHandler client;
private final IItemHandler server;
private final BlockPos pos;
private final int dim;
public ConfigTracker( final DualityInterface dual, final IItemHandler configSlots, final String unlocalizedName )
{
this.server = configSlots;
this.client = new AppEngInternalInventory( null, this.server.getSlots() );
this.unlocalizedName = unlocalizedName;
this.sortBy = dual.getSortValue();
this.pos = dual.getLocation().getPos();
this.dim = dual.getLocation().getWorld().provider.getDimension();
}
public IItemHandler getServer()
{
return server;
}
}
}
@@ -80,6 +80,7 @@ public final class ApiParts implements IParts
private final IItemDefinition interfaceTerminal;
private final IItemDefinition patternTerminal;
private final IItemDefinition expandedProcessingPatternTerminal;
private final IItemDefinition interfaceConfigurationTerminal;
private final IItemDefinition craftingTerminal;
private final IItemDefinition terminal;
private final IItemDefinition storageMonitor;
@@ -142,6 +143,7 @@ public final class ApiParts implements IParts
this.interfaceTerminal = new DamagedItemDefinition( "part.terminal.interface", itemPart.createPart( PartType.INTERFACE_TERMINAL ) );
this.patternTerminal = new DamagedItemDefinition( "part.terminal.pattern", itemPart.createPart( PartType.PATTERN_TERMINAL ) );
this.expandedProcessingPatternTerminal = new DamagedItemDefinition( "part.terminal.expanded_processing_pattern", itemPart.createPart( PartType.EXPANDED_PROCESSING_PATTERN_TERMINAL ) );
this.interfaceConfigurationTerminal = new DamagedItemDefinition( "part.terminal.interface_configuration_terminal", itemPart.createPart( PartType.INTERFACE_CONFIGURATION_TERMINAL ) );
this.craftingTerminal = new DamagedItemDefinition( "part.terminal.crafting", itemPart.createPart( PartType.CRAFTING_TERMINAL ) );
this.terminal = new DamagedItemDefinition( "part.terminal", itemPart.createPart( PartType.TERMINAL ) );
this.storageMonitor = new DamagedItemDefinition( "part.monitor.storage", itemPart.createPart( PartType.STORAGE_MONITOR ) );
@@ -172,6 +172,7 @@ public enum GuiText
Missing,
InterfaceTerminal,
InterfaceConfigurationTerminal,
NoCraftingCPUs,
Clean,
InvalidPattern,
@@ -23,7 +23,7 @@ import java.lang.reflect.Constructor;
import appeng.container.implementations.*;
import appeng.parts.misc.PartOreDicStorageBus;
import appeng.parts.reporting.PartExpandedProcessingPatternTerminal;
import appeng.parts.reporting.*;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack;
@@ -74,9 +74,6 @@ import appeng.items.contents.QuartzKnifeObj;
import appeng.parts.automation.PartFormationPlane;
import appeng.parts.automation.PartLevelEmitter;
import appeng.parts.misc.PartStorageBus;
import appeng.parts.reporting.PartCraftingTerminal;
import appeng.parts.reporting.PartInterfaceTerminal;
import appeng.parts.reporting.PartPatternTerminal;
import appeng.tile.crafting.TileCraftingTile;
import appeng.tile.crafting.TileMolecularAssembler;
import appeng.tile.grindstone.TileGrinder;
@@ -180,7 +177,9 @@ public enum GuiBridge implements IGuiHandler
GUI_INTERFACE_TERMINAL( ContainerInterfaceTerminal.class, PartInterfaceTerminal.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_CRAFTING_STATUS( ContainerCraftingStatus.class, ITerminalHost.class, GuiHostType.ITEM_OR_WORLD, SecurityPermissions.CRAFT );
GUI_CRAFTING_STATUS( ContainerCraftingStatus.class, ITerminalHost.class, GuiHostType.ITEM_OR_WORLD, SecurityPermissions.CRAFT ),
GUI_INTERFACE_CONFIGURATION_TERMINAL( ContainerInterfaceConfigurationTerminal.class, PartInterfaceConfigurationTerminal.class, GuiHostType.WORLD, SecurityPermissions.BUILD );
private final Class tileClass;
private final Class containerClass;
@@ -343,7 +342,7 @@ public enum GuiBridge implements IGuiHandler
if( target == null )
{
throw new IllegalStateException( "Cannot find " + this.containerClass.getName() + "( " + this.typeName( inventory ) + ", " + this
.typeName( tE ) + " )" );
.typeName( tE ) + " )" );
}
return target.newInstance( inventory, tE );
@@ -441,7 +440,7 @@ public enum GuiBridge implements IGuiHandler
if( target == null )
{
throw new IllegalStateException( "Cannot find " + this.containerClass.getName() + "( " + this.typeName( inventory ) + ", " + this
.typeName( tE ) + " )" );
.typeName( tE ) + " )" );
}
return target.newInstance( inventory, tE );
@@ -27,6 +27,7 @@ import java.io.OutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import appeng.client.gui.implementations.GuiInterfaceConfigurationTerminal;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
@@ -113,5 +114,9 @@ public class PacketCompressedNBT extends AppEngPacket
{
( (GuiInterfaceTerminal) gs ).postUpdate( this.in );
}
else if( gs instanceof GuiInterfaceConfigurationTerminal )
{
( (GuiInterfaceConfigurationTerminal) gs ).postUpdate( this.in );
}
}
}
@@ -23,6 +23,9 @@ import java.io.IOException;
import java.util.Collections;
import appeng.api.storage.data.IAEFluidStack;
import appeng.client.me.SlotDisconnected;
import appeng.container.implementations.ContainerInterfaceConfigurationTerminal;
import appeng.container.implementations.ContainerInterfaceConfigurationTerminal.ConfigTracker;
import appeng.container.slot.IJEITargetSlot;
import appeng.container.slot.SlotFake;
import appeng.core.AELog;
@@ -30,11 +33,14 @@ import appeng.core.sync.network.NetworkHandler;
import appeng.fluids.client.gui.widgets.GuiFluidSlot;
import appeng.fluids.container.ContainerFluidConfigurable;
import appeng.fluids.util.AEFluidStack;
import appeng.util.helpers.ItemHandlerUtil;
import appeng.util.inv.WrapperRangeItemHandler;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
@@ -50,6 +56,7 @@ import appeng.helpers.InventoryAction;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.IItemHandler;
public class PacketInventoryAction extends AppEngPacket
@@ -111,14 +118,25 @@ public class PacketInventoryAction extends AppEngPacket
this.configureWrite( data );
}
public PacketInventoryAction(final InventoryAction action, final IJEITargetSlot slot, final IAEItemStack slotItem ) throws IOException
public PacketInventoryAction( final InventoryAction action, final IJEITargetSlot slot, final IAEItemStack slotItem ) throws IOException
{
this.action = action;
if (slot instanceof SlotFake)
this.slot = ((SlotFake) slot).slotNumber;
else this.slot = ((GuiFluidSlot) slot).getId();
this.id = 0;
if( slot instanceof SlotFake )
{
this.slot = ( (SlotFake) slot ).slotNumber;
this.id = 0;
}
else if( slot instanceof SlotDisconnected )
{
this.slot = ( (SlotDisconnected) slot ).getSlotIndex();
this.id = ( (SlotDisconnected) slot ).getSlot().getId();
}
else
{
this.slot = ( (GuiFluidSlot) slot ).getId();
this.id = 0;
}
this.slotItem = slotItem;
final ByteBuf data = Unpooled.buffer();
@@ -205,29 +223,44 @@ public class PacketInventoryAction extends AppEngPacket
}
}
}
else if( this.slot < sender.openContainer.inventorySlots.size() && sender.openContainer.inventorySlots.get( this.slot ) instanceof SlotFake )
else if( sender.openContainer instanceof ContainerInterfaceConfigurationTerminal )
{
if( this.slotItem != null )
ConfigTracker inv = ( (ContainerInterfaceConfigurationTerminal) sender.openContainer ).getSlotByID( this.id );
final IItemHandler theSlot = new WrapperRangeItemHandler( inv.getServer(), 0, slot + 1 );
ItemHandlerUtil.setStackInSlot( theSlot, this.slot, this.slotItem.createItemStack() );
}
else if( this.slot < sender.openContainer.inventorySlots.size() )
{
Slot senderSlot = sender.openContainer.inventorySlots.get( this.slot );
if( senderSlot instanceof SlotFake )
{
sender.openContainer.inventorySlots.get( this.slot ).putStack( this.slotItem.createItemStack() );
if( sender.openContainer.inventorySlots.get( this.slot ).getStack().isEmpty() )
if( this.slotItem != null )
{
IAEFluidStack aefs = AEFluidStack.fromNBT( this.slotItem.getDefinition().getTagCompound() );
if( aefs != null )
senderSlot.putStack( this.slotItem.createItemStack() );
if( senderSlot.getStack().isEmpty() )
{
FluidStack fluid = aefs.getFluidStack();
sender.openContainer.inventorySlots.get( this.slot ).putStack( AEFluidStack.fromFluidStack( fluid ).asItemStackRepresentation() );
IAEFluidStack aefs = AEFluidStack.fromNBT( this.slotItem.getDefinition().getTagCompound() );
if( aefs != null )
{
FluidStack fluid = aefs.getFluidStack();
senderSlot.putStack( AEFluidStack.fromFluidStack( fluid ).asItemStackRepresentation() );
}
}
}
}
else sender.openContainer.inventorySlots.get( this.slot ).putStack( ItemStack.EMPTY );
try
{
NetworkHandler.instance().sendTo( new PacketInventoryAction( InventoryAction.UPDATE_HAND, 0, AEItemStack.fromItemStack( ItemStack.EMPTY ) ), sender );
}
catch( final IOException e )
{
AELog.debug( e );
else
{
senderSlot.putStack( ItemStack.EMPTY );
}
try
{
NetworkHandler.instance().sendTo( new PacketInventoryAction( InventoryAction.UPDATE_HAND, 0, AEItemStack.fromItemStack( ItemStack.EMPTY ) ), sender );
}
catch( final IOException e )
{
AELog.debug( e );
}
}
}
}
@@ -284,7 +284,8 @@ public enum PartType
INTERFACE_TERMINAL( 480, "interface_terminal", EnumSet.of( AEFeature.INTERFACE_TERMINAL ), EnumSet.noneOf( IntegrationType.class ), PartInterfaceTerminal.class ),
FLUID_TERMINAL( 520, "fluid_terminal", EnumSet.of( AEFeature.FLUID_TERMINAL ), EnumSet.noneOf( IntegrationType.class ), PartFluidTerminal.class );
FLUID_TERMINAL( 520, "fluid_terminal", EnumSet.of( AEFeature.FLUID_TERMINAL ), EnumSet.noneOf( IntegrationType.class ), PartFluidTerminal.class ),
INTERFACE_CONFIGURATION_TERMINAL( 521, "interface_configuration_terminal", EnumSet.of( AEFeature.INTERFACE_TERMINAL ), EnumSet.noneOf( IntegrationType.class ), PartInterfaceConfigurationTerminal.class );
private final int baseDamage;
private final Set<AEFeature> features;
@@ -0,0 +1,77 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts.reporting;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d;
import appeng.api.parts.IPartModel;
import appeng.core.AppEng;
import appeng.core.sync.GuiBridge;
import appeng.items.parts.PartModels;
import appeng.parts.PartModel;
import appeng.util.Platform;
public class PartInterfaceConfigurationTerminal extends AbstractPartDisplay
{
@PartModels
public static final ResourceLocation MODEL_OFF = new ResourceLocation( AppEng.MOD_ID, "part/interface_configuration_terminal_off" );
@PartModels
public static final ResourceLocation MODEL_ON = new ResourceLocation( AppEng.MOD_ID, "part/interface_configuration_terminal_on" );
public static final IPartModel MODELS_OFF = new PartModel( MODEL_BASE, MODEL_OFF, MODEL_STATUS_OFF );
public static final IPartModel MODELS_ON = new PartModel( MODEL_BASE, MODEL_ON, MODEL_STATUS_ON );
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel( MODEL_BASE, MODEL_ON, MODEL_STATUS_HAS_CHANNEL );
public String in = "";
public PartInterfaceConfigurationTerminal( final ItemStack is )
{
super( is );
}
@Override
public boolean onPartActivate( final EntityPlayer player, final EnumHand hand, final Vec3d pos )
{
if( !super.onPartActivate( player, hand, pos ) )
{
if( Platform.isServer() )
{
Platform.openGUI( player, this.getHost().getTile(), this.getSide(), GuiBridge.GUI_INTERFACE_CONFIGURATION_TERMINAL );
}
}
return true;
}
@Override
public IPartModel getStaticModels()
{
return this.selectModel( MODELS_OFF, MODELS_ON, MODELS_HAS_CHANNEL );
}
public void saveSearchStrings( String in )
{
this.in = in;
}
}
@@ -168,6 +168,7 @@ gui.appliedenergistics2.StoredFluids=Stored Fluids
gui.appliedenergistics2.Terminal=Terminal
gui.appliedenergistics2.InterfaceTerminal=Interface Terminal
gui.appliedenergistics2.InterfaceTerminalHint=Show Or Hide on Interface Terminal.
gui.appliedenergistics2.InterfaceConfigurationTerminal=Interface Configuration Terminal
gui.appliedenergistics2.FormationPlane=Formation Plane
gui.appliedenergistics2.FluidFormationPlane=Fluid Formation Plane
gui.appliedenergistics2.VibrationChamber=Vibration Chamber
@@ -548,6 +549,7 @@ item.appliedenergistics2.multi_part.inverted_toggle_bus.name=ME Inverted Toggle
item.appliedenergistics2.multi_part.toggle_bus.name=ME Toggle Bus
item.appliedenergistics2.multi_part.crafting_monitor.name=ME Crafting Monitor
item.appliedenergistics2.multi_part.interface_terminal.name=ME Interface Terminal
item.appliedenergistics2.multi_part.interface_configuration_terminal.name=ME Configuration Interface Terminal
item.appliedenergistics2.multi_part.fluid_terminal.name=ME Fluid Terminal
item.appliedenergistics2.multi_part.invalid_type.name=Disabled Item
@@ -0,0 +1,9 @@
{
"parent": "appliedenergistics2:item/part/display",
"textures": {
"front": "appliedenergistics2:items/part/interface_terminal",
"front_bright": "appliedenergistics2:parts/interface_configuration_terminal_bright",
"front_medium": "appliedenergistics2:parts/interface_configuration_terminal_medium",
"front_dark": "appliedenergistics2:parts/interface_configuration_terminal_dark"
}
}
@@ -0,0 +1,8 @@
{
"parent": "appliedenergistics2:part/display_off",
"textures": {
"lightsBright": "appliedenergistics2:parts/interface_configuration_terminal_bright",
"lightsMedium": "appliedenergistics2:parts/interface_configuration_terminal_medium",
"lightsDark": "appliedenergistics2:parts/interface_configuration_terminal_dark"
}
}
@@ -0,0 +1,76 @@
{
"ae2_uvl_marker": true,
"textures": {
"lightsBright": "appliedenergistics2:parts/interface_configuration_terminal_bright",
"lightsMedium": "appliedenergistics2:parts/interface_configuration_terminal_medium",
"lightsDark": "appliedenergistics2:parts/interface_configuration_terminal_dark"
},
"elements": [
{
"from": [
2,
2,
0
],
"to": [
14,
14,
2
],
"faces": {
"north": {
"texture": "#lightsBright",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
}
}
},
{
"from": [
2,
2,
0
],
"to": [
14,
14,
2
],
"faces": {
"north": {
"texture": "#lightsMedium",
"tintindex": 2,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
}
}
},
{
"from": [
2,
2,
0
],
"to": [
14,
14,
2
],
"faces": {
"north": {
"texture": "#lightsDark",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
}
}
}
]
}
@@ -0,0 +1,19 @@
{
"conditions": [
{
"type": "minecraft:item_exists",
"item": "appliedenergistics2:interface"
}
],
"result": {
"type": "appliedenergistics2:part",
"part": "part.interface_terminal"
},
"type": "appliedenergistics2:part_shapeless",
"ingredients": [
{
"type": "appliedenergistics2:part",
"part": "part.interface_configuration_terminal"
}
]
}
@@ -0,0 +1,19 @@
{
"conditions": [
{
"type": "minecraft:item_exists",
"item": "appliedenergistics2:interface"
}
],
"result": {
"type": "appliedenergistics2:part",
"part": "part.interface_configuration_terminal"
},
"type": "appliedenergistics2:part_shapeless",
"ingredients": [
{
"type": "appliedenergistics2:part",
"part": "part.interface_terminal"
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB