mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-17 11:15:12 -04:00
Massive refactoring and redesign of how screens work, adding them to the API to allow re-use... to my huge surprise it seems to actually work so far. Rendering and some other parts will need some cleanup now.
Added environment creation method to item drivers that takes an entity instead of a tile entity, which might at some point be used for entity-based computers (e.g. more advanced robots, portable computers, ...) Removed gpu.getSize, added screen.getAspectRatio. I'm kind of afraid of merging this into the 1.7 branch... conflicts ahoy.
This commit is contained in:
parent
859716b77c
commit
e7c7ad31e6
47
src/main/java/li/cil/oc/api/component/Keyboard.java
Normal file
47
src/main/java/li/cil/oc/api/component/Keyboard.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package li.cil.oc.api.component;
|
||||||
|
|
||||||
|
import li.cil.oc.api.Persistable;
|
||||||
|
import li.cil.oc.api.network.Environment;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface is implemented by the keyboard component, to allow more
|
||||||
|
* flexible use of it.
|
||||||
|
* <p/>
|
||||||
|
* You can obtain an instance of the keyboard component via the item driver
|
||||||
|
* of the keyboard block, for example:
|
||||||
|
* <pre>
|
||||||
|
* final ItemStack stack = li.cil.oc.api.Items.get("keyboard").createItemStack(1);
|
||||||
|
* final Keyboard keyboard = (Keyboard) li.cil.oc.api.Driver.driverFor(stack).createEnvironment(stack, this);
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public interface Keyboard extends Environment, Persistable {
|
||||||
|
/**
|
||||||
|
* Sets a custom usability override.
|
||||||
|
* <p/>
|
||||||
|
* Instead of the default check, which is based on the component's owner's
|
||||||
|
* position, the specified callback will be queried for usability checks
|
||||||
|
* instead.
|
||||||
|
* <p/>
|
||||||
|
* Pass <tt>null</tt> here to unset a previously set override.
|
||||||
|
*
|
||||||
|
* @param callback the usability checker to use.
|
||||||
|
*/
|
||||||
|
void setUsableOverride(UsabilityChecker callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contract interface that has to implemented for usability check overides.
|
||||||
|
*
|
||||||
|
* @see #setUsableOverride(li.cil.oc.api.component.Keyboard.UsabilityChecker)
|
||||||
|
*/
|
||||||
|
public static interface UsabilityChecker {
|
||||||
|
/**
|
||||||
|
* Whether the specified keyboard is usable by the specified player.
|
||||||
|
*
|
||||||
|
* @param keyboard the keyboard to check for.
|
||||||
|
* @param player the player to check for.
|
||||||
|
* @return whether the keyboard is usable by the player.
|
||||||
|
*/
|
||||||
|
boolean isUsableByPlayer(Keyboard keyboard, EntityPlayer player);
|
||||||
|
}
|
||||||
|
}
|
173
src/main/java/li/cil/oc/api/component/Screen.java
Normal file
173
src/main/java/li/cil/oc/api/component/Screen.java
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
package li.cil.oc.api.component;
|
||||||
|
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
import li.cil.oc.api.Persistable;
|
||||||
|
import li.cil.oc.api.network.ManagedEnvironment;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface is implemented by screens' environments.
|
||||||
|
* <p/>
|
||||||
|
* This allows re-using the built-in screens in third-party code without
|
||||||
|
* access to the internals of OC.
|
||||||
|
* <p/>
|
||||||
|
* To get an instance of the screen component, use its item driver, e.g.:
|
||||||
|
* <pre>
|
||||||
|
* final ItemStack stack = li.cil.oc.api.Items.get("screen1").createItemStack(1);
|
||||||
|
* final Screen screen = (Screen) li.cil.oc.api.Driver.driverFor(stack).createEnvironment(stack, this);
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public interface Screen extends ManagedEnvironment, Persistable {
|
||||||
|
void setEnergyCostPerTick(double value);
|
||||||
|
|
||||||
|
double getEnergyCostPerTick();
|
||||||
|
|
||||||
|
void setPowerState(boolean value);
|
||||||
|
|
||||||
|
boolean getPowerState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the maximum resolution supported by this screen.
|
||||||
|
*
|
||||||
|
* @param width the maximum horizontal resolution, in characters.
|
||||||
|
* @param height the maximum vertical resolution, in characters.
|
||||||
|
*/
|
||||||
|
void setMaximumResolution(int width, int height);
|
||||||
|
|
||||||
|
int getMaximumWidth();
|
||||||
|
|
||||||
|
int getMaximumHeight();
|
||||||
|
|
||||||
|
void setAspectRatio(double width, double height);
|
||||||
|
|
||||||
|
double getAspectRatio();
|
||||||
|
|
||||||
|
boolean setResolution(int width, int height);
|
||||||
|
|
||||||
|
int getWidth();
|
||||||
|
|
||||||
|
int getHeight();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the maximum color depth supported by this screen.
|
||||||
|
* <p/>
|
||||||
|
* Note that this is the <em>maximum</em> supported depth, lower depths
|
||||||
|
* will be supported, too. So when setting this to four bit, one bit will
|
||||||
|
* be supported, too. When setting this to eight bit, four and one bit
|
||||||
|
* will be supported, also.
|
||||||
|
*
|
||||||
|
* @param depth the maximum color depth of the screen.
|
||||||
|
*/
|
||||||
|
void setMaximumColorDepth(ColorDepth depth);
|
||||||
|
|
||||||
|
ColorDepth getMaximumColorDepth();
|
||||||
|
|
||||||
|
boolean setColorDepth(ColorDepth depth);
|
||||||
|
|
||||||
|
ColorDepth getColorDepth();
|
||||||
|
|
||||||
|
void setPaletteColor(int index, int color);
|
||||||
|
|
||||||
|
int getPaletteColor(int index);
|
||||||
|
|
||||||
|
void setForegroundColor(int color);
|
||||||
|
|
||||||
|
void setForegroundColor(int color, boolean isFromPalette);
|
||||||
|
|
||||||
|
int getForegroundColor();
|
||||||
|
|
||||||
|
boolean isForegroundFromPalette();
|
||||||
|
|
||||||
|
void setBackgroundColor(int color);
|
||||||
|
|
||||||
|
void setBackgroundColor(int color, boolean isFromPalette);
|
||||||
|
|
||||||
|
int getBackgroundColor();
|
||||||
|
|
||||||
|
boolean isBackgroundFromPalette();
|
||||||
|
|
||||||
|
void copy(int column, int row, int width, int height, int horizontalTranslation, int verticalTranslation);
|
||||||
|
|
||||||
|
void fill(int column, int row, int width, int height, char value);
|
||||||
|
|
||||||
|
void set(int column, int row, String value);
|
||||||
|
|
||||||
|
char get(int column, int row);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the <em>text</em> displayed on the screen.
|
||||||
|
* <p/>
|
||||||
|
* You are responsible for setting up the actual context and applying any
|
||||||
|
* transformations necessary to properly position and scale the text before
|
||||||
|
* calling this. The text should be rendered on a black background.
|
||||||
|
* <p/>
|
||||||
|
* You can use this to either render the text in a GUI or in the world.
|
||||||
|
*/
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
void renderText();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The natural width of the rendered text.
|
||||||
|
* <p/>
|
||||||
|
* This is the width of the complete text buffer, in pixels. In other
|
||||||
|
* words, this is the width of the buffer in chars times the actual width
|
||||||
|
* of a single char in pixels.
|
||||||
|
*
|
||||||
|
* @return the total width of the rendered buffer, in pixels.
|
||||||
|
*/
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
int renderWidth();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The natural height of the rendered text.
|
||||||
|
* <p/>
|
||||||
|
* This is the height of the complete text buffer, in pixels. In other
|
||||||
|
* words, this is the height of the buffer in chars times the actual height
|
||||||
|
* of a single char in pixels.
|
||||||
|
*
|
||||||
|
* @return the total height of the rendered buffer, in pixels.
|
||||||
|
*/
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
int renderHeight();
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
void setRenderingEnabled(boolean enabled);
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
boolean isRenderingEnabled();
|
||||||
|
|
||||||
|
void keyDown(char character, int code, EntityPlayer player);
|
||||||
|
|
||||||
|
void keyUp(char character, int code, EntityPlayer player);
|
||||||
|
|
||||||
|
void clipboard(String value, EntityPlayer player);
|
||||||
|
|
||||||
|
void mouseDown(int x, int y, int button, EntityPlayer player);
|
||||||
|
|
||||||
|
void mouseDrag(int x, int y, int button, EntityPlayer player);
|
||||||
|
|
||||||
|
void mouseUp(int x, int y, int button, EntityPlayer player);
|
||||||
|
|
||||||
|
void mouseScroll(int x, int y, int delta, EntityPlayer player);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used when setting a screens maximum color depth.
|
||||||
|
*/
|
||||||
|
public static enum ColorDepth {
|
||||||
|
/**
|
||||||
|
* Monochrome color, black and white.
|
||||||
|
*/
|
||||||
|
OneBit,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 16 color palette, defaults to Minecraft colors.
|
||||||
|
*/
|
||||||
|
FourBit,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 240 colors, 16 color palette, defaults to grayscale.
|
||||||
|
*/
|
||||||
|
EightBit
|
||||||
|
}
|
||||||
|
}
|
8
src/main/java/li/cil/oc/api/component/package-info.java
Normal file
8
src/main/java/li/cil/oc/api/component/package-info.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* This package contains component specific interfaces.
|
||||||
|
* <p/>
|
||||||
|
* These are implemented by some of the environments created by item drivers
|
||||||
|
* for built-in items, which allows for them to be re-used by third-party mods
|
||||||
|
* without having to access the internals of OpenComputers.
|
||||||
|
*/
|
||||||
|
package li.cil.oc.api.component;
|
@ -1,6 +1,7 @@
|
|||||||
package li.cil.oc.api.driver;
|
package li.cil.oc.api.driver;
|
||||||
|
|
||||||
import li.cil.oc.api.network.ManagedEnvironment;
|
import li.cil.oc.api.network.ManagedEnvironment;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
@ -62,6 +63,24 @@ public interface Item {
|
|||||||
*/
|
*/
|
||||||
ManagedEnvironment createEnvironment(ItemStack stack, TileEntity container);
|
ManagedEnvironment createEnvironment(ItemStack stack, TileEntity container);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new managed environment interfacing the specified item.
|
||||||
|
* <p/>
|
||||||
|
* This is the same as {@link #createEnvironment(net.minecraft.item.ItemStack, net.minecraft.tileentity.TileEntity)},
|
||||||
|
* except that it allows specifying entities, such as players, as the
|
||||||
|
* container of the environment, specifying information such as the
|
||||||
|
* position in the world that way.
|
||||||
|
* <p/>
|
||||||
|
* Not all components will support both types of environment. If you only
|
||||||
|
* intend your component to be used from within computers, for example,
|
||||||
|
* it is safe to simply return <tt>null</tt> here.
|
||||||
|
*
|
||||||
|
* @param stack the item stack for which to get the environment.
|
||||||
|
* @param container the entity the environment will be managed by.
|
||||||
|
* @return the environment for that item.
|
||||||
|
*/
|
||||||
|
ManagedEnvironment createEnvironment(ItemStack stack, Entity container);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The slot type of the specified item this driver supports.
|
* The slot type of the specified item this driver supports.
|
||||||
* <p/>
|
* <p/>
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
package li.cil.oc.api.network;
|
|
||||||
|
|
||||||
import li.cil.oc.api.machine.Robot;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is no longer used nor provided to callbacks. The context in a callback
|
|
||||||
* will always be the one of a machine. To get access to a robot either use
|
|
||||||
* its tile entity where possible (which implements {@link Robot}) or use
|
|
||||||
* <tt>(Robot)((Machine)context).owner()</tt>.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public interface RobotContext extends Context {
|
|
||||||
/**
|
|
||||||
* Gets the index of the currently selected slot in the robot's inventory.
|
|
||||||
*
|
|
||||||
* @return the index of the currently selected slot.
|
|
||||||
*/
|
|
||||||
int selectedSlot();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the fake player used to represent the robot as an entity for
|
|
||||||
* certain actions that require one.
|
|
||||||
* <p/>
|
|
||||||
* This will automatically be positioned and rotated to represent the
|
|
||||||
* robot's current position and rotation in the world. Use this to trigger
|
|
||||||
* events involving the robot that require a player entity, and for
|
|
||||||
* interacting with the robots' inventory.
|
|
||||||
* <p/>
|
|
||||||
* Note that the inventory of each robot is structured such that the first
|
|
||||||
* four slots are the "equipment" slots, from left to right, i.e. slot one
|
|
||||||
* is the tool slot, slot two is the card slot, three the disk slot and
|
|
||||||
* slot four is for upgrades. The inventory proper starts after that.
|
|
||||||
*
|
|
||||||
* @return the fake player for the robot.
|
|
||||||
*/
|
|
||||||
EntityPlayer player();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Causes the currently installed upgrade to be saved and synchronized.
|
|
||||||
* <p/>
|
|
||||||
* If no upgrade is installed in the robot this does nothing.
|
|
||||||
* <p/>
|
|
||||||
* This is intended for upgrade components, to allow them to update their
|
|
||||||
* client side representation for rendering purposes. The component will be
|
|
||||||
* saved to its item's NBT tag compound, as it would be when the game is
|
|
||||||
* saved, and then re-sent to the client. Keep the number of calls to this
|
|
||||||
* function low, since each call causes a network packet to be sent.
|
|
||||||
*/
|
|
||||||
void saveUpgrade();
|
|
||||||
}
|
|
@ -3,11 +3,11 @@ package li.cil.oc
|
|||||||
import com.typesafe.config.{ConfigRenderOptions, Config, ConfigFactory}
|
import com.typesafe.config.{ConfigRenderOptions, Config, ConfigFactory}
|
||||||
import java.io._
|
import java.io._
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
import li.cil.oc.util.PackedColor
|
import li.cil.oc.api.component.Screen.ColorDepth
|
||||||
|
import li.cil.oc.util.mods.Mods
|
||||||
import org.apache.commons.lang3.StringEscapeUtils
|
import org.apache.commons.lang3.StringEscapeUtils
|
||||||
import scala.collection.convert.WrapAsScala._
|
import scala.collection.convert.WrapAsScala._
|
||||||
import scala.io.Source
|
import scala.io.Source
|
||||||
import li.cil.oc.util.mods.Mods
|
|
||||||
|
|
||||||
class Settings(config: Config) {
|
class Settings(config: Config) {
|
||||||
val itemId = config.getInt("ids.item")
|
val itemId = config.getInt("ids.item")
|
||||||
@ -194,7 +194,7 @@ object Settings {
|
|||||||
val savePath = "opencomputers/"
|
val savePath = "opencomputers/"
|
||||||
val scriptPath = "/assets/" + resourceDomain + "/lua/"
|
val scriptPath = "/assets/" + resourceDomain + "/lua/"
|
||||||
val screenResolutionsByTier = Array((50, 16), (80, 25), (160, 50))
|
val screenResolutionsByTier = Array((50, 16), (80, 25), (160, 50))
|
||||||
val screenDepthsByTier = Array(PackedColor.Depth.OneBit, PackedColor.Depth.FourBit, PackedColor.Depth.EightBit)
|
val screenDepthsByTier = Array(ColorDepth.OneBit, ColorDepth.FourBit, ColorDepth.EightBit)
|
||||||
val hologramMaxScaleByTier = Array(3, 4)
|
val hologramMaxScaleByTier = Array(3, 4)
|
||||||
|
|
||||||
// Power conversion values. These are the same values used by Universal
|
// Power conversion values. These are the same values used by Universal
|
||||||
|
5
src/main/scala/li/cil/oc/client/ComponentTracker.scala
Normal file
5
src/main/scala/li/cil/oc/client/ComponentTracker.scala
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package li.cil.oc.client
|
||||||
|
|
||||||
|
import li.cil.oc.common
|
||||||
|
|
||||||
|
object ComponentTracker extends common.ComponentTracker
|
@ -20,7 +20,7 @@ object GuiHandler extends CommonGuiHandler {
|
|||||||
case rack: tileentity.Rack if id == GuiType.Rack.id =>
|
case rack: tileentity.Rack if id == GuiType.Rack.id =>
|
||||||
new gui.Rack(player.inventory, rack)
|
new gui.Rack(player.inventory, rack)
|
||||||
case screen: tileentity.Screen if id == GuiType.Screen.id =>
|
case screen: tileentity.Screen if id == GuiType.Screen.id =>
|
||||||
new gui.Screen(screen.origin.buffer, screen.tier > 0, () => screen.origin.hasPower)
|
new gui.Screen(screen.origin.buffer, screen.tier > 0, () => screen.origin.buffer.isRenderingEnabled)
|
||||||
case _ => Items.multi.subItem(player.getCurrentEquippedItem) match {
|
case _ => Items.multi.subItem(player.getCurrentEquippedItem) match {
|
||||||
case Some(server: item.Server) if id == GuiType.Server.id =>
|
case Some(server: item.Server) if id == GuiType.Server.id =>
|
||||||
new gui.Server(player.inventory, new ServerInventory {
|
new gui.Server(player.inventory, new ServerInventory {
|
||||||
|
@ -2,17 +2,17 @@ package li.cil.oc.client
|
|||||||
|
|
||||||
import cpw.mods.fml.common.network.Player
|
import cpw.mods.fml.common.network.Player
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
|
import li.cil.oc.api.component
|
||||||
|
import li.cil.oc.common.{PacketHandler => CommonPacketHandler}
|
||||||
import li.cil.oc.common.PacketType
|
import li.cil.oc.common.PacketType
|
||||||
import li.cil.oc.common.tileentity._
|
import li.cil.oc.common.tileentity._
|
||||||
import li.cil.oc.common.{PacketHandler => CommonPacketHandler}
|
import li.cil.oc.common.tileentity.traits._
|
||||||
import li.cil.oc.util.{Audio, PackedColor}
|
import li.cil.oc.util.Audio
|
||||||
import net.minecraft.client.gui.GuiScreen
|
import net.minecraft.client.gui.GuiScreen
|
||||||
import net.minecraft.entity.player.EntityPlayer
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
import net.minecraft.util.ChatMessageComponent
|
import net.minecraft.util.ChatMessageComponent
|
||||||
import net.minecraftforge.common.ForgeDirection
|
import net.minecraftforge.common.ForgeDirection
|
||||||
import org.lwjgl.input.Keyboard
|
import org.lwjgl.input.Keyboard
|
||||||
import li.cil.oc.common.tileentity.traits._
|
|
||||||
import scala.Some
|
|
||||||
|
|
||||||
class PacketHandler extends CommonPacketHandler {
|
class PacketHandler extends CommonPacketHandler {
|
||||||
protected override def world(player: Player, dimension: Int) = {
|
protected override def world(player: Player, dimension: Int) = {
|
||||||
@ -45,14 +45,14 @@ class PacketHandler extends CommonPacketHandler {
|
|||||||
case PacketType.RobotXp => onRobotXp(p)
|
case PacketType.RobotXp => onRobotXp(p)
|
||||||
case PacketType.RotatableState => onRotatableState(p)
|
case PacketType.RotatableState => onRotatableState(p)
|
||||||
case PacketType.RouterActivity => onRouterActivity(p)
|
case PacketType.RouterActivity => onRouterActivity(p)
|
||||||
case PacketType.ScreenColorChange => onScreenColorChange(p)
|
case PacketType.TextBufferColorChange => onTextBufferColorChange(p)
|
||||||
case PacketType.ScreenCopy => onScreenCopy(p)
|
case PacketType.TextBufferCopy => onTextBufferCopy(p)
|
||||||
case PacketType.ScreenDepthChange => onScreenDepthChange(p)
|
case PacketType.TextBufferDepthChange => onTextBufferDepthChange(p)
|
||||||
case PacketType.ScreenFill => onScreenFill(p)
|
case PacketType.TextBufferFill => onTextBufferFill(p)
|
||||||
case PacketType.ScreenPaletteChange => onScreenPaletteChange(p)
|
case PacketType.TextBufferPaletteChange => onTextBufferPaletteChange(p)
|
||||||
case PacketType.ScreenPowerChange => onScreenPowerChange(p)
|
case PacketType.TextBufferPowerChange => onTextBufferPowerChange(p)
|
||||||
case PacketType.ScreenResolutionChange => onScreenResolutionChange(p)
|
case PacketType.TextBufferResolutionChange => onTextBufferResolutionChange(p)
|
||||||
case PacketType.ScreenSet => onScreenSet(p)
|
case PacketType.TextBufferSet => onTextBufferSet(p)
|
||||||
case PacketType.ServerPresence => onServerPresence(p)
|
case PacketType.ServerPresence => onServerPresence(p)
|
||||||
case PacketType.Sound => onSound(p)
|
case PacketType.Sound => onSound(p)
|
||||||
case _ => // Invalid packet.
|
case _ => // Invalid packet.
|
||||||
@ -252,96 +252,90 @@ class PacketHandler extends CommonPacketHandler {
|
|||||||
case _ => // Invalid packet.
|
case _ => // Invalid packet.
|
||||||
}
|
}
|
||||||
|
|
||||||
def onScreenColorChange(p: PacketParser) {
|
def onTextBufferColorChange(p: PacketParser) {
|
||||||
val buffer = p.readTileEntity[TileEntity]() match {
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
case Some(t: TextBuffer) => t.buffer
|
case Some(buffer: component.Screen) =>
|
||||||
case Some(t: Rack) => t.terminals(p.readInt()).buffer
|
val foreground = p.readInt()
|
||||||
case _ => return // Invalid packet.
|
val foregroundIsPalette = p.readBoolean()
|
||||||
|
buffer.setForegroundColor(foreground, foregroundIsPalette)
|
||||||
|
val background = p.readInt()
|
||||||
|
val backgroundIsPalette = p.readBoolean()
|
||||||
|
buffer.setBackgroundColor(background, backgroundIsPalette)
|
||||||
|
case _ => // Invalid packet.
|
||||||
}
|
}
|
||||||
val foreground = p.readInt()
|
|
||||||
val foregroundIsPalette = p.readBoolean()
|
|
||||||
buffer.foreground = PackedColor.Color(foreground, foregroundIsPalette)
|
|
||||||
val background = p.readInt()
|
|
||||||
val backgroundIsPalette = p.readBoolean()
|
|
||||||
buffer.background = PackedColor.Color(background, backgroundIsPalette)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def onScreenCopy(p: PacketParser) {
|
def onTextBufferCopy(p: PacketParser) {
|
||||||
val buffer = p.readTileEntity[TileEntity]() match {
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
case Some(t: TextBuffer) => t.buffer
|
case Some(buffer: component.Screen) =>
|
||||||
case Some(t: Rack) => t.terminals(p.readInt()).buffer
|
val col = p.readInt()
|
||||||
case _ => return // Invalid packet.
|
val row = p.readInt()
|
||||||
|
val w = p.readInt()
|
||||||
|
val h = p.readInt()
|
||||||
|
val tx = p.readInt()
|
||||||
|
val ty = p.readInt()
|
||||||
|
buffer.copy(col, row, w, h, tx, ty)
|
||||||
|
case _ => // Invalid packet.
|
||||||
}
|
}
|
||||||
val col = p.readInt()
|
|
||||||
val row = p.readInt()
|
|
||||||
val w = p.readInt()
|
|
||||||
val h = p.readInt()
|
|
||||||
val tx = p.readInt()
|
|
||||||
val ty = p.readInt()
|
|
||||||
buffer.copy(col, row, w, h, tx, ty)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def onScreenDepthChange(p: PacketParser) {
|
def onTextBufferDepthChange(p: PacketParser) {
|
||||||
val buffer = p.readTileEntity[TileEntity]() match {
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
case Some(t: TextBuffer) => t.buffer
|
case Some(buffer: component.Screen) =>
|
||||||
case Some(t: Rack) => t.terminals(p.readInt()).buffer
|
buffer.setColorDepth(component.Screen.ColorDepth.values.apply(p.readInt()))
|
||||||
case _ => return // Invalid packet.
|
case _ => // Invalid packet.
|
||||||
}
|
}
|
||||||
buffer.format = PackedColor.Depth.format(PackedColor.Depth(p.readInt()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def onScreenFill(p: PacketParser) {
|
def onTextBufferFill(p: PacketParser) {
|
||||||
val buffer = p.readTileEntity[TileEntity]() match {
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
case Some(t: TextBuffer) => t.buffer
|
case Some(buffer: component.Screen) =>
|
||||||
case Some(t: Rack) => t.terminals(p.readInt()).buffer
|
val col = p.readInt()
|
||||||
case _ => return // Invalid packet.
|
val row = p.readInt()
|
||||||
|
val w = p.readInt()
|
||||||
|
val h = p.readInt()
|
||||||
|
val c = p.readChar()
|
||||||
|
buffer.fill(col, row, w, h, c)
|
||||||
|
case _ => // Invalid packet.
|
||||||
}
|
}
|
||||||
val col = p.readInt()
|
|
||||||
val row = p.readInt()
|
|
||||||
val w = p.readInt()
|
|
||||||
val h = p.readInt()
|
|
||||||
val c = p.readChar()
|
|
||||||
buffer.fill(col, row, w, h, c)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def onScreenPaletteChange(p: PacketParser) {
|
def onTextBufferPaletteChange(p: PacketParser) {
|
||||||
val buffer = p.readTileEntity[TileEntity]() match {
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
case Some(t: TextBuffer) => t.buffer
|
case Some(buffer: component.Screen) =>
|
||||||
case Some(t: Rack) => t.terminals(p.readInt()).buffer
|
val index = p.readInt()
|
||||||
case _ => return // Invalid packet.
|
val color = p.readInt()
|
||||||
|
buffer.setPaletteColor(index, color)
|
||||||
|
case _ => // Invalid packet.
|
||||||
}
|
}
|
||||||
val index = p.readInt()
|
|
||||||
val color = p.readInt()
|
|
||||||
buffer.setPalette(index, color)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def onScreenPowerChange(p: PacketParser) =
|
def onTextBufferPowerChange(p: PacketParser) =
|
||||||
p.readTileEntity[Screen]() match {
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
case Some(t) => t.hasPower = p.readBoolean()
|
case Some(buffer: component.Screen) =>
|
||||||
|
buffer.setRenderingEnabled(p.readBoolean())
|
||||||
case _ => // Invalid packet.
|
case _ => // Invalid packet.
|
||||||
}
|
}
|
||||||
|
|
||||||
def onScreenResolutionChange(p: PacketParser) {
|
def onTextBufferResolutionChange(p: PacketParser) {
|
||||||
val buffer = p.readTileEntity[TileEntity]() match {
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
case Some(t: TextBuffer) => t.buffer
|
case Some(buffer: component.Screen) =>
|
||||||
case Some(t: Rack) => t.terminals(p.readInt()).buffer
|
val w = p.readInt()
|
||||||
case _ => return // Invalid packet.
|
val h = p.readInt()
|
||||||
|
buffer.setResolution(w, h)
|
||||||
|
case _ => // Invalid packet.
|
||||||
}
|
}
|
||||||
val w = p.readInt()
|
|
||||||
val h = p.readInt()
|
|
||||||
buffer.resolution = (w, h)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def onScreenSet(p: PacketParser) {
|
def onTextBufferSet(p: PacketParser) {
|
||||||
val buffer = p.readTileEntity[TileEntity]() match {
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
case Some(t: TextBuffer) => t.buffer
|
case Some(buffer: component.Screen) =>
|
||||||
case Some(t: Rack) => t.terminals(p.readInt()).buffer
|
val col = p.readInt()
|
||||||
case _ => return // Invalid packet.
|
val row = p.readInt()
|
||||||
|
val s = p.readUTF()
|
||||||
|
buffer.set(col, row, s)
|
||||||
|
case _ => // Invalid packet.
|
||||||
}
|
}
|
||||||
val col = p.readInt()
|
|
||||||
val row = p.readInt()
|
|
||||||
val s = p.readUTF()
|
|
||||||
buffer.set(col, row, s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def onServerPresence(p: PacketParser) =
|
def onServerPresence(p: PacketParser) =
|
||||||
|
@ -20,41 +20,27 @@ object PacketSender {
|
|||||||
pb.sendToServer()
|
pb.sendToServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendKeyDown(b: component.Buffer, char: Char, code: Int) {
|
def sendKeyDown(address: String, char: Char, code: Int) {
|
||||||
val pb = new PacketBuilder(PacketType.KeyDown)
|
val pb = new PacketBuilder(PacketType.KeyDown)
|
||||||
|
|
||||||
b.owner match {
|
pb.writeUTF(address)
|
||||||
case t: TextBuffer if t.hasKeyboard =>
|
|
||||||
pb.writeTileEntity(t)
|
|
||||||
case t: component.Terminal =>
|
|
||||||
pb.writeTileEntity(t.rack)
|
|
||||||
pb.writeInt(t.number)
|
|
||||||
case _ => return
|
|
||||||
}
|
|
||||||
pb.writeChar(char)
|
pb.writeChar(char)
|
||||||
pb.writeInt(code)
|
pb.writeInt(code)
|
||||||
|
|
||||||
pb.sendToServer()
|
pb.sendToServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendKeyUp(b: component.Buffer, char: Char, code: Int) {
|
def sendKeyUp(address: String, char: Char, code: Int) {
|
||||||
val pb = new PacketBuilder(PacketType.KeyUp)
|
val pb = new PacketBuilder(PacketType.KeyUp)
|
||||||
|
|
||||||
b.owner match {
|
pb.writeUTF(address)
|
||||||
case t: TextBuffer if t.hasKeyboard =>
|
|
||||||
pb.writeTileEntity(t)
|
|
||||||
case t: component.Terminal =>
|
|
||||||
pb.writeTileEntity(t.rack)
|
|
||||||
pb.writeInt(t.number)
|
|
||||||
case _ => return
|
|
||||||
}
|
|
||||||
pb.writeChar(char)
|
pb.writeChar(char)
|
||||||
pb.writeInt(code)
|
pb.writeInt(code)
|
||||||
|
|
||||||
pb.sendToServer()
|
pb.sendToServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendClipboard(b: component.Buffer, value: String) {
|
def sendClipboard(address: String, value: String) {
|
||||||
if (value != null && !value.isEmpty) {
|
if (value != null && !value.isEmpty) {
|
||||||
if (System.currentTimeMillis() < clipboardCooldown) {
|
if (System.currentTimeMillis() < clipboardCooldown) {
|
||||||
Minecraft.getMinecraft.sndManager.playSoundFX("note.harp", 3, 1)
|
Minecraft.getMinecraft.sndManager.playSoundFX("note.harp", 3, 1)
|
||||||
@ -63,14 +49,7 @@ object PacketSender {
|
|||||||
clipboardCooldown = System.currentTimeMillis() + value.length / 10
|
clipboardCooldown = System.currentTimeMillis() + value.length / 10
|
||||||
val pb = new CompressedPacketBuilder(PacketType.Clipboard)
|
val pb = new CompressedPacketBuilder(PacketType.Clipboard)
|
||||||
|
|
||||||
b.owner match {
|
pb.writeUTF(address)
|
||||||
case t: TextBuffer if t.hasKeyboard =>
|
|
||||||
pb.writeTileEntity(t)
|
|
||||||
case t: component.Terminal =>
|
|
||||||
pb.writeTileEntity(t.rack)
|
|
||||||
pb.writeInt(t.number)
|
|
||||||
case _ => return
|
|
||||||
}
|
|
||||||
pb.writeUTF(value.substring(0, math.min(value.length, 64 * 1024)))
|
pb.writeUTF(value.substring(0, math.min(value.length, 64 * 1024)))
|
||||||
|
|
||||||
pb.sendToServer()
|
pb.sendToServer()
|
||||||
@ -78,56 +57,35 @@ object PacketSender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendMouseClick(b: component.Buffer, x: Int, y: Int, drag: Boolean, button: Int) {
|
def sendMouseClick(address: String, x: Int, y: Int, drag: Boolean, button: Int) {
|
||||||
val pb = new PacketBuilder(PacketType.MouseClickOrDrag)
|
val pb = new PacketBuilder(PacketType.MouseClickOrDrag)
|
||||||
|
|
||||||
b.owner match {
|
pb.writeUTF(address)
|
||||||
case t: TextBuffer if t.tier > 0 =>
|
pb.writeShort(x)
|
||||||
pb.writeTileEntity(t)
|
pb.writeShort(y)
|
||||||
case t: component.Terminal =>
|
|
||||||
pb.writeTileEntity(t.rack)
|
|
||||||
pb.writeInt(t.number)
|
|
||||||
case _ => return
|
|
||||||
}
|
|
||||||
pb.writeInt(x)
|
|
||||||
pb.writeInt(y)
|
|
||||||
pb.writeBoolean(drag)
|
pb.writeBoolean(drag)
|
||||||
pb.writeByte(button.toByte)
|
pb.writeByte(button.toByte)
|
||||||
|
|
||||||
pb.sendToServer()
|
pb.sendToServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendMouseScroll(b: component.Buffer, x: Int, y: Int, scroll: Int) {
|
def sendMouseScroll(address: String, x: Int, y: Int, scroll: Int) {
|
||||||
val pb = new PacketBuilder(PacketType.MouseScroll)
|
val pb = new PacketBuilder(PacketType.MouseScroll)
|
||||||
|
|
||||||
b.owner match {
|
pb.writeUTF(address)
|
||||||
case t: TextBuffer if t.tier > 0 =>
|
pb.writeShort(x)
|
||||||
pb.writeTileEntity(t)
|
pb.writeShort(y)
|
||||||
case t: component.Terminal =>
|
|
||||||
pb.writeTileEntity(t.rack)
|
|
||||||
pb.writeInt(t.number)
|
|
||||||
case _ => return
|
|
||||||
}
|
|
||||||
pb.writeInt(x)
|
|
||||||
pb.writeInt(y)
|
|
||||||
pb.writeByte(scroll)
|
pb.writeByte(scroll)
|
||||||
|
|
||||||
pb.sendToServer()
|
pb.sendToServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendMouseUp(b: component.Buffer, x: Int, y: Int, button: Int) {
|
def sendMouseUp(address: String, x: Int, y: Int, button: Int) {
|
||||||
val pb = new PacketBuilder(PacketType.MouseUp)
|
val pb = new PacketBuilder(PacketType.MouseUp)
|
||||||
|
|
||||||
b.owner match {
|
pb.writeUTF(address)
|
||||||
case t: TextBuffer if t.tier > 0 =>
|
pb.writeShort(x)
|
||||||
pb.writeTileEntity(t)
|
pb.writeShort(y)
|
||||||
case t: component.Terminal =>
|
|
||||||
pb.writeTileEntity(t.rack)
|
|
||||||
pb.writeInt(t.number)
|
|
||||||
case _ => return
|
|
||||||
}
|
|
||||||
pb.writeInt(x)
|
|
||||||
pb.writeInt(y)
|
|
||||||
pb.writeByte(button.toByte)
|
pb.writeByte(button.toByte)
|
||||||
|
|
||||||
pb.sendToServer()
|
pb.sendToServer()
|
||||||
|
@ -8,7 +8,7 @@ import cpw.mods.fml.relauncher.Side
|
|||||||
import li.cil.oc.client.renderer.block.BlockRenderer
|
import li.cil.oc.client.renderer.block.BlockRenderer
|
||||||
import li.cil.oc.client.renderer.item.UpgradeRenderer
|
import li.cil.oc.client.renderer.item.UpgradeRenderer
|
||||||
import li.cil.oc.client.renderer.tileentity._
|
import li.cil.oc.client.renderer.tileentity._
|
||||||
import li.cil.oc.client.renderer.WirelessNetworkDebugRenderer
|
import li.cil.oc.client.renderer.{TextBufferRenderCache, WirelessNetworkDebugRenderer}
|
||||||
import li.cil.oc.common.{Proxy => CommonProxy, tileentity}
|
import li.cil.oc.common.{Proxy => CommonProxy, tileentity}
|
||||||
import li.cil.oc.{Items, Settings, OpenComputers}
|
import li.cil.oc.{Items, Settings, OpenComputers}
|
||||||
import net.minecraft.client.Minecraft
|
import net.minecraft.client.Minecraft
|
||||||
@ -60,7 +60,7 @@ private[oc] class Proxy extends CommonProxy {
|
|||||||
super.postInit(e)
|
super.postInit(e)
|
||||||
|
|
||||||
TickRegistry.registerTickHandler(HologramRenderer, Side.CLIENT)
|
TickRegistry.registerTickHandler(HologramRenderer, Side.CLIENT)
|
||||||
TickRegistry.registerTickHandler(ScreenRenderer, Side.CLIENT)
|
TickRegistry.registerTickHandler(TextBufferRenderCache, Side.CLIENT)
|
||||||
if (Settings.get.rTreeDebugRenderer) {
|
if (Settings.get.rTreeDebugRenderer) {
|
||||||
MinecraftForge.EVENT_BUS.register(WirelessNetworkDebugRenderer)
|
MinecraftForge.EVENT_BUS.register(WirelessNetworkDebugRenderer)
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package li.cil.oc.client.gui
|
package li.cil.oc.client.gui
|
||||||
|
|
||||||
import li.cil.oc.client.{KeyBindings, PacketSender}
|
import li.cil.oc.client.KeyBindings
|
||||||
import li.cil.oc.client.renderer.MonospaceFontRenderer
|
import li.cil.oc.client.renderer.MonospaceFontRenderer
|
||||||
import li.cil.oc.client.renderer.gui.BufferRenderer
|
import li.cil.oc.client.renderer.gui.BufferRenderer
|
||||||
import li.cil.oc.common.component
|
|
||||||
import li.cil.oc.util.RenderState
|
import li.cil.oc.util.RenderState
|
||||||
import li.cil.oc.util.mods.NEI
|
import li.cil.oc.util.mods.NEI
|
||||||
import net.minecraft.client.Minecraft
|
import net.minecraft.client.Minecraft
|
||||||
@ -11,9 +10,10 @@ import net.minecraft.client.gui.GuiScreen
|
|||||||
import org.lwjgl.input.Keyboard
|
import org.lwjgl.input.Keyboard
|
||||||
import org.lwjgl.opengl.GL11
|
import org.lwjgl.opengl.GL11
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
|
import li.cil.oc.api
|
||||||
|
|
||||||
trait Buffer extends GuiScreen {
|
trait Buffer extends GuiScreen {
|
||||||
protected def buffer: component.Buffer
|
protected def buffer: api.component.Screen
|
||||||
|
|
||||||
private val pressedKeys = mutable.Map.empty[Int, Char]
|
private val pressedKeys = mutable.Map.empty[Int, Char]
|
||||||
|
|
||||||
@ -34,15 +34,13 @@ trait Buffer extends GuiScreen {
|
|||||||
MonospaceFontRenderer.init(Minecraft.getMinecraft.renderEngine)
|
MonospaceFontRenderer.init(Minecraft.getMinecraft.renderEngine)
|
||||||
BufferRenderer.init(Minecraft.getMinecraft.renderEngine)
|
BufferRenderer.init(Minecraft.getMinecraft.renderEngine)
|
||||||
Keyboard.enableRepeatEvents(true)
|
Keyboard.enableRepeatEvents(true)
|
||||||
buffer.owner.currentGui = Some(this)
|
|
||||||
recompileDisplayLists()
|
recompileDisplayLists()
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onGuiClosed() = {
|
override def onGuiClosed() = {
|
||||||
super.onGuiClosed()
|
super.onGuiClosed()
|
||||||
buffer.owner.currentGui = None
|
|
||||||
for ((code, char) <- pressedKeys) {
|
for ((code, char) <- pressedKeys) {
|
||||||
PacketSender.sendKeyUp(buffer, char, code)
|
buffer.keyUp(char, code, null)
|
||||||
}
|
}
|
||||||
Keyboard.enableRepeatEvents(false)
|
Keyboard.enableRepeatEvents(false)
|
||||||
}
|
}
|
||||||
@ -50,11 +48,9 @@ trait Buffer extends GuiScreen {
|
|||||||
protected def drawBufferLayer() {
|
protected def drawBufferLayer() {
|
||||||
if (shouldRecompileDisplayLists) {
|
if (shouldRecompileDisplayLists) {
|
||||||
shouldRecompileDisplayLists = false
|
shouldRecompileDisplayLists = false
|
||||||
val (w, h) = buffer.resolution
|
currentWidth = buffer.getWidth
|
||||||
currentWidth = w
|
currentHeight = buffer.getHeight
|
||||||
currentHeight = h
|
|
||||||
scale = changeSize(currentWidth, currentHeight)
|
scale = changeSize(currentWidth, currentHeight)
|
||||||
BufferRenderer.compileText(scale, buffer.lines, buffer.color, buffer.format)
|
|
||||||
}
|
}
|
||||||
GL11.glPushMatrix()
|
GL11.glPushMatrix()
|
||||||
RenderState.disableLighting()
|
RenderState.disableLighting()
|
||||||
@ -74,17 +70,17 @@ trait Buffer extends GuiScreen {
|
|||||||
if (Keyboard.getEventKeyState) {
|
if (Keyboard.getEventKeyState) {
|
||||||
val char = Keyboard.getEventCharacter
|
val char = Keyboard.getEventCharacter
|
||||||
if (!pressedKeys.contains(code) || !ignoreRepeat(char, code)) {
|
if (!pressedKeys.contains(code) || !ignoreRepeat(char, code)) {
|
||||||
PacketSender.sendKeyDown(buffer, char, code)
|
buffer.keyDown(char, code, null)
|
||||||
pressedKeys += code -> char
|
pressedKeys += code -> char
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else pressedKeys.remove(code) match {
|
else pressedKeys.remove(code) match {
|
||||||
case Some(char) => PacketSender.sendKeyUp(buffer, char, code)
|
case Some(char) => buffer.keyUp(char, code, null)
|
||||||
case _ => // Wasn't pressed while viewing the screen.
|
case _ => // Wasn't pressed while viewing the screen.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Keyboard.isKeyDown(KeyBindings.clipboardPaste.keyCode) && Keyboard.getEventKeyState) {
|
if (Keyboard.isKeyDown(KeyBindings.clipboardPaste.keyCode) && Keyboard.getEventKeyState) {
|
||||||
PacketSender.sendClipboard(buffer, GuiScreen.getClipboardString)
|
buffer.clipboard(GuiScreen.getClipboardString, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,7 +88,7 @@ trait Buffer extends GuiScreen {
|
|||||||
override protected def mouseClicked(x: Int, y: Int, button: Int) {
|
override protected def mouseClicked(x: Int, y: Int, button: Int) {
|
||||||
super.mouseClicked(x, y, button)
|
super.mouseClicked(x, y, button)
|
||||||
if (button == 2) {
|
if (button == 2) {
|
||||||
PacketSender.sendClipboard(buffer, GuiScreen.getClipboardString)
|
buffer.clipboard(GuiScreen.getClipboardString, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,18 +82,18 @@ class Robot(playerInventory: InventoryPlayer, val robot: tileentity.Robot) exten
|
|||||||
GL11.glTranslatef(8, 8, 0)
|
GL11.glTranslatef(8, 8, 0)
|
||||||
RenderState.disableLighting()
|
RenderState.disableLighting()
|
||||||
RenderState.makeItBlend()
|
RenderState.makeItBlend()
|
||||||
val (w, h) = buffer.resolution
|
val scaleX = 48f / buffer.getWidth
|
||||||
val scaleX = 48f / w
|
val scaleY = 14f / buffer.getHeight
|
||||||
val scaleY = 14f / h
|
|
||||||
val scale = math.min(scaleX, scaleY)
|
val scale = math.min(scaleX, scaleY)
|
||||||
if (scaleX > scale) {
|
if (scaleX > scale) {
|
||||||
GL11.glTranslated(MonospaceFontRenderer.fontWidth * w * (scaleX - scale) / 2, 0, 0)
|
GL11.glTranslated(buffer.renderWidth * (scaleX - scale) / 2, 0, 0)
|
||||||
}
|
}
|
||||||
else if (scaleY > scale) {
|
else if (scaleY > scale) {
|
||||||
GL11.glTranslated(0, MonospaceFontRenderer.fontHeight * h * (scaleY - scale) / 2, 0)
|
GL11.glTranslated(0, buffer.renderHeight * (scaleY - scale) / 2, 0)
|
||||||
}
|
}
|
||||||
GL11.glScalef(scale, scale, scale)
|
GL11.glScalef(scale, scale, scale)
|
||||||
BufferRenderer.drawText()
|
GL11.glScaled(this.scale, this.scale, 1)
|
||||||
|
BufferRenderer.drawText(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) {
|
protected override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) {
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
package li.cil.oc.client.gui
|
package li.cil.oc.client.gui
|
||||||
|
|
||||||
import li.cil.oc.client.PacketSender
|
import li.cil.oc.api
|
||||||
import li.cil.oc.client.renderer.MonospaceFontRenderer
|
import li.cil.oc.client.renderer.MonospaceFontRenderer
|
||||||
import li.cil.oc.client.renderer.gui.BufferRenderer
|
import li.cil.oc.client.renderer.gui.BufferRenderer
|
||||||
import li.cil.oc.common
|
|
||||||
import li.cil.oc.util.RenderState
|
import li.cil.oc.util.RenderState
|
||||||
import org.lwjgl.input.Mouse
|
import org.lwjgl.input.Mouse
|
||||||
import org.lwjgl.opengl.GL11
|
import org.lwjgl.opengl.GL11
|
||||||
|
|
||||||
class Screen(val buffer: common.component.Buffer, val hasMouse: Boolean, val hasPower: () => Boolean) extends Buffer {
|
class Screen(val buffer: api.component.Screen, val hasMouse: Boolean, val hasPower: () => Boolean) extends Buffer {
|
||||||
private val bufferMargin = BufferRenderer.margin + BufferRenderer.innerMargin
|
private val bufferMargin = BufferRenderer.margin + BufferRenderer.innerMargin
|
||||||
|
|
||||||
private var didDrag = false
|
private var didDrag = false
|
||||||
@ -24,10 +23,11 @@ class Screen(val buffer: common.component.Buffer, val hasMouse: Boolean, val has
|
|||||||
val mouseY = height - Mouse.getEventY * height / mc.displayHeight - 1
|
val mouseY = height - Mouse.getEventY * height / mc.displayHeight - 1
|
||||||
val bx = (mouseX - x - bufferMargin) / MonospaceFontRenderer.fontWidth + 1
|
val bx = (mouseX - x - bufferMargin) / MonospaceFontRenderer.fontWidth + 1
|
||||||
val by = (mouseY - y - bufferMargin) / MonospaceFontRenderer.fontHeight + 1
|
val by = (mouseY - y - bufferMargin) / MonospaceFontRenderer.fontHeight + 1
|
||||||
val (bw, bh) = buffer.resolution
|
val bw = buffer.getWidth
|
||||||
|
val bh = buffer.getHeight
|
||||||
if (bx > 0 && by > 0 && bx <= bw && by <= bh) {
|
if (bx > 0 && by > 0 && bx <= bw && by <= bh) {
|
||||||
val scroll = math.signum(Mouse.getEventDWheel)
|
val scroll = math.signum(Mouse.getEventDWheel)
|
||||||
PacketSender.sendMouseScroll(buffer, bx, by, scroll)
|
buffer.mouseScroll(bx, by, scroll, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,12 +56,13 @@ class Screen(val buffer: common.component.Buffer, val hasMouse: Boolean, val has
|
|||||||
if (didDrag) {
|
if (didDrag) {
|
||||||
val bx = ((mouseX - x - bufferMargin) / scale / MonospaceFontRenderer.fontWidth).toInt + 1
|
val bx = ((mouseX - x - bufferMargin) / scale / MonospaceFontRenderer.fontWidth).toInt + 1
|
||||||
val by = ((mouseY - y - bufferMargin) / scale / MonospaceFontRenderer.fontHeight).toInt + 1
|
val by = ((mouseY - y - bufferMargin) / scale / MonospaceFontRenderer.fontHeight).toInt + 1
|
||||||
val (bw, bh) = buffer.resolution
|
val bw = buffer.getWidth
|
||||||
|
val bh = buffer.getHeight
|
||||||
if (bx > 0 && by > 0 && bx <= bw && by <= bh) {
|
if (bx > 0 && by > 0 && bx <= bw && by <= bh) {
|
||||||
PacketSender.sendMouseUp(buffer, bx, by, button)
|
buffer.mouseUp(bx, by, button, null)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PacketSender.sendMouseUp(buffer, -1, -1, button)
|
buffer.mouseUp(-1, -1, button, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
didDrag = false
|
didDrag = false
|
||||||
@ -73,10 +74,12 @@ class Screen(val buffer: common.component.Buffer, val hasMouse: Boolean, val has
|
|||||||
private def clickOrDrag(mouseX: Int, mouseY: Int, button: Int) {
|
private def clickOrDrag(mouseX: Int, mouseY: Int, button: Int) {
|
||||||
val bx = ((mouseX - x - bufferMargin) / scale / MonospaceFontRenderer.fontWidth).toInt + 1
|
val bx = ((mouseX - x - bufferMargin) / scale / MonospaceFontRenderer.fontWidth).toInt + 1
|
||||||
val by = ((mouseY - y - bufferMargin) / scale / MonospaceFontRenderer.fontHeight).toInt + 1
|
val by = ((mouseY - y - bufferMargin) / scale / MonospaceFontRenderer.fontHeight).toInt + 1
|
||||||
val (bw, bh) = buffer.resolution
|
val bw = buffer.getWidth
|
||||||
|
val bh = buffer.getHeight
|
||||||
if (bx > 0 && by > 0 && bx <= bw && by <= bh) {
|
if (bx > 0 && by > 0 && bx <= bw && by <= bh) {
|
||||||
if (bx != mx || by != my) {
|
if (bx != mx || by != my) {
|
||||||
PacketSender.sendMouseClick(buffer, bx, by, mx > 0 && my > 0, button)
|
if (mx > 0 && my > 0) buffer.mouseDrag(bx, by, button, null)
|
||||||
|
else buffer.mouseDown(bx, by, button, null)
|
||||||
didDrag = mx > 0 && my > 0
|
didDrag = mx > 0 && my > 0
|
||||||
mx = bx
|
mx = bx
|
||||||
my = by
|
my = by
|
||||||
@ -94,14 +97,15 @@ class Screen(val buffer: common.component.Buffer, val hasMouse: Boolean, val has
|
|||||||
BufferRenderer.drawBackground()
|
BufferRenderer.drawBackground()
|
||||||
if (hasPower()) {
|
if (hasPower()) {
|
||||||
GL11.glTranslatef(bufferMargin, bufferMargin, 0)
|
GL11.glTranslatef(bufferMargin, bufferMargin, 0)
|
||||||
|
GL11.glScaled(scale, scale, 1)
|
||||||
RenderState.makeItBlend()
|
RenderState.makeItBlend()
|
||||||
BufferRenderer.drawText()
|
BufferRenderer.drawText(buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override protected def changeSize(w: Double, h: Double) = {
|
override protected def changeSize(w: Double, h: Double) = {
|
||||||
val bw = w * MonospaceFontRenderer.fontWidth
|
val bw = buffer.renderWidth
|
||||||
val bh = h * MonospaceFontRenderer.fontHeight
|
val bh = buffer.renderHeight
|
||||||
val scaleX = math.min(width / (bw + bufferMargin * 2.0), 1)
|
val scaleX = math.min(width / (bw + bufferMargin * 2.0), 1)
|
||||||
val scaleY = math.min(height / (bh + bufferMargin * 2.0), 1)
|
val scaleY = math.min(height / (bh + bufferMargin * 2.0), 1)
|
||||||
val scale = math.min(scaleX, scaleY)
|
val scale = math.min(scaleX, scaleY)
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
package li.cil.oc.client.renderer
|
||||||
|
|
||||||
|
import com.google.common.cache.{RemovalListener, RemovalNotification, CacheBuilder}
|
||||||
|
import cpw.mods.fml.common.{ITickHandler, TickType}
|
||||||
|
import java.util
|
||||||
|
import java.util.concurrent.{Callable, TimeUnit}
|
||||||
|
import li.cil.oc.common.component.TextBuffer
|
||||||
|
import li.cil.oc.util.RenderState
|
||||||
|
import net.minecraft.client.renderer.GLAllocation
|
||||||
|
import net.minecraft.tileentity.TileEntity
|
||||||
|
import org.lwjgl.opengl.GL11
|
||||||
|
import net.minecraft.client.Minecraft
|
||||||
|
|
||||||
|
object TextBufferRenderCache extends Callable[Int] with RemovalListener[TileEntity, Int] with ITickHandler {
|
||||||
|
val cache = com.google.common.cache.CacheBuilder.newBuilder().
|
||||||
|
expireAfterAccess(2, TimeUnit.SECONDS).
|
||||||
|
removalListener(this).
|
||||||
|
asInstanceOf[CacheBuilder[TextBuffer, Int]].
|
||||||
|
build[TextBuffer, Int]()
|
||||||
|
|
||||||
|
// To allow access in cache entry init.
|
||||||
|
private var currentBuffer: TextBuffer = _
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
// Rendering
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
def render(buffer: TextBuffer) {
|
||||||
|
MonospaceFontRenderer.init(Minecraft.getMinecraft.getTextureManager)
|
||||||
|
currentBuffer = buffer
|
||||||
|
compileOrDraw(cache.get(currentBuffer, this))
|
||||||
|
}
|
||||||
|
|
||||||
|
private def compileOrDraw(list: Int) = if (currentBuffer.proxy.dirty) {
|
||||||
|
val doCompile = !RenderState.compilingDisplayList
|
||||||
|
if (doCompile) {
|
||||||
|
currentBuffer.proxy.dirty = false
|
||||||
|
GL11.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (((line, color), i) <- currentBuffer.data.buffer.zip(currentBuffer.data.color).zipWithIndex) {
|
||||||
|
MonospaceFontRenderer.drawString(0, i * MonospaceFontRenderer.fontHeight, line, color, currentBuffer.data.format)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doCompile) {
|
||||||
|
GL11.glEndList()
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else GL11.glCallList(list)
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
// Cache
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
def call = {
|
||||||
|
val list = GLAllocation.generateDisplayLists(1)
|
||||||
|
currentBuffer.proxy.dirty = true // Force compilation.
|
||||||
|
list
|
||||||
|
}
|
||||||
|
|
||||||
|
def onRemoval(e: RemovalNotification[TileEntity, Int]) {
|
||||||
|
GLAllocation.deleteDisplayLists(e.getValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
// ITickHandler
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
def getLabel = "OpenComputers.TextBufferRenderer"
|
||||||
|
|
||||||
|
def ticks() = util.EnumSet.of(TickType.CLIENT)
|
||||||
|
|
||||||
|
def tickStart(tickType: util.EnumSet[TickType], tickData: AnyRef*) = cache.cleanUp()
|
||||||
|
|
||||||
|
def tickEnd(tickType: util.EnumSet[TickType], tickData: AnyRef*) {}
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
package li.cil.oc.client.renderer.gui
|
package li.cil.oc.client.renderer.gui
|
||||||
|
|
||||||
import li.cil.oc.client.Textures
|
import li.cil.oc.client.Textures
|
||||||
import li.cil.oc.client.renderer.MonospaceFontRenderer
|
import li.cil.oc.util.RenderState
|
||||||
import li.cil.oc.util.{RenderState, PackedColor}
|
|
||||||
import net.minecraft.client.renderer.texture.TextureManager
|
import net.minecraft.client.renderer.texture.TextureManager
|
||||||
import net.minecraft.client.renderer.{Tessellator, GLAllocation}
|
import net.minecraft.client.renderer.{Tessellator, GLAllocation}
|
||||||
import org.lwjgl.opengl.GL11
|
import org.lwjgl.opengl.GL11
|
||||||
|
import li.cil.oc.api.component.Screen
|
||||||
|
|
||||||
object BufferRenderer {
|
object BufferRenderer {
|
||||||
val margin = 7
|
val margin = 7
|
||||||
@ -67,29 +67,17 @@ object BufferRenderer {
|
|||||||
GL11.glEndList()
|
GL11.glEndList()
|
||||||
}
|
}
|
||||||
|
|
||||||
def compileText(scale: Double, lines: Array[Array[Char]], colors: Array[Array[Short]], format: PackedColor.ColorFormat) =
|
|
||||||
if (textureManager.isDefined) {
|
|
||||||
GL11.glNewList(displayLists + 1, GL11.GL_COMPILE)
|
|
||||||
GL11.glPushAttrib(GL11.GL_DEPTH_BUFFER_BIT)
|
|
||||||
GL11.glDepthMask(false)
|
|
||||||
|
|
||||||
GL11.glScaled(scale, scale, 1)
|
|
||||||
lines.zip(colors).zipWithIndex.foreach {
|
|
||||||
case ((line, color), i) => MonospaceFontRenderer.drawString(0, i * MonospaceFontRenderer.fontHeight, line, color, format)
|
|
||||||
}
|
|
||||||
|
|
||||||
GL11.glPopAttrib()
|
|
||||||
GL11.glEndList()
|
|
||||||
}
|
|
||||||
|
|
||||||
def drawBackground() =
|
def drawBackground() =
|
||||||
if (textureManager.isDefined) {
|
if (textureManager.isDefined) {
|
||||||
GL11.glCallList(displayLists)
|
GL11.glCallList(displayLists)
|
||||||
}
|
}
|
||||||
|
|
||||||
def drawText() =
|
def drawText(screen: Screen) =
|
||||||
if (textureManager.isDefined) {
|
if (textureManager.isDefined) {
|
||||||
GL11.glCallList(displayLists + 1)
|
GL11.glPushAttrib(GL11.GL_DEPTH_BUFFER_BIT)
|
||||||
|
GL11.glDepthMask(false)
|
||||||
|
screen.renderText()
|
||||||
|
GL11.glPopAttrib()
|
||||||
}
|
}
|
||||||
|
|
||||||
private def drawBorder(x: Double, y: Double, w: Double, h: Double, u1: Int, v1: Int, u2: Int, v2: Int) = {
|
private def drawBorder(x: Double, y: Double, w: Double, h: Double, u1: Int, v1: Int, u2: Int, v2: Int) = {
|
||||||
|
@ -1,38 +1,25 @@
|
|||||||
package li.cil.oc.client.renderer.tileentity
|
package li.cil.oc.client.renderer.tileentity
|
||||||
|
|
||||||
import com.google.common.cache.{CacheBuilder, RemovalNotification, RemovalListener}
|
|
||||||
import cpw.mods.fml.common.{TickType, ITickHandler}
|
|
||||||
import java.util
|
|
||||||
import java.util.concurrent.{TimeUnit, Callable}
|
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
import li.cil.oc.client.Textures
|
import li.cil.oc.client.Textures
|
||||||
import li.cil.oc.client.renderer.MonospaceFontRenderer
|
|
||||||
import li.cil.oc.common.block
|
import li.cil.oc.common.block
|
||||||
import li.cil.oc.common.tileentity.Screen
|
import li.cil.oc.common.tileentity.Screen
|
||||||
import li.cil.oc.util.RenderState
|
import li.cil.oc.util.RenderState
|
||||||
import li.cil.oc.util.mods.BuildCraft
|
import li.cil.oc.util.mods.BuildCraft
|
||||||
import net.minecraft.client.Minecraft
|
import net.minecraft.client.Minecraft
|
||||||
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
|
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
|
||||||
import net.minecraft.client.renderer.{Tessellator, GLAllocation}
|
import net.minecraft.client.renderer.Tessellator
|
||||||
import net.minecraft.tileentity.TileEntity
|
import net.minecraft.tileentity.TileEntity
|
||||||
import net.minecraftforge.common.ForgeDirection
|
import net.minecraftforge.common.ForgeDirection
|
||||||
import org.lwjgl.opengl.GL11
|
import org.lwjgl.opengl.GL11
|
||||||
|
|
||||||
object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with RemovalListener[TileEntity, Int] with ITickHandler {
|
object ScreenRenderer extends TileEntitySpecialRenderer {
|
||||||
private val maxRenderDistanceSq = Settings.get.maxScreenTextRenderDistance * Settings.get.maxScreenTextRenderDistance
|
private val maxRenderDistanceSq = Settings.get.maxScreenTextRenderDistance * Settings.get.maxScreenTextRenderDistance
|
||||||
|
|
||||||
private val fadeDistanceSq = Settings.get.screenTextFadeStartDistance * Settings.get.screenTextFadeStartDistance
|
private val fadeDistanceSq = Settings.get.screenTextFadeStartDistance * Settings.get.screenTextFadeStartDistance
|
||||||
|
|
||||||
private val fadeRatio = 1.0 / (maxRenderDistanceSq - fadeDistanceSq)
|
private val fadeRatio = 1.0 / (maxRenderDistanceSq - fadeDistanceSq)
|
||||||
|
|
||||||
/** We cache the display lists for the screens we render for performance. */
|
|
||||||
val cache = com.google.common.cache.CacheBuilder.newBuilder().
|
|
||||||
expireAfterAccess(2, TimeUnit.SECONDS).
|
|
||||||
removalListener(this).
|
|
||||||
asInstanceOf[CacheBuilder[Screen, Int]].
|
|
||||||
build[Screen, Int]()
|
|
||||||
|
|
||||||
/** Used to pass the current screen along to call(). */
|
|
||||||
private var screen: Screen = null
|
private var screen: Screen = null
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
@ -72,9 +59,8 @@ object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with
|
|||||||
RenderState.setBlendAlpha(math.max(0, 1 - ((distance - fadeDistanceSq) * fadeRatio).toFloat))
|
RenderState.setBlendAlpha(math.max(0, 1 - ((distance - fadeDistanceSq) * fadeRatio).toFloat))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (screen.hasPower) {
|
if (screen.buffer.isRenderingEnabled) {
|
||||||
MonospaceFontRenderer.init(tileEntityRenderer.renderEngine)
|
compileOrDraw()
|
||||||
compileOrDraw(cache.get(screen, this))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GL11.glPopMatrix()
|
GL11.glPopMatrix()
|
||||||
@ -129,18 +115,12 @@ object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def compileOrDraw(list: Int) = if (screen.bufferIsDirty) {
|
private def compileOrDraw() {
|
||||||
val sx = screen.width
|
val sx = screen.width
|
||||||
val sy = screen.height
|
val sy = screen.height
|
||||||
val tw = sx * 16f
|
val tw = sx * 16f
|
||||||
val th = sy * 16f
|
val th = sy * 16f
|
||||||
|
|
||||||
val doCompile = !RenderState.compilingDisplayList
|
|
||||||
if (doCompile) {
|
|
||||||
screen.bufferIsDirty = false
|
|
||||||
GL11.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE)
|
|
||||||
}
|
|
||||||
|
|
||||||
transform()
|
transform()
|
||||||
|
|
||||||
// Offset from border.
|
// Offset from border.
|
||||||
@ -151,9 +131,8 @@ object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with
|
|||||||
val isy = sy - (4.5f / 16)
|
val isy = sy - (4.5f / 16)
|
||||||
|
|
||||||
// Scale based on actual buffer size.
|
// Scale based on actual buffer size.
|
||||||
val (resX, resY) = screen.buffer.resolution
|
val sizeX = screen.buffer.renderWidth
|
||||||
val sizeX = resX * MonospaceFontRenderer.fontWidth
|
val sizeY = screen.buffer.renderHeight
|
||||||
val sizeY = resY * MonospaceFontRenderer.fontHeight
|
|
||||||
val scaleX = isx / sizeX
|
val scaleX = isx / sizeX
|
||||||
val scaleY = isy / sizeY
|
val scaleY = isy / sizeY
|
||||||
if (true) {
|
if (true) {
|
||||||
@ -174,17 +153,9 @@ object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with
|
|||||||
// Slightly offset the text so it doesn't clip into the screen.
|
// Slightly offset the text so it doesn't clip into the screen.
|
||||||
GL11.glTranslatef(0, 0, 0.01f)
|
GL11.glTranslatef(0, 0, 0.01f)
|
||||||
|
|
||||||
for (((line, color), i) <- screen.buffer.lines.zip(screen.buffer.color).zipWithIndex) {
|
// Render the actual text.
|
||||||
MonospaceFontRenderer.drawString(0, i * MonospaceFontRenderer.fontHeight, line, color, screen.buffer.format)
|
screen.buffer.renderText()
|
||||||
}
|
|
||||||
|
|
||||||
if (doCompile) {
|
|
||||||
GL11.glEndList()
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
else GL11.glCallList(list)
|
|
||||||
|
|
||||||
private def playerDistanceSq() = {
|
private def playerDistanceSq() = {
|
||||||
val player = Minecraft.getMinecraft.thePlayer
|
val player = Minecraft.getMinecraft.thePlayer
|
||||||
@ -230,30 +201,4 @@ object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with
|
|||||||
}
|
}
|
||||||
else 0)
|
else 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
|
||||||
// Cache
|
|
||||||
// ----------------------------------------------------------------------- //
|
|
||||||
|
|
||||||
def call = {
|
|
||||||
val list = GLAllocation.generateDisplayLists(1)
|
|
||||||
screen.bufferIsDirty = true // Force compilation.
|
|
||||||
list
|
|
||||||
}
|
|
||||||
|
|
||||||
def onRemoval(e: RemovalNotification[TileEntity, Int]) {
|
|
||||||
GLAllocation.deleteDisplayLists(e.getValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
|
||||||
// ITickHandler
|
|
||||||
// ----------------------------------------------------------------------- //
|
|
||||||
|
|
||||||
def getLabel = "OpenComputers.Screen"
|
|
||||||
|
|
||||||
def ticks() = util.EnumSet.of(TickType.CLIENT)
|
|
||||||
|
|
||||||
def tickStart(tickType: util.EnumSet[TickType], tickData: AnyRef*) = cache.cleanUp()
|
|
||||||
|
|
||||||
def tickEnd(tickType: util.EnumSet[TickType], tickData: AnyRef*) {}
|
|
||||||
}
|
}
|
23
src/main/scala/li/cil/oc/common/ComponentTracker.scala
Normal file
23
src/main/scala/li/cil/oc/common/ComponentTracker.scala
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package li.cil.oc.common
|
||||||
|
|
||||||
|
import li.cil.oc.api.network.ManagedEnvironment
|
||||||
|
import scala.collection.mutable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keeps track of loaded components by ID. Used to send messages between
|
||||||
|
* component representation on server and client without knowledge of their
|
||||||
|
* containers. For now this is only used for screens / text buffer components.
|
||||||
|
*/
|
||||||
|
abstract class ComponentTracker {
|
||||||
|
private val components = mutable.WeakHashMap.empty[String, ManagedEnvironment]
|
||||||
|
|
||||||
|
def add(address: String, component: ManagedEnvironment) {
|
||||||
|
components += address -> component
|
||||||
|
}
|
||||||
|
|
||||||
|
def remove(address: String) {
|
||||||
|
components -= address
|
||||||
|
}
|
||||||
|
|
||||||
|
def get(address: String): Option[ManagedEnvironment] = components.get(address)
|
||||||
|
}
|
@ -5,6 +5,7 @@ import cpw.mods.fml.common.network.PacketDispatcher
|
|||||||
import cpw.mods.fml.common.network.Player
|
import cpw.mods.fml.common.network.Player
|
||||||
import java.io.{OutputStream, ByteArrayOutputStream, DataOutputStream}
|
import java.io.{OutputStream, ByteArrayOutputStream, DataOutputStream}
|
||||||
import java.util.zip.GZIPOutputStream
|
import java.util.zip.GZIPOutputStream
|
||||||
|
import li.cil.oc.server.component.Container
|
||||||
import net.minecraft.entity.player.EntityPlayerMP
|
import net.minecraft.entity.player.EntityPlayerMP
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.{CompressedStreamTools, NBTTagCompound}
|
import net.minecraft.nbt.{CompressedStreamTools, NBTTagCompound}
|
||||||
@ -39,6 +40,8 @@ abstract class PacketBuilderBase[T <: OutputStream](protected val stream: T) ext
|
|||||||
|
|
||||||
def sendToNearbyPlayers(t: TileEntity, range: Double = 1024): Unit = sendToNearbyPlayers(t.getWorldObj, t.xCoord + 0.5, t.yCoord + 0.5, t.zCoord + 0.5, range)
|
def sendToNearbyPlayers(t: TileEntity, range: Double = 1024): Unit = sendToNearbyPlayers(t.getWorldObj, t.xCoord + 0.5, t.yCoord + 0.5, t.zCoord + 0.5, range)
|
||||||
|
|
||||||
|
def sendToNearbyPlayers(c: Container): Unit = sendToNearbyPlayers(c.world, c.x, c.y, c.z, 1024)
|
||||||
|
|
||||||
def sendToNearbyPlayers(world: World, x: Double, y: Double, z: Double, range: Double) {
|
def sendToNearbyPlayers(world: World, x: Double, y: Double, z: Double, range: Double) {
|
||||||
val dimension = world.provider.dimensionId
|
val dimension = world.provider.dimensionId
|
||||||
val server = FMLCommonHandler.instance.getMinecraftServerInstance
|
val server = FMLCommonHandler.instance.getMinecraftServerInstance
|
||||||
|
@ -25,14 +25,14 @@ object PacketType extends Enumeration {
|
|||||||
RobotXp,
|
RobotXp,
|
||||||
RotatableState,
|
RotatableState,
|
||||||
RouterActivity,
|
RouterActivity,
|
||||||
ScreenColorChange,
|
TextBufferColorChange,
|
||||||
ScreenCopy,
|
TextBufferCopy,
|
||||||
ScreenDepthChange,
|
TextBufferDepthChange,
|
||||||
ScreenFill,
|
TextBufferFill,
|
||||||
ScreenPaletteChange,
|
TextBufferPaletteChange,
|
||||||
ScreenPowerChange,
|
TextBufferPowerChange,
|
||||||
ScreenResolutionChange,
|
TextBufferResolutionChange,
|
||||||
ScreenSet,
|
TextBufferSet,
|
||||||
ServerPresence,
|
ServerPresence,
|
||||||
Sound,
|
Sound,
|
||||||
|
|
||||||
|
@ -10,8 +10,7 @@ import li.cil.oc.api.FileSystem
|
|||||||
import li.cil.oc.common.asm.SimpleComponentTickHandler
|
import li.cil.oc.common.asm.SimpleComponentTickHandler
|
||||||
import li.cil.oc.common.multipart.MultiPart
|
import li.cil.oc.common.multipart.MultiPart
|
||||||
import li.cil.oc.common.recipe.Recipes
|
import li.cil.oc.common.recipe.Recipes
|
||||||
import li.cil.oc.server.component.Keyboard
|
import li.cil.oc.server.component.{Keyboard, machine}
|
||||||
import li.cil.oc.server.component.machine
|
|
||||||
import li.cil.oc.server.component.machine.{LuaJLuaArchitecture, NativeLuaArchitecture}
|
import li.cil.oc.server.component.machine.{LuaJLuaArchitecture, NativeLuaArchitecture}
|
||||||
import li.cil.oc.server.network.WirelessNetwork
|
import li.cil.oc.server.network.WirelessNetwork
|
||||||
import li.cil.oc.server.{TickHandler, driver, fs, network}
|
import li.cil.oc.server.{TickHandler, driver, fs, network}
|
||||||
@ -73,8 +72,10 @@ class Proxy {
|
|||||||
api.Driver.add(driver.item.Loot)
|
api.Driver.add(driver.item.Loot)
|
||||||
api.Driver.add(driver.item.Memory)
|
api.Driver.add(driver.item.Memory)
|
||||||
api.Driver.add(driver.item.NetworkCard)
|
api.Driver.add(driver.item.NetworkCard)
|
||||||
|
api.Driver.add(driver.item.Keyboard)
|
||||||
api.Driver.add(driver.item.Processor)
|
api.Driver.add(driver.item.Processor)
|
||||||
api.Driver.add(driver.item.RedstoneCard)
|
api.Driver.add(driver.item.RedstoneCard)
|
||||||
|
api.Driver.add(driver.item.Screen)
|
||||||
api.Driver.add(driver.item.UpgradeCrafting)
|
api.Driver.add(driver.item.UpgradeCrafting)
|
||||||
api.Driver.add(driver.item.UpgradeGenerator)
|
api.Driver.add(driver.item.UpgradeGenerator)
|
||||||
api.Driver.add(driver.item.UpgradeNavigation)
|
api.Driver.add(driver.item.UpgradeNavigation)
|
||||||
|
@ -1,190 +0,0 @@
|
|||||||
package li.cil.oc.common.component
|
|
||||||
|
|
||||||
import li.cil.oc.api.network.{Message, Node, Visibility}
|
|
||||||
import li.cil.oc.common.tileentity
|
|
||||||
import li.cil.oc.util.ExtendedNBT._
|
|
||||||
import li.cil.oc.util.{PackedColor, TextBuffer}
|
|
||||||
import li.cil.oc.{api, Settings}
|
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
|
||||||
import scala.collection.convert.WrapAsScala._
|
|
||||||
|
|
||||||
class Buffer(val owner: Buffer.Owner) extends api.network.Environment {
|
|
||||||
val node = api.Network.newNode(this, Visibility.Network).
|
|
||||||
withComponent("screen").
|
|
||||||
withConnector().
|
|
||||||
create()
|
|
||||||
|
|
||||||
val buffer = new TextBuffer(maxResolution, PackedColor.Depth.format(maxDepth))
|
|
||||||
|
|
||||||
def maxResolution = Settings.screenResolutionsByTier(owner.tier)
|
|
||||||
|
|
||||||
def maxDepth = Settings.screenDepthsByTier(owner.tier)
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
|
||||||
|
|
||||||
def text = buffer.toString
|
|
||||||
|
|
||||||
def lines = buffer.buffer
|
|
||||||
|
|
||||||
def color = buffer.color
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
|
||||||
|
|
||||||
def format = buffer.format
|
|
||||||
|
|
||||||
def format_=(value: PackedColor.ColorFormat) = {
|
|
||||||
if (value.depth > maxDepth)
|
|
||||||
throw new IllegalArgumentException("unsupported depth")
|
|
||||||
if (buffer.format = value) {
|
|
||||||
owner.onScreenDepthChange(value.depth)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else false
|
|
||||||
}
|
|
||||||
|
|
||||||
def foreground = buffer.foreground
|
|
||||||
|
|
||||||
def foreground_=(value: PackedColor.Color) = {
|
|
||||||
if (buffer.foreground != value) {
|
|
||||||
val result = buffer.foreground
|
|
||||||
buffer.foreground = value
|
|
||||||
owner.onScreenColorChange(foreground, background)
|
|
||||||
result
|
|
||||||
}
|
|
||||||
else value
|
|
||||||
}
|
|
||||||
|
|
||||||
def background = buffer.background
|
|
||||||
|
|
||||||
def background_=(value: PackedColor.Color) = {
|
|
||||||
if (buffer.background != value) {
|
|
||||||
val result = buffer.background
|
|
||||||
buffer.background = value
|
|
||||||
owner.onScreenColorChange(foreground, background)
|
|
||||||
result
|
|
||||||
}
|
|
||||||
else value
|
|
||||||
}
|
|
||||||
|
|
||||||
def getPalette(index: Int) = format match {
|
|
||||||
case palette: PackedColor.MutablePaletteFormat => palette(index)
|
|
||||||
case _ => throw new Exception("palette not available")
|
|
||||||
}
|
|
||||||
|
|
||||||
def setPalette(index: Int, color: Int) = format match {
|
|
||||||
case palette: PackedColor.MutablePaletteFormat =>
|
|
||||||
val result = palette(index)
|
|
||||||
palette(index) = color
|
|
||||||
owner.onScreenPaletteChange(index, color)
|
|
||||||
result
|
|
||||||
case _ => throw new Exception("palette not available")
|
|
||||||
}
|
|
||||||
|
|
||||||
def resolution = buffer.size
|
|
||||||
|
|
||||||
def resolution_=(value: (Int, Int)) = {
|
|
||||||
val (w, h) = value
|
|
||||||
val (mw, mh) = maxResolution
|
|
||||||
if (w < 1 || h < 1 || w > mw || h > mw || h * w > mw * mh)
|
|
||||||
throw new IllegalArgumentException("unsupported resolution")
|
|
||||||
if (buffer.size = value) {
|
|
||||||
if (node != null) {
|
|
||||||
node.sendToReachable("computer.signal", "screen_resized", Int.box(w), Int.box(h))
|
|
||||||
}
|
|
||||||
owner.onScreenResolutionChange(w, h)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else false
|
|
||||||
}
|
|
||||||
|
|
||||||
def get(col: Int, row: Int) = buffer.get(col, row)
|
|
||||||
|
|
||||||
def set(col: Int, row: Int, s: String) = if (col < buffer.width && (col >= 0 || -col < s.length)) {
|
|
||||||
// Make sure the string isn't longer than it needs to be, in particular to
|
|
||||||
// avoid sending too much data to our clients.
|
|
||||||
val (x, truncated) =
|
|
||||||
if (col < 0) (0, s.substring(-col))
|
|
||||||
else (col, s.substring(0, math.min(s.length, buffer.width - col)))
|
|
||||||
if (buffer.set(x, row, truncated))
|
|
||||||
owner.onScreenSet(x, row, truncated)
|
|
||||||
}
|
|
||||||
|
|
||||||
def fill(col: Int, row: Int, w: Int, h: Int, c: Char) =
|
|
||||||
if (buffer.fill(col, row, w, h, c))
|
|
||||||
owner.onScreenFill(col, row, w, h, c)
|
|
||||||
|
|
||||||
def copy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) =
|
|
||||||
if (buffer.copy(col, row, w, h, tx, ty))
|
|
||||||
owner.onScreenCopy(col, row, w, h, tx, ty)
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
|
||||||
|
|
||||||
override def onConnect(node: Node) {}
|
|
||||||
|
|
||||||
override def onDisconnect(node: Node) {}
|
|
||||||
|
|
||||||
override def onMessage(message: Message) {}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
|
||||||
|
|
||||||
// TODO remove compatibility check for older saves in version 1.3 or so.
|
|
||||||
def load(nbt: NBTTagCompound) = {
|
|
||||||
if (nbt.hasKey("node")) node.load(nbt.getCompoundTag("node"))
|
|
||||||
else node.load(nbt.getCompoundTag(Settings.namespace + "node"))
|
|
||||||
if (nbt.hasKey("buffer")) buffer.load(nbt.getCompoundTag("buffer"))
|
|
||||||
else buffer.load(nbt.getCompoundTag(Settings.namespace + "buffer"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Null check for Waila (and other mods that may call this client side).
|
|
||||||
def save(nbt: NBTTagCompound) = if (node != null) {
|
|
||||||
// Happy thread synchronization hack! Here's the problem: GPUs allow direct
|
|
||||||
// calls for modifying screens to give a more responsive experience. This
|
|
||||||
// causes the following problem: when saving, if the screen is saved first,
|
|
||||||
// then the executor runs in parallel and changes the screen *before* the
|
|
||||||
// server thread begins saving that computer, the saved computer will think
|
|
||||||
// it changed the screen, although the saved screen wasn't. To avoid that we
|
|
||||||
// wait for all computers the screen is connected to to finish their current
|
|
||||||
// execution and pausing them (which will make them resume in the next tick
|
|
||||||
// when their update() runs).
|
|
||||||
if (node.network != null) {
|
|
||||||
for (node <- node.reachableNodes) node.host match {
|
|
||||||
case host: tileentity.traits.Computer if !host.isPaused =>
|
|
||||||
host.pause(0.1)
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nbt.setNewCompoundTag(Settings.namespace + "node", node.save)
|
|
||||||
nbt.setNewCompoundTag(Settings.namespace + "buffer", buffer.save)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object Buffer {
|
|
||||||
|
|
||||||
import li.cil.oc.client.gui
|
|
||||||
|
|
||||||
trait Owner {
|
|
||||||
protected var _currentGui: Option[gui.Buffer] = None
|
|
||||||
|
|
||||||
def currentGui = _currentGui
|
|
||||||
|
|
||||||
def currentGui_=(value: Option[gui.Buffer]) = _currentGui = value
|
|
||||||
|
|
||||||
def tier: Int
|
|
||||||
|
|
||||||
def onScreenColorChange(foreground: PackedColor.Color, background: PackedColor.Color)
|
|
||||||
|
|
||||||
def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int)
|
|
||||||
|
|
||||||
def onScreenDepthChange(depth: PackedColor.Depth.Value)
|
|
||||||
|
|
||||||
def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char)
|
|
||||||
|
|
||||||
def onScreenPaletteChange(index: Int, color: Int)
|
|
||||||
|
|
||||||
def onScreenResolutionChange(w: Int, h: Int)
|
|
||||||
|
|
||||||
def onScreenSet(col: Int, row: Int, s: String)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
package li.cil.oc.server.component
|
package li.cil.oc.common.component
|
||||||
|
|
||||||
|
import li.cil.oc.api
|
||||||
import li.cil.oc.api.network.{ManagedEnvironment, Node, Message}
|
import li.cil.oc.api.network.{ManagedEnvironment, Node, Message}
|
||||||
import li.cil.oc.util.ExtendedNBT._
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
@ -21,6 +22,11 @@ abstract class ManagedComponent extends ManagedEnvironment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override def save(nbt: NBTTagCompound) = {
|
override def save(nbt: NBTTagCompound) = {
|
||||||
|
// Force joining a network when saving and we're not in one yet, so that
|
||||||
|
// the address is embedded in the saved data that gets sent to the client,
|
||||||
|
// so that that address can be used to associate components on server and
|
||||||
|
// client (for example keyboard and screen/text buffer).
|
||||||
|
if (node == null) api.Network.joinNewNetwork(node)
|
||||||
if (node != null) nbt.setNewCompoundTag("node", node.save)
|
if (node != null) nbt.setNewCompoundTag("node", node.save)
|
||||||
}
|
}
|
||||||
|
|
@ -1,36 +1,47 @@
|
|||||||
package li.cil.oc.common.component
|
package li.cil.oc.common.component
|
||||||
|
|
||||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||||
import li.cil.oc.api.network.{Node, Visibility}
|
import li.cil.oc.api
|
||||||
|
import li.cil.oc.api.component.{Screen, Keyboard}
|
||||||
|
import li.cil.oc.api.component.Keyboard.UsabilityChecker
|
||||||
|
import li.cil.oc.api.network.{Component, Node, Visibility}
|
||||||
import li.cil.oc.common.item
|
import li.cil.oc.common.item
|
||||||
import li.cil.oc.common.tileentity
|
import li.cil.oc.common.tileentity
|
||||||
import li.cil.oc.server.component
|
|
||||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
|
||||||
import li.cil.oc.util.ExtendedNBT._
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
import li.cil.oc.util.PackedColor.Depth
|
import li.cil.oc.{Items, Settings}
|
||||||
import li.cil.oc.{Items, Settings, common}
|
|
||||||
import net.minecraft.entity.player.EntityPlayer
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
import net.minecraft.nbt.{NBTTagString, NBTTagCompound}
|
import net.minecraft.nbt.{NBTTagString, NBTTagCompound}
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import li.cil.oc.util.PackedColor
|
|
||||||
|
|
||||||
class Terminal(val rack: tileentity.Rack, val number: Int) extends Buffer.Owner {
|
class Terminal(val rack: tileentity.Rack, val number: Int) {
|
||||||
val buffer = new common.component.Buffer(this)
|
val buffer = {
|
||||||
val keyboard = if (buffer.node != null) {
|
val screenItem = api.Items.get("screen1").createItemStack(1)
|
||||||
buffer.node.setVisibility(Visibility.Neighbors)
|
val buffer = api.Driver.driverFor(screenItem).createEnvironment(screenItem, rack).asInstanceOf[Screen]
|
||||||
new component.Keyboard {
|
val (maxWidth, maxHeight) = Settings.screenResolutionsByTier(1)
|
||||||
node.setVisibility(Visibility.Neighbors)
|
buffer.setMaximumResolution(maxWidth, maxHeight)
|
||||||
|
buffer.setMaximumColorDepth(Settings.screenDepthsByTier(1))
|
||||||
|
buffer
|
||||||
|
}
|
||||||
|
|
||||||
override def isUseableByPlayer(p: EntityPlayer) = {
|
val keyboard = {
|
||||||
val stack = p.getCurrentEquippedItem
|
val keyboardItem = api.Items.get("keyboard").createItemStack(1)
|
||||||
|
val keyboard = api.Driver.driverFor(keyboardItem).createEnvironment(keyboardItem, rack).asInstanceOf[Keyboard]
|
||||||
|
keyboard.setUsableOverride(new UsabilityChecker {
|
||||||
|
override def isUsableByPlayer(keyboard: Keyboard, player: EntityPlayer) = {
|
||||||
|
val stack = player.getCurrentEquippedItem
|
||||||
Items.multi.subItem(stack) match {
|
Items.multi.subItem(stack) match {
|
||||||
case Some(t: item.Terminal) if stack.hasTagCompound => keys.contains(stack.getTagCompound.getString(Settings.namespace + "key"))
|
case Some(t: item.Terminal) if stack.hasTagCompound => keys.contains(stack.getTagCompound.getString(Settings.namespace + "key"))
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
keyboard
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer.node != null) {
|
||||||
|
buffer.node.asInstanceOf[Component].setVisibility(Visibility.Neighbors)
|
||||||
|
keyboard.node.asInstanceOf[Component].setVisibility(Visibility.Neighbors)
|
||||||
}
|
}
|
||||||
else null
|
|
||||||
|
|
||||||
val keys = mutable.ListBuffer.empty[String]
|
val keys = mutable.ListBuffer.empty[String]
|
||||||
|
|
||||||
@ -44,8 +55,6 @@ class Terminal(val rack: tileentity.Rack, val number: Int) extends Buffer.Owner
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override def tier = 1
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
def load(nbt: NBTTagCompound) {
|
def load(nbt: NBTTagCompound) {
|
||||||
@ -66,70 +75,12 @@ class Terminal(val rack: tileentity.Rack, val number: Int) extends Buffer.Owner
|
|||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
def readFromNBTForClient(nbt: NBTTagCompound) {
|
def readFromNBTForClient(nbt: NBTTagCompound) {
|
||||||
buffer.buffer.load(nbt)
|
buffer.load(nbt)
|
||||||
nbt.getTagList("keys").foreach[NBTTagString](keys += _.data)
|
nbt.getTagList("keys").foreach[NBTTagString](keys += _.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
def writeToNBTForClient(nbt: NBTTagCompound) {
|
def writeToNBTForClient(nbt: NBTTagCompound) {
|
||||||
buffer.buffer.save(nbt)
|
buffer.save(nbt)
|
||||||
nbt.setNewTagList("keys", keys)
|
nbt.setNewTagList("keys", keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
|
||||||
|
|
||||||
override def onScreenColorChange(foreground: PackedColor.Color, background: PackedColor.Color) {
|
|
||||||
if (isServer) {
|
|
||||||
rack.markAsChanged()
|
|
||||||
ServerPacketSender.sendScreenColorChange(buffer, foreground, background)
|
|
||||||
}
|
|
||||||
else currentGui.foreach(_.recompileDisplayLists())
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
|
|
||||||
if (isServer) {
|
|
||||||
rack.markAsChanged()
|
|
||||||
ServerPacketSender.sendScreenCopy(buffer, col, row, w, h, tx, ty)
|
|
||||||
}
|
|
||||||
else currentGui.foreach(_.recompileDisplayLists())
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenDepthChange(depth: Depth.Value) {
|
|
||||||
if (isServer) {
|
|
||||||
rack.markAsChanged()
|
|
||||||
ServerPacketSender.sendScreenDepthChange(buffer, depth)
|
|
||||||
}
|
|
||||||
else currentGui.foreach(_.recompileDisplayLists())
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
|
|
||||||
if (isServer) {
|
|
||||||
rack.markAsChanged()
|
|
||||||
ServerPacketSender.sendScreenFill(buffer, col, row, w, h, c)
|
|
||||||
}
|
|
||||||
else currentGui.foreach(_.recompileDisplayLists())
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenPaletteChange(index: Int, color: Int) {
|
|
||||||
if (isServer) {
|
|
||||||
rack.markAsChanged()
|
|
||||||
ServerPacketSender.sendScreenPaletteChange(buffer, index, color)
|
|
||||||
}
|
|
||||||
else currentGui.foreach(_.recompileDisplayLists())
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenResolutionChange(w: Int, h: Int) {
|
|
||||||
if (isServer) {
|
|
||||||
rack.markAsChanged()
|
|
||||||
ServerPacketSender.sendScreenResolutionChange(buffer, w, h)
|
|
||||||
}
|
|
||||||
else currentGui.foreach(_.recompileDisplayLists())
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenSet(col: Int, row: Int, s: String) {
|
|
||||||
if (isServer) {
|
|
||||||
rack.markAsChanged()
|
|
||||||
ServerPacketSender.sendScreenSet(buffer, col, row, s)
|
|
||||||
}
|
|
||||||
else currentGui.foreach(_.recompileDisplayLists())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
489
src/main/scala/li/cil/oc/common/component/TextBuffer.scala
Normal file
489
src/main/scala/li/cil/oc/common/component/TextBuffer.scala
Normal file
@ -0,0 +1,489 @@
|
|||||||
|
package li.cil.oc.common.component
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.FMLCommonHandler
|
||||||
|
import cpw.mods.fml.relauncher.{SideOnly, Side}
|
||||||
|
import li.cil.oc.{api, Settings}
|
||||||
|
import li.cil.oc.api.component.Screen.ColorDepth
|
||||||
|
import li.cil.oc.api.network._
|
||||||
|
import li.cil.oc.client.{PacketSender => ClientPacketSender, ComponentTracker => ClientComponentTracker}
|
||||||
|
import li.cil.oc.client.renderer.{MonospaceFontRenderer, TextBufferRenderCache}
|
||||||
|
import li.cil.oc.common.tileentity
|
||||||
|
import li.cil.oc.server.{PacketSender => ServerPacketSender, ComponentTracker => ServerComponentTracker, component}
|
||||||
|
import li.cil.oc.util
|
||||||
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
|
import li.cil.oc.util.PackedColor
|
||||||
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
import scala.collection.convert.WrapAsScala._
|
||||||
|
|
||||||
|
class TextBuffer(val owner: component.Container) extends ManagedComponent with api.component.Screen {
|
||||||
|
val node = api.Network.newNode(this, Visibility.Network).
|
||||||
|
withComponent("screen").
|
||||||
|
withConnector().
|
||||||
|
create()
|
||||||
|
|
||||||
|
private var maxResolution = Settings.screenResolutionsByTier(0)
|
||||||
|
|
||||||
|
private var maxDepth = Settings.screenDepthsByTier(0)
|
||||||
|
|
||||||
|
private var aspectRatio = (1.0, 1.0)
|
||||||
|
|
||||||
|
private var powerConsumptionPerTick = Settings.get.screenCost
|
||||||
|
|
||||||
|
// For client side only.
|
||||||
|
private var isRendering = true
|
||||||
|
|
||||||
|
private var isDisplaying = true
|
||||||
|
|
||||||
|
private var hasPower = true
|
||||||
|
|
||||||
|
private var relativeLitArea = -1.0
|
||||||
|
|
||||||
|
var fullyLitCost = computeFullyLitCost()
|
||||||
|
|
||||||
|
// This computes the energy cost (per tick) to keep the screen running if
|
||||||
|
// every single "pixel" is lit. This cost increases with higher tiers as
|
||||||
|
// their maximum resolution (pixel density) increases. For a basic screen
|
||||||
|
// this is simply the configured cost.
|
||||||
|
def computeFullyLitCost() = {
|
||||||
|
val (w, h) = Settings.screenResolutionsByTier(0)
|
||||||
|
val mw = getMaximumWidth
|
||||||
|
val mh = getMaximumHeight
|
||||||
|
powerConsumptionPerTick * (mw * mh) / (w * h)
|
||||||
|
}
|
||||||
|
|
||||||
|
val proxy =
|
||||||
|
if (FMLCommonHandler.instance.getEffectiveSide.isClient) new TextBuffer.ClientProxy(this)
|
||||||
|
else new TextBuffer.ServerProxy(this)
|
||||||
|
|
||||||
|
val data = new util.TextBuffer(maxResolution, PackedColor.Depth.format(maxDepth))
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
override val canUpdate = true
|
||||||
|
|
||||||
|
override def update() {
|
||||||
|
super.update()
|
||||||
|
if (isDisplaying && owner.world.getWorldTime % Settings.get.tickFrequency == 0) {
|
||||||
|
if (relativeLitArea < 0) {
|
||||||
|
// The relative lit area is the number of pixels that are not blank
|
||||||
|
// versus the number of pixels in the *current* resolution. This is
|
||||||
|
// scaled to multi-block screens, since we only compute this for the
|
||||||
|
// origin.
|
||||||
|
val w = getWidth
|
||||||
|
val h = getHeight
|
||||||
|
relativeLitArea = data.buffer.foldLeft(0) {
|
||||||
|
(acc, line) => acc + line.count(' ' !=)
|
||||||
|
} / (w * h).toDouble
|
||||||
|
}
|
||||||
|
val hadPower = hasPower
|
||||||
|
val neededPower = relativeLitArea * fullyLitCost * Settings.get.tickFrequency
|
||||||
|
hasPower = node.tryChangeBuffer(-neededPower)
|
||||||
|
if (hasPower != hadPower) {
|
||||||
|
ServerPacketSender.sendTextBufferPowerChange(node.address, isDisplaying && hasPower, owner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
@Callback(doc = """function():boolean -- Returns whether the screen is currently on.""")
|
||||||
|
def isOn(computer: Context, args: Arguments): Array[AnyRef] = result(isDisplaying)
|
||||||
|
|
||||||
|
@Callback(doc = """function():boolean -- Turns the screen on. Returns true if it was off.""")
|
||||||
|
def turnOn(computer: Context, args: Arguments): Array[AnyRef] = {
|
||||||
|
val oldPowerState = isDisplaying
|
||||||
|
setPowerState(value = true)
|
||||||
|
result(isDisplaying != oldPowerState, isDisplaying)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(doc = """function():boolean -- Turns off the screen. Returns true if it was on.""")
|
||||||
|
def turnOff(computer: Context, args: Arguments): Array[AnyRef] = {
|
||||||
|
val oldPowerState = isDisplaying
|
||||||
|
setPowerState(value = false)
|
||||||
|
result(isDisplaying != oldPowerState, isDisplaying)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(doc = """function():number, number -- The aspect ratio of the screen. For multi-block screens this is the number of blocks, horizontal and vertical.""")
|
||||||
|
def getAspectRatio(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
|
result(aspectRatio._1, aspectRatio._2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
override def setEnergyCostPerTick(value: Double) {
|
||||||
|
powerConsumptionPerTick = value
|
||||||
|
fullyLitCost = computeFullyLitCost()
|
||||||
|
}
|
||||||
|
|
||||||
|
override def getEnergyCostPerTick = powerConsumptionPerTick
|
||||||
|
|
||||||
|
override def setPowerState(value: Boolean) {
|
||||||
|
if (isDisplaying != value) {
|
||||||
|
isDisplaying = value
|
||||||
|
if (isDisplaying) {
|
||||||
|
val neededPower = fullyLitCost * Settings.get.tickFrequency
|
||||||
|
hasPower = node.changeBuffer(-neededPower) == 0
|
||||||
|
}
|
||||||
|
ServerPacketSender.sendTextBufferPowerChange(node.address, isDisplaying && hasPower, owner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def getPowerState = isDisplaying
|
||||||
|
|
||||||
|
override def setMaximumResolution(width: Int, height: Int) {
|
||||||
|
if (width < 1) throw new IllegalArgumentException("width must be larger or equal to one")
|
||||||
|
if (height < 1) throw new IllegalArgumentException("height must be larger or equal to one")
|
||||||
|
maxResolution = (width, height)
|
||||||
|
fullyLitCost = computeFullyLitCost()
|
||||||
|
}
|
||||||
|
|
||||||
|
override def getMaximumWidth = maxResolution._1
|
||||||
|
|
||||||
|
override def getMaximumHeight = maxResolution._2
|
||||||
|
|
||||||
|
override def setAspectRatio(width: Double, height: Double) = aspectRatio = (width, height)
|
||||||
|
|
||||||
|
override def getAspectRatio = aspectRatio._1 / aspectRatio._2
|
||||||
|
|
||||||
|
override def setResolution(w: Int, h: Int) = {
|
||||||
|
val (mw, mh) = maxResolution
|
||||||
|
if (w < 1 || h < 1 || w > mw || h > mw || h * w > mw * mh)
|
||||||
|
throw new IllegalArgumentException("unsupported resolution")
|
||||||
|
if (data.size = (w, h)) {
|
||||||
|
if (node != null) {
|
||||||
|
node.sendToReachable("computer.signal", "screen_resized", Int.box(w), Int.box(h))
|
||||||
|
}
|
||||||
|
proxy.onScreenResolutionChange(w, h)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else false
|
||||||
|
}
|
||||||
|
|
||||||
|
override def getWidth = data.width
|
||||||
|
|
||||||
|
override def getHeight = data.height
|
||||||
|
|
||||||
|
override def setMaximumColorDepth(depth: ColorDepth) = maxDepth = depth
|
||||||
|
|
||||||
|
override def getMaximumColorDepth = maxDepth
|
||||||
|
|
||||||
|
override def setColorDepth(depth: ColorDepth) = {
|
||||||
|
if (depth.ordinal > maxDepth.ordinal)
|
||||||
|
throw new IllegalArgumentException("unsupported depth")
|
||||||
|
if (data.format = PackedColor.Depth.format(depth)) {
|
||||||
|
proxy.onScreenDepthChange(depth)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else false
|
||||||
|
}
|
||||||
|
|
||||||
|
override def getColorDepth = data.format.depth
|
||||||
|
|
||||||
|
override def setPaletteColor(index: Int, color: Int) = data.format match {
|
||||||
|
case palette: PackedColor.MutablePaletteFormat =>
|
||||||
|
palette(index) = color
|
||||||
|
proxy.onScreenPaletteChange(index)
|
||||||
|
case _ => throw new Exception("palette not available")
|
||||||
|
}
|
||||||
|
|
||||||
|
override def getPaletteColor(index: Int) = data.format match {
|
||||||
|
case palette: PackedColor.MutablePaletteFormat => palette(index)
|
||||||
|
case _ => throw new Exception("palette not available")
|
||||||
|
}
|
||||||
|
|
||||||
|
override def setForegroundColor(color: Int) = setForegroundColor(color, isFromPalette = false)
|
||||||
|
|
||||||
|
override def setForegroundColor(color: Int, isFromPalette: Boolean) {
|
||||||
|
val value = PackedColor.Color(color, isFromPalette)
|
||||||
|
if (data.foreground != value) {
|
||||||
|
data.foreground = value
|
||||||
|
proxy.onScreenColorChange()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def getForegroundColor = data.foreground.value
|
||||||
|
|
||||||
|
override def isForegroundFromPalette = data.foreground.isPalette
|
||||||
|
|
||||||
|
override def setBackgroundColor(color: Int) = setBackgroundColor(color, isFromPalette = false)
|
||||||
|
|
||||||
|
override def setBackgroundColor(color: Int, isFromPalette: Boolean) {
|
||||||
|
val value = PackedColor.Color(color, isFromPalette)
|
||||||
|
if (data.background != value) {
|
||||||
|
data.background = value
|
||||||
|
proxy.onScreenColorChange()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def getBackgroundColor = data.background.value
|
||||||
|
|
||||||
|
override def isBackgroundFromPalette = data.background.isPalette
|
||||||
|
|
||||||
|
def copy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) =
|
||||||
|
if (data.copy(col, row, w, h, tx, ty))
|
||||||
|
proxy.onScreenCopy(col, row, w, h, tx, ty)
|
||||||
|
|
||||||
|
def fill(col: Int, row: Int, w: Int, h: Int, c: Char) =
|
||||||
|
if (data.fill(col, row, w, h, c))
|
||||||
|
proxy.onScreenFill(col, row, w, h, c)
|
||||||
|
|
||||||
|
def set(col: Int, row: Int, s: String) = if (col < data.width && (col >= 0 || -col < s.length)) {
|
||||||
|
// Make sure the string isn't longer than it needs to be, in particular to
|
||||||
|
// avoid sending too much data to our clients.
|
||||||
|
val (x, truncated) =
|
||||||
|
if (col < 0) (0, s.substring(-col))
|
||||||
|
else (col, s.substring(0, math.min(s.length, data.width - col)))
|
||||||
|
if (data.set(x, row, truncated))
|
||||||
|
proxy.onScreenSet(x, row, truncated)
|
||||||
|
}
|
||||||
|
|
||||||
|
def get(col: Int, row: Int) = data.get(col, row)
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
override def renderText() = proxy.render()
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
override def renderWidth = MonospaceFontRenderer.fontWidth * data.width
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
override def renderHeight = MonospaceFontRenderer.fontHeight * data.height
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
override def setRenderingEnabled(enabled: Boolean) = isRendering = enabled
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
override def isRenderingEnabled = isRendering
|
||||||
|
|
||||||
|
override def keyDown(character: Char, code: Int, player: EntityPlayer) =
|
||||||
|
proxy.keyDown(character, code, player)
|
||||||
|
|
||||||
|
override def keyUp(character: Char, code: Int, player: EntityPlayer) =
|
||||||
|
proxy.keyUp(character, code, player)
|
||||||
|
|
||||||
|
override def clipboard(value: String, player: EntityPlayer) =
|
||||||
|
proxy.clipboard(value, player)
|
||||||
|
|
||||||
|
override def mouseDown(x: Int, y: Int, button: Int, player: EntityPlayer) =
|
||||||
|
proxy.mouseDown(x, y, button, player)
|
||||||
|
|
||||||
|
override def mouseDrag(x: Int, y: Int, button: Int, player: EntityPlayer) =
|
||||||
|
proxy.mouseDrag(x, y, button, player)
|
||||||
|
|
||||||
|
override def mouseUp(x: Int, y: Int, button: Int, player: EntityPlayer) =
|
||||||
|
proxy.mouseUp(x, y, button, player)
|
||||||
|
|
||||||
|
override def mouseScroll(x: Int, y: Int, delta: Int, player: EntityPlayer) =
|
||||||
|
proxy.mouseScroll(x, y, delta, player)
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
override def onConnect(node: Node) {
|
||||||
|
super.onConnect(node)
|
||||||
|
if (node == this.node) {
|
||||||
|
ServerComponentTracker.add(node.address, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def onDisconnect(node: Node) {
|
||||||
|
super.onDisconnect(node)
|
||||||
|
if (node == this.node) {
|
||||||
|
ServerComponentTracker.remove(node.address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
override def load(nbt: NBTTagCompound) = {
|
||||||
|
super.load(nbt)
|
||||||
|
data.load(nbt.getCompoundTag("buffer"))
|
||||||
|
if (FMLCommonHandler.instance.getEffectiveSide.isClient) {
|
||||||
|
proxy.nodeAddress = nbt.getCompoundTag("node").getString("address")
|
||||||
|
ClientComponentTracker.add(proxy.nodeAddress, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nbt.hasKey(Settings.namespace + "isOn")) {
|
||||||
|
isDisplaying = nbt.getBoolean(Settings.namespace + "isOn")
|
||||||
|
}
|
||||||
|
if (nbt.hasKey(Settings.namespace + "hasPower")) {
|
||||||
|
hasPower = nbt.getBoolean(Settings.namespace + "hasPower")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Null check for Waila (and other mods that may call this client side).
|
||||||
|
override def save(nbt: NBTTagCompound) = if (node != null) {
|
||||||
|
super.save(nbt)
|
||||||
|
// Happy thread synchronization hack! Here's the problem: GPUs allow direct
|
||||||
|
// calls for modifying screens to give a more responsive experience. This
|
||||||
|
// causes the following problem: when saving, if the screen is saved first,
|
||||||
|
// then the executor runs in parallel and changes the screen *before* the
|
||||||
|
// server thread begins saving that computer, the saved computer will think
|
||||||
|
// it changed the screen, although the saved screen wasn't. To avoid that we
|
||||||
|
// wait for all computers the screen is connected to to finish their current
|
||||||
|
// execution and pausing them (which will make them resume in the next tick
|
||||||
|
// when their update() runs).
|
||||||
|
if (node.network != null) {
|
||||||
|
for (node <- node.reachableNodes) node.host match {
|
||||||
|
case host: tileentity.traits.Computer if !host.isPaused =>
|
||||||
|
host.pause(0.1)
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nbt.setNewCompoundTag("buffer", data.save)
|
||||||
|
nbt.setBoolean(Settings.namespace + "isOn", isDisplaying)
|
||||||
|
nbt.setBoolean(Settings.namespace + "hasPower", hasPower)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object TextBuffer {
|
||||||
|
|
||||||
|
abstract class Proxy {
|
||||||
|
var dirty = false
|
||||||
|
|
||||||
|
var nodeAddress = ""
|
||||||
|
|
||||||
|
def render() {}
|
||||||
|
|
||||||
|
def onScreenColorChange()
|
||||||
|
|
||||||
|
def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int)
|
||||||
|
|
||||||
|
def onScreenDepthChange(depth: ColorDepth)
|
||||||
|
|
||||||
|
def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char)
|
||||||
|
|
||||||
|
def onScreenPaletteChange(index: Int)
|
||||||
|
|
||||||
|
def onScreenResolutionChange(w: Int, h: Int)
|
||||||
|
|
||||||
|
def onScreenSet(col: Int, row: Int, s: String)
|
||||||
|
|
||||||
|
def keyDown(character: Char, code: Int, player: EntityPlayer)
|
||||||
|
|
||||||
|
def keyUp(character: Char, code: Int, player: EntityPlayer)
|
||||||
|
|
||||||
|
def clipboard(value: String, player: EntityPlayer)
|
||||||
|
|
||||||
|
def mouseDown(x: Int, y: Int, button: Int, player: EntityPlayer)
|
||||||
|
|
||||||
|
def mouseDrag(x: Int, y: Int, button: Int, player: EntityPlayer)
|
||||||
|
|
||||||
|
def mouseUp(x: Int, y: Int, button: Int, player: EntityPlayer)
|
||||||
|
|
||||||
|
def mouseScroll(x: Int, y: Int, delta: Int, player: EntityPlayer)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClientProxy(val owner: TextBuffer) extends Proxy {
|
||||||
|
override def render() = TextBufferRenderCache.render(owner)
|
||||||
|
|
||||||
|
override def onScreenColorChange() = dirty = true
|
||||||
|
|
||||||
|
override def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) = dirty = true
|
||||||
|
|
||||||
|
override def onScreenDepthChange(depth: ColorDepth) = dirty = true
|
||||||
|
|
||||||
|
override def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) = dirty = true
|
||||||
|
|
||||||
|
override def onScreenPaletteChange(index: Int) = dirty = true
|
||||||
|
|
||||||
|
override def onScreenResolutionChange(w: Int, h: Int) = dirty = true
|
||||||
|
|
||||||
|
override def onScreenSet(col: Int, row: Int, s: String) = dirty = true
|
||||||
|
|
||||||
|
override def keyDown(character: Char, code: Int, player: EntityPlayer) =
|
||||||
|
ClientPacketSender.sendKeyDown(nodeAddress, character, code)
|
||||||
|
|
||||||
|
override def keyUp(character: Char, code: Int, player: EntityPlayer) =
|
||||||
|
ClientPacketSender.sendKeyUp(nodeAddress, character, code)
|
||||||
|
|
||||||
|
override def clipboard(value: String, player: EntityPlayer) =
|
||||||
|
ClientPacketSender.sendClipboard(nodeAddress, value)
|
||||||
|
|
||||||
|
override def mouseDown(x: Int, y: Int, button: Int, player: EntityPlayer) =
|
||||||
|
ClientPacketSender.sendMouseClick(nodeAddress, x, y, drag = false, button)
|
||||||
|
|
||||||
|
override def mouseDrag(x: Int, y: Int, button: Int, player: EntityPlayer) =
|
||||||
|
ClientPacketSender.sendMouseClick(nodeAddress, x, y, drag = true, button)
|
||||||
|
|
||||||
|
override def mouseUp(x: Int, y: Int, button: Int, player: EntityPlayer) =
|
||||||
|
ClientPacketSender.sendMouseUp(nodeAddress, x, y, button)
|
||||||
|
|
||||||
|
override def mouseScroll(x: Int, y: Int, delta: Int, player: EntityPlayer) =
|
||||||
|
ClientPacketSender.sendMouseScroll(nodeAddress, x, y, delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ServerProxy(val buffer: TextBuffer) extends Proxy {
|
||||||
|
override def onScreenColorChange() {
|
||||||
|
buffer.owner.markChanged()
|
||||||
|
ServerPacketSender.sendTextBufferColorChange(buffer.node.address, buffer.data.foreground, buffer.data.background, buffer.owner)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
|
||||||
|
buffer.relativeLitArea = -1
|
||||||
|
buffer.owner.markChanged()
|
||||||
|
ServerPacketSender.sendTextBufferCopy(buffer.node.address, col, row, w, h, tx, ty, buffer.owner)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def onScreenDepthChange(depth: ColorDepth) {
|
||||||
|
buffer.owner.markChanged()
|
||||||
|
ServerPacketSender.sendTextBufferDepthChange(buffer.node.address, depth, buffer.owner)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
|
||||||
|
buffer.relativeLitArea = -1
|
||||||
|
buffer.owner.markChanged()
|
||||||
|
ServerPacketSender.sendTextBufferFill(buffer.node.address, col, row, w, h, c, buffer.owner)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def onScreenPaletteChange(index: Int) {
|
||||||
|
buffer.owner.markChanged()
|
||||||
|
ServerPacketSender.sendTextBufferPaletteChange(buffer.node.address, index, buffer.getPaletteColor(index), buffer.owner)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def onScreenResolutionChange(w: Int, h: Int) {
|
||||||
|
buffer.relativeLitArea = -1
|
||||||
|
buffer.owner.markChanged()
|
||||||
|
ServerPacketSender.sendTextBufferResolutionChange(buffer.node.address, w, h, buffer.owner)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def onScreenSet(col: Int, row: Int, s: String) {
|
||||||
|
buffer.relativeLitArea = -1
|
||||||
|
buffer.owner.markChanged()
|
||||||
|
ServerPacketSender.sendTextBufferSet(buffer.node.address, col, row, s, buffer.owner)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def keyDown(character: Char, code: Int, player: EntityPlayer) {
|
||||||
|
buffer.node.sendToVisible("keyboard.keyDown", player, Char.box(character), Int.box(code))
|
||||||
|
}
|
||||||
|
|
||||||
|
override def keyUp(character: Char, code: Int, player: EntityPlayer) {
|
||||||
|
buffer.node.sendToVisible("keyboard.keyUp", player, Char.box(character), Int.box(code))
|
||||||
|
}
|
||||||
|
|
||||||
|
override def clipboard(value: String, player: EntityPlayer) {
|
||||||
|
buffer.node.sendToVisible("keyboard.clipboard", player, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def mouseDown(x: Int, y: Int, button: Int, player: EntityPlayer) {
|
||||||
|
if (Settings.get.inputUsername) buffer.node.sendToReachable("computer.checked_signal", player, "touch", Int.box(x), Int.box(y), Int.box(button), player.getCommandSenderName)
|
||||||
|
else buffer.node.sendToReachable("computer.checked_signal", player, "touch", Int.box(x), Int.box(y), Int.box(button))
|
||||||
|
}
|
||||||
|
|
||||||
|
override def mouseDrag(x: Int, y: Int, button: Int, player: EntityPlayer) {
|
||||||
|
if (Settings.get.inputUsername) buffer.node.sendToReachable("computer.checked_signal", player, "drag", Int.box(x), Int.box(y), Int.box(button), player.getCommandSenderName)
|
||||||
|
else buffer.node.sendToReachable("computer.checked_signal", player, "drag", Int.box(x), Int.box(y), Int.box(button))
|
||||||
|
}
|
||||||
|
|
||||||
|
override def mouseUp(x: Int, y: Int, button: Int, player: EntityPlayer) {
|
||||||
|
if (Settings.get.inputUsername) buffer.node.sendToReachable("computer.checked_signal", player, "drop", Int.box(x), Int.box(y), Int.box(button), player.getCommandSenderName)
|
||||||
|
else buffer.node.sendToReachable("computer.checked_signal", player, "drop", Int.box(x), Int.box(y), Int.box(button))
|
||||||
|
}
|
||||||
|
|
||||||
|
override def mouseScroll(x: Int, y: Int, delta: Int, player: EntityPlayer) {
|
||||||
|
if (Settings.get.inputUsername) buffer.node.sendToReachable("computer.checked_signal", player, "scroll", Int.box(x), Int.box(y), Int.box(delta), player.getCommandSenderName)
|
||||||
|
else buffer.node.sendToReachable("computer.checked_signal", player, "scroll", Int.box(x), Int.box(y), Int.box(delta))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,8 +2,8 @@ package li.cil.oc.common.tileentity
|
|||||||
|
|
||||||
import cpw.mods.fml.relauncher.{SideOnly, Side}
|
import cpw.mods.fml.relauncher.{SideOnly, Side}
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
|
import li.cil.oc.api
|
||||||
import li.cil.oc.api.network.{Analyzable, SidedEnvironment}
|
import li.cil.oc.api.network.{Analyzable, SidedEnvironment}
|
||||||
import li.cil.oc.server.component
|
|
||||||
import li.cil.oc.util.ExtendedNBT._
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
import net.minecraft.entity.player.EntityPlayer
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
@ -14,14 +14,12 @@ class Keyboard(isRemote: Boolean) extends traits.Environment with traits.Rotatab
|
|||||||
|
|
||||||
override def validFacings = ForgeDirection.VALID_DIRECTIONS
|
override def validFacings = ForgeDirection.VALID_DIRECTIONS
|
||||||
|
|
||||||
val keyboard = if (isRemote) null
|
val keyboard = {
|
||||||
else new component.Keyboard {
|
val keyboardItem = api.Items.get("keyboard").createItemStack(1)
|
||||||
override def isUseableByPlayer(p: EntityPlayer) =
|
api.Driver.driverFor(keyboardItem).createEnvironment(keyboardItem, this)
|
||||||
world.getBlockTileEntity(x, y, z) == Keyboard.this &&
|
|
||||||
p.getDistanceSq(x + 0.5, y + 0.5, z + 0.5) <= 64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override def node = if (isClient) null else keyboard.node
|
override def node = keyboard.node
|
||||||
|
|
||||||
def hasNodeOnSide(side: ForgeDirection) =
|
def hasNodeOnSide(side: ForgeDirection) =
|
||||||
side == facing.getOpposite || side == forward || (isOnWall && side == forward.getOpposite)
|
side == facing.getOpposite || side == forward || (isOnWall && side == forward.getOpposite)
|
||||||
|
@ -6,10 +6,10 @@ import li.cil.oc._
|
|||||||
import li.cil.oc.api.Driver
|
import li.cil.oc.api.Driver
|
||||||
import li.cil.oc.api.driver.Slot
|
import li.cil.oc.api.driver.Slot
|
||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
|
import li.cil.oc.client.gui
|
||||||
import li.cil.oc.common.block.Delegator
|
import li.cil.oc.common.block.Delegator
|
||||||
import li.cil.oc.server.component.GraphicsCard
|
import li.cil.oc.server.component.{GraphicsCard, robot}
|
||||||
import li.cil.oc.server.component.robot
|
import li.cil.oc.server.{PacketSender => ServerPacketSender, driver}
|
||||||
import li.cil.oc.server.{PacketSender => ServerPacketSender, driver, component}
|
|
||||||
import li.cil.oc.util.ExtendedNBT._
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
import net.minecraft.block.{BlockFlowing, Block}
|
import net.minecraft.block.{BlockFlowing, Block}
|
||||||
import net.minecraft.client.Minecraft
|
import net.minecraft.client.Minecraft
|
||||||
@ -71,22 +71,22 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
|||||||
|
|
||||||
override def node = if (isServer) computer.node else null
|
override def node = if (isServer) computer.node else null
|
||||||
|
|
||||||
override val _buffer = new common.component.Buffer(this) {
|
override def tier: Int = 0
|
||||||
override def maxResolution = (48, 14)
|
|
||||||
}
|
buffer.setMaximumResolution(48, 14)
|
||||||
val (bot, gpu, keyboard) = if (isServer) {
|
val (bot, gpu) = if (isServer) {
|
||||||
val bot = new robot.Robot(this)
|
val bot = new robot.Robot(this)
|
||||||
val gpu = new GraphicsCard.Tier1 {
|
val gpu = new GraphicsCard.Tier1 {
|
||||||
override val maxResolution = (48, 14)
|
override val maxResolution = (48, 14)
|
||||||
}
|
}
|
||||||
val keyboard = new component.Keyboard {
|
(bot, gpu)
|
||||||
override def isUseableByPlayer(p: EntityPlayer) =
|
}
|
||||||
world.getBlockTileEntity(x, y, z) == proxy &&
|
else (null, null)
|
||||||
p.getDistanceSq(x + 0.5, y + 0.5, z + 0.5) <= 64
|
|
||||||
}
|
lazy val keyboard = {
|
||||||
(bot, gpu, keyboard)
|
val keyboardItem = api.Items.get("keyboard").createItemStack(1)
|
||||||
|
api.Driver.driverFor(keyboardItem).createEnvironment(keyboardItem, this)
|
||||||
}
|
}
|
||||||
else (null, null, null)
|
|
||||||
|
|
||||||
var owner = "OpenComputers"
|
var owner = "OpenComputers"
|
||||||
|
|
||||||
@ -352,8 +352,10 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
|||||||
|
|
||||||
override protected def dispose() {
|
override protected def dispose() {
|
||||||
super.dispose()
|
super.dispose()
|
||||||
if (currentGui.isDefined) {
|
Minecraft.getMinecraft.currentScreen match {
|
||||||
Minecraft.getMinecraft.displayGuiScreen(null)
|
case robotGui: gui.Robot if robotGui.robot == this =>
|
||||||
|
Minecraft.getMinecraft.displayGuiScreen(null)
|
||||||
|
case _ =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,16 +566,8 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
|||||||
case _ => 0
|
case _ => 0
|
||||||
})
|
})
|
||||||
|
|
||||||
override def tier = 0
|
|
||||||
|
|
||||||
override def hasRedstoneCard = items(1).fold(false)(driver.item.RedstoneCard.worksWith)
|
override def hasRedstoneCard = items(1).fold(false)(driver.item.RedstoneCard.worksWith)
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
|
||||||
override protected def markForRenderUpdate() {
|
|
||||||
super.markForRenderUpdate()
|
|
||||||
currentGui.foreach(_.recompileDisplayLists())
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
override def getInvName = Settings.namespace + "container.Robot"
|
override def getInvName = Settings.namespace + "container.Robot"
|
||||||
|
@ -4,7 +4,6 @@ import cpw.mods.fml.common.Optional
|
|||||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||||
import li.cil.oc.api
|
import li.cil.oc.api
|
||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
import li.cil.oc.client.gui
|
|
||||||
import mods.immibis.redlogic.api.wiring.IWire
|
import mods.immibis.redlogic.api.wiring.IWire
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
import net.minecraft.entity.player.EntityPlayer
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
@ -230,14 +229,6 @@ class RobotProxy(val robot: Robot) extends traits.Computer with traits.TextBuffe
|
|||||||
|
|
||||||
override lazy val buffer = robot.buffer
|
override lazy val buffer = robot.buffer
|
||||||
|
|
||||||
override def bufferIsDirty = robot.bufferIsDirty
|
|
||||||
|
|
||||||
override def bufferIsDirty_=(value: Boolean) = robot.bufferIsDirty = value
|
|
||||||
|
|
||||||
override def currentGui = robot.currentGui
|
|
||||||
|
|
||||||
override def currentGui_=(value: Option[gui.Buffer]) = robot.currentGui = value
|
|
||||||
|
|
||||||
override def tier = robot.tier
|
override def tier = robot.tier
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
@ -2,13 +2,8 @@ package li.cil.oc.common.tileentity
|
|||||||
|
|
||||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
import li.cil.oc.client.renderer.MonospaceFontRenderer
|
|
||||||
import li.cil.oc.client.{PacketSender => ClientPacketSender}
|
|
||||||
import li.cil.oc.common.component
|
|
||||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
import li.cil.oc.util.{PackedColor, Color}
|
import li.cil.oc.util.Color
|
||||||
import net.minecraft.client.Minecraft
|
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
import net.minecraft.entity.player.EntityPlayer
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
import net.minecraft.entity.projectile.EntityArrow
|
import net.minecraft.entity.projectile.EntityArrow
|
||||||
@ -21,45 +16,13 @@ import scala.language.postfixOps
|
|||||||
class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with traits.Rotatable with traits.RedstoneAware with traits.Colored with Analyzable with Ordered[Screen] {
|
class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with traits.Rotatable with traits.RedstoneAware with traits.Colored with Analyzable with Ordered[Screen] {
|
||||||
def this() = this(0)
|
def this() = this(0)
|
||||||
|
|
||||||
|
// Enable redstone functionality.
|
||||||
_isOutputEnabled = true
|
_isOutputEnabled = true
|
||||||
|
|
||||||
override def validFacings = ForgeDirection.VALID_DIRECTIONS
|
override def validFacings = ForgeDirection.VALID_DIRECTIONS
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
override protected val _buffer = new component.Buffer(this) {
|
|
||||||
@Callback(doc = """function():boolean -- Returns whether the screen is currently on.""")
|
|
||||||
def isOn(computer: Context, args: Arguments): Array[AnyRef] = result(origin.isOn)
|
|
||||||
|
|
||||||
@Callback(doc = """function():boolean -- Turns the screen on. Returns true if it was off.""")
|
|
||||||
def turnOn(computer: Context, args: Arguments): Array[AnyRef] = {
|
|
||||||
if (!origin.isOn) {
|
|
||||||
origin.turnOn()
|
|
||||||
result(true, origin.isOn)
|
|
||||||
}
|
|
||||||
else result(false, origin.isOn)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Callback(doc = """function():boolean -- Turns off the screen. Returns true if it was on.""")
|
|
||||||
def turnOff(computer: Context, args: Arguments): Array[AnyRef] = {
|
|
||||||
if (origin.isOn) {
|
|
||||||
origin.turnOff()
|
|
||||||
result(true, origin.isOn)
|
|
||||||
}
|
|
||||||
else result(false, origin.isOn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is the energy cost (per tick) to keep the screen running if every
|
|
||||||
// single "pixel" is lit. This cost increases with higher tiers as their
|
|
||||||
// maximum resolution (pixel density) increases. For a basic screen this is
|
|
||||||
// simply the configured cost.
|
|
||||||
val fullyLitCost = {
|
|
||||||
val (w, h) = Settings.screenResolutionsByTier(0)
|
|
||||||
val (mw, mh) = buffer.maxResolution
|
|
||||||
Settings.get.screenCost * (mw * mh) / (w * h)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for multi-block screen option in next update. We do this in the
|
* Check for multi-block screen option in next update. We do this in the
|
||||||
* update to avoid unnecessary checks on chunk unload.
|
* update to avoid unnecessary checks on chunk unload.
|
||||||
@ -72,12 +35,6 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
|||||||
|
|
||||||
val screens = mutable.Set(this)
|
val screens = mutable.Set(this)
|
||||||
|
|
||||||
var relativeLitArea = -1.0
|
|
||||||
|
|
||||||
var hasPower = true
|
|
||||||
|
|
||||||
var isOn = true
|
|
||||||
|
|
||||||
var hadRedstoneInput = false
|
var hadRedstoneInput = false
|
||||||
|
|
||||||
var cachedBounds: Option[AxisAlignedBB] = None
|
var cachedBounds: Option[AxisAlignedBB] = None
|
||||||
@ -102,7 +59,7 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
|||||||
(lx - ox, ly - oy)
|
(lx - ox, ly - oy)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def hasKeyboard = screens.exists(screen =>
|
def hasKeyboard = screens.exists(screen =>
|
||||||
ForgeDirection.VALID_DIRECTIONS.map(side => (side, world.getBlockTileEntity(screen.x + side.offsetX, screen.y + side.offsetY, screen.z + side.offsetZ))).exists {
|
ForgeDirection.VALID_DIRECTIONS.map(side => (side, world.getBlockTileEntity(screen.x + side.offsetX, screen.y + side.offsetY, screen.z + side.offsetZ))).exists {
|
||||||
case (side, keyboard: Keyboard) => keyboard.hasNodeOnSide(side.getOpposite)
|
case (side, keyboard: Keyboard) => keyboard.hasNodeOnSide(side.getOpposite)
|
||||||
case _ => false
|
case _ => false
|
||||||
@ -136,8 +93,9 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
|||||||
val (rx, ry) = ((ax - border) / iw, (ay - border) / ih)
|
val (rx, ry) = ((ax - border) / iw, (ay - border) / ih)
|
||||||
|
|
||||||
// Make it a relative position in the displayed buffer.
|
// Make it a relative position in the displayed buffer.
|
||||||
val (bw, bh) = origin.buffer.resolution
|
val bw = buffer.getWidth
|
||||||
val (bpw, bph) = (bw * MonospaceFontRenderer.fontWidth / iw.toDouble, bh * MonospaceFontRenderer.fontHeight / ih.toDouble)
|
val bh = buffer.getHeight
|
||||||
|
val (bpw, bph) = (buffer.renderWidth / iw.toDouble, buffer.renderHeight / ih.toDouble)
|
||||||
val (brx, bry) = if (bpw > bph) {
|
val (brx, bry) = if (bpw > bph) {
|
||||||
val rh = bph.toDouble / bpw.toDouble
|
val rh = bph.toDouble / bpw.toDouble
|
||||||
val bry = (ry - (1 - rh) * 0.5) / rh
|
val bry = (ry - (1 - rh) * 0.5) / rh
|
||||||
@ -160,7 +118,7 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
|||||||
|
|
||||||
// Convert to absolute coordinates and send the packet to the server.
|
// Convert to absolute coordinates and send the packet to the server.
|
||||||
if (world.isRemote) {
|
if (world.isRemote) {
|
||||||
ClientPacketSender.sendMouseClick(this.buffer, (brx * bw).toInt + 1, (bry * bh).toInt + 1, drag = false, 0)
|
buffer.mouseDown((brx * bw).toInt + 1, (bry * bh).toInt + 1, 0, null)
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@ -190,40 +148,10 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def turnOn() {
|
|
||||||
origin.isOn = true
|
|
||||||
val neededPower = width * height * Settings.get.screenCost * Settings.get.tickFrequency
|
|
||||||
origin.hasPower = buffer.node.changeBuffer(-neededPower) == 0
|
|
||||||
ServerPacketSender.sendScreenPowerChange(origin, origin.isOn && origin.hasPower)
|
|
||||||
}
|
|
||||||
|
|
||||||
def turnOff() {
|
|
||||||
origin.isOn = false
|
|
||||||
ServerPacketSender.sendScreenPowerChange(origin, origin.isOn && origin.hasPower)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
override def updateEntity() {
|
override def updateEntity() {
|
||||||
super.updateEntity()
|
super.updateEntity()
|
||||||
if (isServer && isOn && isOrigin && world.getWorldTime % Settings.get.tickFrequency == 0) {
|
|
||||||
if (relativeLitArea < 0) {
|
|
||||||
// The relative lit area is the number of pixels that are not blank
|
|
||||||
// versus the number of pixels in the *current* resolution. This is
|
|
||||||
// scaled to multi-block screens, since we only compute this for the
|
|
||||||
// origin.
|
|
||||||
val (w, h) = buffer.resolution
|
|
||||||
relativeLitArea = width * height * buffer.lines.foldLeft(0) {
|
|
||||||
(acc, line) => acc + line.count(' ' !=)
|
|
||||||
} / (w * h).toDouble
|
|
||||||
}
|
|
||||||
val hadPower = hasPower
|
|
||||||
val neededPower = relativeLitArea * fullyLitCost * Settings.get.tickFrequency
|
|
||||||
hasPower = buffer.node.tryChangeBuffer(-neededPower)
|
|
||||||
if (hasPower != hadPower) {
|
|
||||||
ServerPacketSender.sendScreenPowerChange(this, isOn && hasPower)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (shouldCheckForMultiBlock) {
|
if (shouldCheckForMultiBlock) {
|
||||||
// Make sure we merge in a deterministic order, to avoid getting
|
// Make sure we merge in a deterministic order, to avoid getting
|
||||||
// different results on server and client due to the update order
|
// different results on server and client due to the update order
|
||||||
@ -253,7 +181,6 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
|||||||
current.screens.foreach {
|
current.screens.foreach {
|
||||||
screen =>
|
screen =>
|
||||||
screen.shouldCheckForMultiBlock = false
|
screen.shouldCheckForMultiBlock = false
|
||||||
screen.bufferIsDirty = true
|
|
||||||
pending.remove(screen)
|
pending.remove(screen)
|
||||||
queue += screen
|
queue += screen
|
||||||
}
|
}
|
||||||
@ -264,25 +191,28 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Update visibility after everything is done, to avoid noise.
|
// Update visibility after everything is done, to avoid noise.
|
||||||
queue.foreach(screen =>
|
queue.foreach(screen => {
|
||||||
|
val buffer = screen.buffer
|
||||||
if (screen.isOrigin) {
|
if (screen.isOrigin) {
|
||||||
if (isServer) {
|
if (isServer) {
|
||||||
screen.buffer.node.setVisibility(Visibility.Network)
|
buffer.node.asInstanceOf[Component].setVisibility(Visibility.Network)
|
||||||
|
buffer.setEnergyCostPerTick(Settings.get.screenCost * width * height)
|
||||||
|
buffer.setAspectRatio(width, height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (isServer) {
|
if (isServer) {
|
||||||
screen.buffer.node.setVisibility(Visibility.None)
|
buffer.node.asInstanceOf[Component].setVisibility(Visibility.None)
|
||||||
}
|
buffer.setEnergyCostPerTick(Settings.get.screenCost)
|
||||||
val buffer = screen.buffer
|
|
||||||
val (w, h) = buffer.resolution
|
|
||||||
buffer.foreground = PackedColor.Color(0xFFFFFF)
|
|
||||||
buffer.background = PackedColor.Color(0x000000)
|
|
||||||
if (buffer.buffer.fill(0, 0, w, h, ' ')) {
|
|
||||||
onScreenFill(0, 0, w, h, ' ')
|
|
||||||
}
|
}
|
||||||
|
buffer.setAspectRatio(1, 1)
|
||||||
|
val w = buffer.getWidth
|
||||||
|
val h = buffer.getHeight
|
||||||
|
buffer.setForegroundColor(0xFFFFFF, false)
|
||||||
|
buffer.setBackgroundColor(0x000000, false)
|
||||||
|
buffer.fill(0, 0, w, h, ' ')
|
||||||
}
|
}
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
if (arrows.size > 0) {
|
if (arrows.size > 0) {
|
||||||
for (arrow <- arrows) {
|
for (arrow <- arrows) {
|
||||||
@ -297,9 +227,6 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
|||||||
|
|
||||||
override protected def dispose() {
|
override protected def dispose() {
|
||||||
super.dispose()
|
super.dispose()
|
||||||
if (currentGui.isDefined) {
|
|
||||||
Minecraft.getMinecraft.displayGuiScreen(null)
|
|
||||||
}
|
|
||||||
screens.clone().foreach(_.checkMultiBlock())
|
screens.clone().foreach(_.checkMultiBlock())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,36 +241,15 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
|||||||
tier = nbt.getByte(Settings.namespace + "tier") max 0 min 2
|
tier = nbt.getByte(Settings.namespace + "tier") max 0 min 2
|
||||||
color = Color.byTier(tier)
|
color = Color.byTier(tier)
|
||||||
super.readFromNBT(nbt)
|
super.readFromNBT(nbt)
|
||||||
// This check is just to avoid powering off any screens that have been
|
|
||||||
// placed before this was introduced.
|
|
||||||
if (nbt.hasKey(Settings.namespace + "isOn")) {
|
|
||||||
isOn = nbt.getBoolean(Settings.namespace + "isOn")
|
|
||||||
}
|
|
||||||
if (nbt.hasKey(Settings.namespace + "isOn")) {
|
|
||||||
hasPower = nbt.getBoolean(Settings.namespace + "hasPower")
|
|
||||||
}
|
|
||||||
hadRedstoneInput = nbt.getBoolean(Settings.namespace + "hadRedstoneInput")
|
hadRedstoneInput = nbt.getBoolean(Settings.namespace + "hadRedstoneInput")
|
||||||
}
|
}
|
||||||
|
|
||||||
override def writeToNBT(nbt: NBTTagCompound) {
|
override def writeToNBT(nbt: NBTTagCompound) {
|
||||||
nbt.setByte(Settings.namespace + "tier", tier.toByte)
|
nbt.setByte(Settings.namespace + "tier", tier.toByte)
|
||||||
super.writeToNBT(nbt)
|
super.writeToNBT(nbt)
|
||||||
nbt.setBoolean(Settings.namespace + "isOn", isOn)
|
|
||||||
nbt.setBoolean(Settings.namespace + "hasPower", hasPower)
|
|
||||||
nbt.setBoolean(Settings.namespace + "hadRedstoneInput", hadRedstoneInput)
|
nbt.setBoolean(Settings.namespace + "hadRedstoneInput", hadRedstoneInput)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
|
||||||
override def readFromNBTForClient(nbt: NBTTagCompound) {
|
|
||||||
super.readFromNBTForClient(nbt)
|
|
||||||
hasPower = nbt.getBoolean("hasPower")
|
|
||||||
}
|
|
||||||
|
|
||||||
override def writeToNBTForClient(nbt: NBTTagCompound) {
|
|
||||||
super.writeToNBTForClient(nbt)
|
|
||||||
nbt.setBoolean("hasPower", isOn && hasPower)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
@ -376,7 +282,7 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
|||||||
if (hasRedstoneInput != hadRedstoneInput) {
|
if (hasRedstoneInput != hadRedstoneInput) {
|
||||||
hadRedstoneInput = hasRedstoneInput
|
hadRedstoneInput = hasRedstoneInput
|
||||||
if (hasRedstoneInput) {
|
if (hasRedstoneInput) {
|
||||||
if (origin.isOn) turnOff() else turnOn()
|
origin.buffer.setPowerState(!origin.buffer.getPowerState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -386,37 +292,6 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
|||||||
screens.clone().foreach(_.checkMultiBlock())
|
screens.clone().foreach(_.checkMultiBlock())
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
|
|
||||||
super.onScreenCopy(col, row, w, h, tx, ty)
|
|
||||||
relativeLitArea = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
|
|
||||||
super.onScreenFill(col, row, w, h, c)
|
|
||||||
relativeLitArea = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenPaletteChange(index: Int, color: Int){
|
|
||||||
super.onScreenPaletteChange(index, color)
|
|
||||||
relativeLitArea = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenResolutionChange(w: Int, h: Int) {
|
|
||||||
super.onScreenResolutionChange(w, h)
|
|
||||||
relativeLitArea = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenSet(col: Int, row: Int, s: String) {
|
|
||||||
super.onScreenSet(col, row, s)
|
|
||||||
relativeLitArea = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
|
||||||
override protected def markForRenderUpdate() {
|
|
||||||
super.markForRenderUpdate()
|
|
||||||
currentGui.foreach(_.recompileDisplayLists())
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
override def compare(that: Screen) =
|
override def compare(that: Screen) =
|
||||||
|
@ -10,6 +10,7 @@ import li.cil.oc.util.mods.{Mods, StargateTech2}
|
|||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
import stargatetech2.api.bus.{IBusInterface, IBusDevice}
|
import stargatetech2.api.bus.{IBusInterface, IBusDevice}
|
||||||
import stargatetech2.api.StargateTechAPI
|
import stargatetech2.api.StargateTechAPI
|
||||||
|
import li.cil.oc.server.component.AbstractBus
|
||||||
|
|
||||||
// IMPORTANT: for some reason that is beyond me we cannot implement the
|
// IMPORTANT: for some reason that is beyond me we cannot implement the
|
||||||
// IBusDevice here directly, since we'll get an error if the interface is not
|
// IBusDevice here directly, since we'll get an error if the interface is not
|
||||||
@ -32,7 +33,7 @@ trait AbstractBusAware extends TileEntity with network.Environment {
|
|||||||
if (isAbstractBusAvailable) {
|
if (isAbstractBusAvailable) {
|
||||||
if (isServer) {
|
if (isServer) {
|
||||||
installedComponents.collect {
|
installedComponents.collect {
|
||||||
case abstractBus: component.AbstractBus => abstractBus.busInterface
|
case abstractBus: AbstractBus => abstractBus.busInterface
|
||||||
}.toArray
|
}.toArray
|
||||||
}
|
}
|
||||||
else fakeInterface.map(_.asInstanceOf[IBusInterface])
|
else fakeInterface.map(_.asInstanceOf[IBusInterface])
|
||||||
|
@ -1,28 +1,29 @@
|
|||||||
package li.cil.oc.common.tileentity.traits
|
package li.cil.oc.common.tileentity.traits
|
||||||
|
|
||||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||||
import li.cil.oc.api.network.Node
|
import li.cil.oc.{Settings, api}
|
||||||
import li.cil.oc.common.component
|
|
||||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
|
||||||
import li.cil.oc.util.PackedColor
|
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
|
||||||
trait TextBuffer extends Environment with component.Buffer.Owner {
|
trait TextBuffer extends Environment {
|
||||||
protected val _buffer = new component.Buffer(this)
|
lazy val buffer = {
|
||||||
|
val screenItem = api.Items.get("screen1").createItemStack(1)
|
||||||
|
val buffer = api.Driver.driverFor(screenItem).createEnvironment(screenItem, this).asInstanceOf[api.component.Screen]
|
||||||
|
val (maxWidth, maxHeight) = Settings.screenResolutionsByTier(tier)
|
||||||
|
buffer.setMaximumResolution(maxWidth, maxHeight)
|
||||||
|
buffer.setMaximumColorDepth(Settings.screenDepthsByTier(tier))
|
||||||
|
buffer
|
||||||
|
}
|
||||||
|
|
||||||
protected var _bufferIsDirty = false
|
override def node = buffer.node
|
||||||
|
|
||||||
lazy val buffer = _buffer
|
def tier: Int
|
||||||
|
|
||||||
def bufferIsDirty = _bufferIsDirty
|
override def updateEntity() {
|
||||||
|
super.updateEntity()
|
||||||
def bufferIsDirty_=(value: Boolean) = _bufferIsDirty = value
|
if (isServer) {
|
||||||
|
buffer.update()
|
||||||
override def node: Node = buffer.node
|
}
|
||||||
|
}
|
||||||
override def tier: Int
|
|
||||||
|
|
||||||
def hasKeyboard = true
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
@ -39,73 +40,11 @@ trait TextBuffer extends Environment with component.Buffer.Owner {
|
|||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
override def readFromNBTForClient(nbt: NBTTagCompound) {
|
override def readFromNBTForClient(nbt: NBTTagCompound) {
|
||||||
super.readFromNBTForClient(nbt)
|
super.readFromNBTForClient(nbt)
|
||||||
buffer.buffer.load(nbt)
|
buffer.load(nbt)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def writeToNBTForClient(nbt: NBTTagCompound) {
|
override def writeToNBTForClient(nbt: NBTTagCompound) {
|
||||||
super.writeToNBTForClient(nbt)
|
super.writeToNBTForClient(nbt)
|
||||||
buffer.buffer.save(nbt)
|
buffer.save(nbt)
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
|
||||||
|
|
||||||
override def onScreenColorChange(foreground: PackedColor.Color, background: PackedColor.Color) {
|
|
||||||
if (isServer) {
|
|
||||||
world.markTileEntityChunkModified(x, y, z, this)
|
|
||||||
ServerPacketSender.sendScreenColorChange(buffer, foreground, background)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
|
|
||||||
if (isServer) {
|
|
||||||
world.markTileEntityChunkModified(x, y, z, this)
|
|
||||||
ServerPacketSender.sendScreenCopy(buffer, col, row, w, h, tx, ty)
|
|
||||||
}
|
|
||||||
else markForRenderUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenDepthChange(depth: PackedColor.Depth.Value) {
|
|
||||||
if (isServer) {
|
|
||||||
world.markTileEntityChunkModified(x, y, z, this)
|
|
||||||
ServerPacketSender.sendScreenDepthChange(buffer, depth)
|
|
||||||
}
|
|
||||||
else markForRenderUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
|
|
||||||
if (isServer) {
|
|
||||||
world.markTileEntityChunkModified(x, y, z, this)
|
|
||||||
ServerPacketSender.sendScreenFill(buffer, col, row, w, h, c)
|
|
||||||
}
|
|
||||||
else markForRenderUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenPaletteChange(index: Int, color: Int) {
|
|
||||||
if (isServer) {
|
|
||||||
world.markTileEntityChunkModified(x, y, z, this)
|
|
||||||
ServerPacketSender.sendScreenPaletteChange(buffer, index, color)
|
|
||||||
}
|
|
||||||
else markForRenderUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenResolutionChange(w: Int, h: Int) {
|
|
||||||
if (isServer) {
|
|
||||||
world.markTileEntityChunkModified(x, y, z, this)
|
|
||||||
ServerPacketSender.sendScreenResolutionChange(buffer, w, h)
|
|
||||||
}
|
|
||||||
else markForRenderUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onScreenSet(col: Int, row: Int, s: String) {
|
|
||||||
if (isServer) {
|
|
||||||
world.markTileEntityChunkModified(x, y, z, this)
|
|
||||||
ServerPacketSender.sendScreenSet(buffer, col, row, s)
|
|
||||||
}
|
|
||||||
else markForRenderUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
|
||||||
protected def markForRenderUpdate() {
|
|
||||||
bufferIsDirty = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
src/main/scala/li/cil/oc/server/ComponentTracker.scala
Normal file
5
src/main/scala/li/cil/oc/server/ComponentTracker.scala
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package li.cil.oc.server
|
||||||
|
|
||||||
|
import li.cil.oc.common
|
||||||
|
|
||||||
|
object ComponentTracker extends common.ComponentTracker
|
@ -1,14 +1,15 @@
|
|||||||
package li.cil.oc.server
|
package li.cil.oc.server
|
||||||
|
|
||||||
import cpw.mods.fml.common.network.Player
|
import cpw.mods.fml.common.network.Player
|
||||||
import li.cil.oc.api.machine.Machine
|
|
||||||
import li.cil.oc.common.multipart.EventHandler
|
|
||||||
import li.cil.oc.common.PacketType
|
|
||||||
import li.cil.oc.common.tileentity._
|
|
||||||
import li.cil.oc.common.tileentity.traits.{Computer, TextBuffer, TileEntity}
|
|
||||||
import li.cil.oc.common.{PacketHandler => CommonPacketHandler}
|
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
import net.minecraft.entity.player.EntityPlayerMP
|
import li.cil.oc.api
|
||||||
|
import li.cil.oc.api.machine.Machine
|
||||||
|
import li.cil.oc.common.{PacketHandler => CommonPacketHandler}
|
||||||
|
import li.cil.oc.common.PacketType
|
||||||
|
import li.cil.oc.common.multipart.EventHandler
|
||||||
|
import li.cil.oc.common.tileentity._
|
||||||
|
import li.cil.oc.common.tileentity.traits.{Computer, TileEntity}
|
||||||
|
import net.minecraft.entity.player.{EntityPlayer, EntityPlayerMP}
|
||||||
import net.minecraft.util.ChatMessageComponent
|
import net.minecraft.util.ChatMessageComponent
|
||||||
import net.minecraftforge.common.{ForgeDirection, DimensionManager}
|
import net.minecraftforge.common.{ForgeDirection, DimensionManager}
|
||||||
|
|
||||||
@ -63,100 +64,51 @@ class PacketHandler extends CommonPacketHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def onKeyDown(p: PacketParser) =
|
def onKeyDown(p: PacketParser) {
|
||||||
p.readTileEntity[TileEntity]() match {
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
case Some(t: Screen) =>
|
case Some(buffer: api.component.Screen) => buffer.keyDown(p.readChar(), p.readInt(), p.player.asInstanceOf[EntityPlayer])
|
||||||
val char = Char.box(p.readChar())
|
case _ => // Invalid Packet
|
||||||
val code = Int.box(p.readInt())
|
|
||||||
t.screens.foreach(_.node.sendToNeighbors("keyboard.keyDown", p.player, char, code))
|
|
||||||
case Some(t: TextBuffer) => t.buffer.node.sendToNeighbors("keyboard.keyDown", p.player, Char.box(p.readChar()), Int.box(p.readInt()))
|
|
||||||
case Some(t: Rack) => t.terminals(p.readInt()).buffer.node.sendToNeighbors("keyboard.keyDown", p.player, Char.box(p.readChar()), Int.box(p.readInt()))
|
|
||||||
case _ => // Invalid packet.
|
|
||||||
}
|
|
||||||
|
|
||||||
def onKeyUp(p: PacketParser) =
|
|
||||||
p.readTileEntity[TileEntity]() match {
|
|
||||||
case Some(t: Screen) =>
|
|
||||||
val char = Char.box(p.readChar())
|
|
||||||
val code = Int.box(p.readInt())
|
|
||||||
t.screens.foreach(_.node.sendToNeighbors("keyboard.keyUp", p.player, char, code))
|
|
||||||
case Some(t: TextBuffer) => t.buffer.node.sendToNeighbors("keyboard.keyUp", p.player, Char.box(p.readChar()), Int.box(p.readInt()))
|
|
||||||
case Some(t: Rack) => t.terminals(p.readInt()).buffer.node.sendToNeighbors("keyboard.keyUp", p.player, Char.box(p.readChar()), Int.box(p.readInt()))
|
|
||||||
case _ => // Invalid packet.
|
|
||||||
}
|
|
||||||
|
|
||||||
def onClipboard(p: PacketParser) =
|
|
||||||
p.readTileEntity[TileEntity]() match {
|
|
||||||
case Some(t: Screen) =>
|
|
||||||
val value = p.readUTF()
|
|
||||||
t.screens.foreach(_.node.sendToNeighbors("keyboard.clipboard", p.player, value))
|
|
||||||
case Some(t: TextBuffer) => t.buffer.node.sendToNeighbors("keyboard.clipboard", p.player, p.readUTF())
|
|
||||||
case Some(t: Rack) => t.terminals(p.readInt()).buffer.node.sendToNeighbors("keyboard.clipboard", p.player, p.readUTF())
|
|
||||||
case _ => // Invalid packet.
|
|
||||||
}
|
|
||||||
|
|
||||||
def onMouseClick(p: PacketParser) {
|
|
||||||
p.player match {
|
|
||||||
case player: EntityPlayerMP =>
|
|
||||||
val node = p.readTileEntity[TileEntity]() match {
|
|
||||||
case Some(t: Screen) => t.origin.node
|
|
||||||
case Some(t: Rack) => t.terminals(p.readInt()).buffer.node
|
|
||||||
case _ => return // Invalid packet.
|
|
||||||
}
|
|
||||||
val x = p.readInt()
|
|
||||||
val y = p.readInt()
|
|
||||||
val what = if (p.readBoolean()) "drag" else "touch"
|
|
||||||
val button = p.readByte()
|
|
||||||
if (Settings.get.inputUsername) {
|
|
||||||
node.sendToReachable("computer.checked_signal", player, what, Int.box(x), Int.box(y), Int.box(button), player.getCommandSenderName)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
node.sendToReachable("computer.checked_signal", player, what, Int.box(x), Int.box(y), Int.box(button))
|
|
||||||
}
|
|
||||||
case _ => // Invalid packet.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def onMouseScroll(p: PacketParser) {
|
def onKeyUp(p: PacketParser) {
|
||||||
p.player match {
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
case player: EntityPlayerMP =>
|
case Some(buffer: api.component.Screen) => buffer.keyUp(p.readChar(), p.readInt(), p.player.asInstanceOf[EntityPlayer])
|
||||||
val node = p.readTileEntity[TileEntity]() match {
|
case _ => // Invalid Packet
|
||||||
case Some(t: Screen) => t.origin.node
|
}
|
||||||
case Some(t: Rack) => t.terminals(p.readInt()).buffer.node
|
}
|
||||||
case _ => return // Invalid packet.
|
|
||||||
}
|
def onClipboard(p: PacketParser) {
|
||||||
val x = p.readInt()
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
val y = p.readInt()
|
case Some(buffer: api.component.Screen) => buffer.clipboard(p.readUTF(), p.player.asInstanceOf[EntityPlayer])
|
||||||
val scroll = p.readByte()
|
case _ => // Invalid Packet
|
||||||
if (Settings.get.inputUsername) {
|
}
|
||||||
node.sendToReachable("computer.checked_signal", player, "scroll", Int.box(x), Int.box(y), Int.box(scroll), player.getCommandSenderName)
|
}
|
||||||
}
|
|
||||||
else {
|
def onMouseClick(p: PacketParser) {
|
||||||
node.sendToReachable("computer.checked_signal", player, "scroll", Int.box(x), Int.box(y), Int.box(scroll))
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
}
|
case Some(buffer: api.component.Screen) =>
|
||||||
case _ => // Invalid packet.
|
val x = p.readShort()
|
||||||
|
val y = p.readShort()
|
||||||
|
val dragging = p.readBoolean()
|
||||||
|
val button = p.readByte()
|
||||||
|
if (dragging) buffer.mouseDrag(x, y, button, p.player.asInstanceOf[EntityPlayer])
|
||||||
|
else buffer.mouseDown(x, y, button, p.player.asInstanceOf[EntityPlayer])
|
||||||
|
case _ => // Invalid Packet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def onMouseUp(p: PacketParser) {
|
def onMouseUp(p: PacketParser) {
|
||||||
p.player match {
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
case player: EntityPlayerMP =>
|
case Some(buffer: api.component.Screen) => buffer.mouseUp(p.readShort(), p.readShort(), p.readByte(), p.player.asInstanceOf[EntityPlayer])
|
||||||
val node = p.readTileEntity[TileEntity]() match {
|
case _ => // Invalid Packet
|
||||||
case Some(t: Screen) => t.origin.node
|
}
|
||||||
case Some(t: Rack) => t.terminals(p.readInt()).buffer.node
|
}
|
||||||
case _ => return // Invalid packet.
|
|
||||||
}
|
def onMouseScroll(p: PacketParser) {
|
||||||
val x = p.readInt()
|
ComponentTracker.get(p.readUTF()) match {
|
||||||
val y = p.readInt()
|
case Some(buffer: api.component.Screen) => buffer.mouseScroll(p.readShort(), p.readShort(), p.readByte(), p.player.asInstanceOf[EntityPlayer])
|
||||||
val what = "drop"
|
case _ => // Invalid Packet
|
||||||
val button = p.readByte()
|
|
||||||
if (Settings.get.inputUsername) {
|
|
||||||
node.sendToReachable("computer.checked_signal", player, what, Int.box(x), Int.box(y), Int.box(button), player.getCommandSenderName)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
node.sendToReachable("computer.checked_signal", player, what, Int.box(x), Int.box(y), Int.box(button))
|
|
||||||
}
|
|
||||||
case _ => // Invalid packet.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package li.cil.oc.server
|
package li.cil.oc.server
|
||||||
|
|
||||||
import li.cil.oc.common
|
|
||||||
import li.cil.oc.common.tileentity
|
import li.cil.oc.common.tileentity
|
||||||
import li.cil.oc.common.tileentity.traits._
|
import li.cil.oc.common.tileentity.traits._
|
||||||
import li.cil.oc.common.{CompressedPacketBuilder, PacketBuilder, PacketType}
|
import li.cil.oc.common.{CompressedPacketBuilder, PacketBuilder, PacketType}
|
||||||
@ -9,6 +8,8 @@ import net.minecraft.entity.player.EntityPlayerMP
|
|||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraftforge.common.ForgeDirection
|
import net.minecraftforge.common.ForgeDirection
|
||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
|
import li.cil.oc.api.component.Screen.ColorDepth
|
||||||
|
import li.cil.oc.server.component.Container
|
||||||
|
|
||||||
object PacketSender {
|
object PacketSender {
|
||||||
def sendAbstractBusState(t: AbstractBusAware) {
|
def sendAbstractBusState(t: AbstractBusAware) {
|
||||||
@ -227,40 +228,22 @@ object PacketSender {
|
|||||||
pb.sendToNearbyPlayers(t, 64)
|
pb.sendToNearbyPlayers(t, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendScreenColorChange(b: common.component.Buffer, foreground: PackedColor.Color, background: PackedColor.Color) {
|
def sendTextBufferColorChange(address: String, foreground: PackedColor.Color, background: PackedColor.Color, container: Container) {
|
||||||
val pb = new PacketBuilder(PacketType.ScreenColorChange)
|
val pb = new PacketBuilder(PacketType.TextBufferColorChange)
|
||||||
|
|
||||||
val t = b.owner match {
|
pb.writeUTF(address)
|
||||||
case t: TextBuffer =>
|
|
||||||
pb.writeTileEntity(t)
|
|
||||||
t
|
|
||||||
case t: common.component.Terminal =>
|
|
||||||
pb.writeTileEntity(t.rack)
|
|
||||||
pb.writeInt(t.number)
|
|
||||||
t.rack
|
|
||||||
case _ => return
|
|
||||||
}
|
|
||||||
pb.writeInt(foreground.value)
|
pb.writeInt(foreground.value)
|
||||||
pb.writeBoolean(foreground.isPalette)
|
pb.writeBoolean(foreground.isPalette)
|
||||||
pb.writeInt(background.value)
|
pb.writeInt(background.value)
|
||||||
pb.writeBoolean(background.isPalette)
|
pb.writeBoolean(background.isPalette)
|
||||||
|
|
||||||
pb.sendToNearbyPlayers(t)
|
pb.sendToNearbyPlayers(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendScreenCopy(b: common.component.Buffer, col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
|
def sendTextBufferCopy(address: String, col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int, container: Container) {
|
||||||
val pb = new PacketBuilder(PacketType.ScreenCopy)
|
val pb = new PacketBuilder(PacketType.TextBufferCopy)
|
||||||
|
|
||||||
val t = b.owner match {
|
pb.writeUTF(address)
|
||||||
case t: TextBuffer =>
|
|
||||||
pb.writeTileEntity(t)
|
|
||||||
t
|
|
||||||
case t: common.component.Terminal =>
|
|
||||||
pb.writeTileEntity(t.rack)
|
|
||||||
pb.writeInt(t.number)
|
|
||||||
t.rack
|
|
||||||
case _ => return
|
|
||||||
}
|
|
||||||
pb.writeInt(col)
|
pb.writeInt(col)
|
||||||
pb.writeInt(row)
|
pb.writeInt(row)
|
||||||
pb.writeInt(w)
|
pb.writeInt(w)
|
||||||
@ -268,114 +251,69 @@ object PacketSender {
|
|||||||
pb.writeInt(tx)
|
pb.writeInt(tx)
|
||||||
pb.writeInt(ty)
|
pb.writeInt(ty)
|
||||||
|
|
||||||
pb.sendToNearbyPlayers(t)
|
pb.sendToNearbyPlayers(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendScreenDepthChange(b: common.component.Buffer, value: PackedColor.Depth.Value) {
|
def sendTextBufferDepthChange(address: String, value: ColorDepth, container: Container) {
|
||||||
val pb = new PacketBuilder(PacketType.ScreenDepthChange)
|
val pb = new PacketBuilder(PacketType.TextBufferDepthChange)
|
||||||
|
|
||||||
val t = b.owner match {
|
pb.writeUTF(address)
|
||||||
case t: TextBuffer =>
|
pb.writeInt(value.ordinal)
|
||||||
pb.writeTileEntity(t)
|
|
||||||
t
|
|
||||||
case t: common.component.Terminal =>
|
|
||||||
pb.writeTileEntity(t.rack)
|
|
||||||
pb.writeInt(t.number)
|
|
||||||
t.rack
|
|
||||||
case _ => return
|
|
||||||
}
|
|
||||||
pb.writeInt(value.id)
|
|
||||||
|
|
||||||
pb.sendToNearbyPlayers(t)
|
pb.sendToNearbyPlayers(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendScreenFill(b: common.component.Buffer, col: Int, row: Int, w: Int, h: Int, c: Char) {
|
def sendTextBufferFill(address: String, col: Int, row: Int, w: Int, h: Int, c: Char, container: Container) {
|
||||||
val pb = new PacketBuilder(PacketType.ScreenFill)
|
val pb = new PacketBuilder(PacketType.TextBufferFill)
|
||||||
|
|
||||||
val t = b.owner match {
|
pb.writeUTF(address)
|
||||||
case t: TextBuffer =>
|
|
||||||
pb.writeTileEntity(t)
|
|
||||||
t
|
|
||||||
case t: common.component.Terminal =>
|
|
||||||
pb.writeTileEntity(t.rack)
|
|
||||||
pb.writeInt(t.number)
|
|
||||||
t.rack
|
|
||||||
case _ => return
|
|
||||||
}
|
|
||||||
pb.writeInt(col)
|
pb.writeInt(col)
|
||||||
pb.writeInt(row)
|
pb.writeInt(row)
|
||||||
pb.writeInt(w)
|
pb.writeInt(w)
|
||||||
pb.writeInt(h)
|
pb.writeInt(h)
|
||||||
pb.writeChar(c)
|
pb.writeChar(c)
|
||||||
|
|
||||||
pb.sendToNearbyPlayers(t)
|
pb.sendToNearbyPlayers(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendScreenPaletteChange(b: common.component.Buffer, index: Int, color: Int) {
|
def sendTextBufferPaletteChange(address: String, index: Int, color: Int, container: Container) {
|
||||||
val pb = new PacketBuilder(PacketType.ScreenPaletteChange)
|
val pb = new PacketBuilder(PacketType.TextBufferPaletteChange)
|
||||||
|
|
||||||
val t = b.owner match {
|
pb.writeUTF(address)
|
||||||
case t: TextBuffer =>
|
|
||||||
pb.writeTileEntity(t)
|
|
||||||
t
|
|
||||||
case t: common.component.Terminal =>
|
|
||||||
pb.writeTileEntity(t.rack)
|
|
||||||
pb.writeInt(t.number)
|
|
||||||
t.rack
|
|
||||||
case _ => return
|
|
||||||
}
|
|
||||||
pb.writeInt(index)
|
pb.writeInt(index)
|
||||||
pb.writeInt(color)
|
pb.writeInt(color)
|
||||||
|
|
||||||
pb.sendToNearbyPlayers(t)
|
pb.sendToNearbyPlayers(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendScreenPowerChange(t: TextBuffer, hasPower: Boolean) {
|
def sendTextBufferPowerChange(address: String, hasPower: Boolean, container: Container) {
|
||||||
val pb = new PacketBuilder(PacketType.ScreenPowerChange)
|
val pb = new PacketBuilder(PacketType.TextBufferPowerChange)
|
||||||
|
|
||||||
pb.writeTileEntity(t)
|
pb.writeUTF(address)
|
||||||
pb.writeBoolean(hasPower)
|
pb.writeBoolean(hasPower)
|
||||||
|
|
||||||
pb.sendToNearbyPlayers(t, 64)
|
pb.sendToNearbyPlayers(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendScreenResolutionChange(b: common.component.Buffer, w: Int, h: Int) {
|
def sendTextBufferResolutionChange(address: String, w: Int, h: Int, container: Container) {
|
||||||
val pb = new PacketBuilder(PacketType.ScreenResolutionChange)
|
val pb = new PacketBuilder(PacketType.TextBufferResolutionChange)
|
||||||
|
|
||||||
val t = b.owner match {
|
pb.writeUTF(address)
|
||||||
case t: TextBuffer =>
|
|
||||||
pb.writeTileEntity(t)
|
|
||||||
t
|
|
||||||
case t: common.component.Terminal =>
|
|
||||||
pb.writeTileEntity(t.rack)
|
|
||||||
pb.writeInt(t.number)
|
|
||||||
t.rack
|
|
||||||
case _ => return
|
|
||||||
}
|
|
||||||
pb.writeInt(w)
|
pb.writeInt(w)
|
||||||
pb.writeInt(h)
|
pb.writeInt(h)
|
||||||
|
|
||||||
pb.sendToNearbyPlayers(t)
|
pb.sendToNearbyPlayers(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendScreenSet(b: common.component.Buffer, col: Int, row: Int, s: String) {
|
def sendTextBufferSet(address: String, col: Int, row: Int, s: String, container: Container) {
|
||||||
val pb = new PacketBuilder(PacketType.ScreenSet)
|
val pb = new PacketBuilder(PacketType.TextBufferSet)
|
||||||
|
|
||||||
val t = b.owner match {
|
pb.writeUTF(address)
|
||||||
case t: TextBuffer =>
|
|
||||||
pb.writeTileEntity(t)
|
|
||||||
t
|
|
||||||
case t: common.component.Terminal =>
|
|
||||||
pb.writeTileEntity(t.rack)
|
|
||||||
pb.writeInt(t.number)
|
|
||||||
t.rack
|
|
||||||
case _ => return
|
|
||||||
}
|
|
||||||
pb.writeInt(col)
|
pb.writeInt(col)
|
||||||
pb.writeInt(row)
|
pb.writeInt(row)
|
||||||
pb.writeUTF(s)
|
pb.writeUTF(s)
|
||||||
|
|
||||||
pb.sendToNearbyPlayers(t)
|
pb.sendToNearbyPlayers(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendServerPresence(t: tileentity.Rack) {
|
def sendServerPresence(t: tileentity.Rack) {
|
||||||
|
@ -3,6 +3,7 @@ package li.cil.oc.server.component
|
|||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
import li.cil.oc.api.Network
|
import li.cil.oc.api.Network
|
||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
import scala.collection.convert.WrapAsScala._
|
import scala.collection.convert.WrapAsScala._
|
||||||
import stargatetech2.api.StargateTechAPI
|
import stargatetech2.api.StargateTechAPI
|
||||||
|
51
src/main/scala/li/cil/oc/server/component/Container.scala
Normal file
51
src/main/scala/li/cil/oc/server/component/Container.scala
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package li.cil.oc.server.component
|
||||||
|
|
||||||
|
import net.minecraft.tileentity.TileEntity
|
||||||
|
import net.minecraft.entity.Entity
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
trait Container {
|
||||||
|
def tileEntity: Option[TileEntity] = None
|
||||||
|
|
||||||
|
def entity: Option[Entity] = None
|
||||||
|
|
||||||
|
def world: World
|
||||||
|
|
||||||
|
def x: Double
|
||||||
|
|
||||||
|
def y: Double
|
||||||
|
|
||||||
|
def z: Double
|
||||||
|
|
||||||
|
def markChanged() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Container {
|
||||||
|
|
||||||
|
case class TileEntityContainer(container: TileEntity) extends Container {
|
||||||
|
override def tileEntity = Option(container)
|
||||||
|
|
||||||
|
override def world = container.getWorldObj
|
||||||
|
|
||||||
|
override def x = container.xCoord + 0.5
|
||||||
|
|
||||||
|
override def y = container.yCoord + 0.5
|
||||||
|
|
||||||
|
override def z = container.zCoord + 0.5
|
||||||
|
|
||||||
|
override def markChanged() = container.onInventoryChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
case class EntityContainer(container: Entity) extends Container {
|
||||||
|
override def entity = Option(container)
|
||||||
|
|
||||||
|
override def world = container.worldObj
|
||||||
|
|
||||||
|
override def x = container.posX
|
||||||
|
|
||||||
|
override def y = container.posY
|
||||||
|
|
||||||
|
override def z = container.posZ
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,11 +1,12 @@
|
|||||||
package li.cil.oc.server.component
|
package li.cil.oc.server.component
|
||||||
|
|
||||||
import java.io.{FileNotFoundException, IOException}
|
import java.io.{FileNotFoundException, IOException}
|
||||||
|
import li.cil.oc.Settings
|
||||||
import li.cil.oc.api.fs.{Label, Mode, FileSystem => IFileSystem}
|
import li.cil.oc.api.fs.{Label, Mode, FileSystem => IFileSystem}
|
||||||
import li.cil.oc.api.Network
|
import li.cil.oc.api.Network
|
||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
import li.cil.oc.common.Sound
|
import li.cil.oc.common.Sound
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
import li.cil.oc.util.ExtendedNBT._
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
import net.minecraft.nbt.{NBTTagInt, NBTTagList, NBTTagCompound}
|
import net.minecraft.nbt.{NBTTagInt, NBTTagList, NBTTagCompound}
|
||||||
import net.minecraft.tileentity.TileEntity
|
import net.minecraft.tileentity.TileEntity
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
package li.cil.oc.server.component
|
package li.cil.oc.server.component
|
||||||
|
|
||||||
import li.cil.oc.api.Network
|
|
||||||
import li.cil.oc.api.network._
|
|
||||||
import li.cil.oc.common.component.Buffer
|
|
||||||
import li.cil.oc.common.tileentity
|
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
|
import li.cil.oc.api.Network
|
||||||
|
import li.cil.oc.api.component.Screen.ColorDepth
|
||||||
|
import li.cil.oc.api.network._
|
||||||
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
|
import li.cil.oc.common.tileentity
|
||||||
import li.cil.oc.util.PackedColor
|
import li.cil.oc.util.PackedColor
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
import net.minecraft.util.StatCollector
|
import net.minecraft.util.StatCollector
|
||||||
|
import li.cil.oc.api.component.Screen
|
||||||
|
|
||||||
abstract class GraphicsCard extends ManagedComponent {
|
abstract class GraphicsCard extends ManagedComponent {
|
||||||
val node = Network.newNode(this, Visibility.Neighbors).
|
val node = Network.newNode(this, Visibility.Neighbors).
|
||||||
@ -15,15 +17,15 @@ abstract class GraphicsCard extends ManagedComponent {
|
|||||||
withConnector().
|
withConnector().
|
||||||
create()
|
create()
|
||||||
|
|
||||||
val maxResolution: (Int, Int)
|
protected val maxResolution: (Int, Int)
|
||||||
|
|
||||||
val maxDepth: PackedColor.Depth.Value
|
protected val maxDepth: ColorDepth
|
||||||
|
|
||||||
private var screenAddress: Option[String] = None
|
private var screenAddress: Option[String] = None
|
||||||
|
|
||||||
private var screenInstance: Option[Buffer] = None
|
private var screenInstance: Option[Screen] = None
|
||||||
|
|
||||||
private def screen(f: (Buffer) => Array[AnyRef]) = screenInstance match {
|
private def screen(f: (Screen) => Array[AnyRef]) = screenInstance match {
|
||||||
case Some(screen) => screen.synchronized(f(screen))
|
case Some(screen) => screen.synchronized(f(screen))
|
||||||
case _ => Array(Unit, "no screen")
|
case _ => Array(Unit, "no screen")
|
||||||
}
|
}
|
||||||
@ -36,8 +38,8 @@ abstract class GraphicsCard extends ManagedComponent {
|
|||||||
super.update()
|
super.update()
|
||||||
if (node.network != null && screenInstance.isEmpty && screenAddress.isDefined) {
|
if (node.network != null && screenInstance.isEmpty && screenAddress.isDefined) {
|
||||||
Option(node.network.node(screenAddress.get)) match {
|
Option(node.network.node(screenAddress.get)) match {
|
||||||
case Some(node: Node) if node.host.isInstanceOf[Buffer] =>
|
case Some(node: Node) if node.host.isInstanceOf[Screen] =>
|
||||||
screenInstance = Some(node.host.asInstanceOf[Buffer])
|
screenInstance = Some(node.host.asInstanceOf[Screen])
|
||||||
case _ =>
|
case _ =>
|
||||||
// This could theoretically happen after loading an old address, but
|
// This could theoretically happen after loading an old address, but
|
||||||
// if the screen either disappeared between saving and now or changed
|
// if the screen either disappeared between saving and now or changed
|
||||||
@ -54,16 +56,17 @@ abstract class GraphicsCard extends ManagedComponent {
|
|||||||
val address = args.checkString(0)
|
val address = args.checkString(0)
|
||||||
node.network.node(address) match {
|
node.network.node(address) match {
|
||||||
case null => result(Unit, "invalid address")
|
case null => result(Unit, "invalid address")
|
||||||
case node: Node if node.host.isInstanceOf[Buffer] =>
|
case node: Node if node.host.isInstanceOf[Screen] =>
|
||||||
screenAddress = Option(address)
|
screenAddress = Option(address)
|
||||||
screenInstance = Some(node.host.asInstanceOf[Buffer])
|
screenInstance = Some(node.host.asInstanceOf[Screen])
|
||||||
screen(s => {
|
screen(s => {
|
||||||
val (gmw, gmh) = maxResolution
|
val (gmw, gmh) = maxResolution
|
||||||
val (smw, smh) = s.maxResolution
|
val smw = s.getMaximumWidth
|
||||||
s.resolution = (math.min(gmw, smw), math.min(gmh, smh))
|
val smh = s.getMaximumHeight
|
||||||
s.format = PackedColor.Depth.format(PackedColor.Depth(math.min(maxDepth.id, s.maxDepth.id)))
|
s.setResolution(math.min(gmw, smw), math.min(gmh, smh))
|
||||||
s.foreground = PackedColor.Color(0xFFFFFF)
|
s.setColorDepth(ColorDepth.values.apply(math.min(maxDepth.ordinal, s.getMaximumColorDepth.ordinal)))
|
||||||
s.background = PackedColor.Color(0x000000)
|
s.setForegroundColor(0xFFFFFF)
|
||||||
|
s.setBackgroundColor(0x000000)
|
||||||
result(true)
|
result(true)
|
||||||
})
|
})
|
||||||
case _ => result(Unit, "not a screen")
|
case _ => result(Unit, "not a screen")
|
||||||
@ -72,32 +75,36 @@ abstract class GraphicsCard extends ManagedComponent {
|
|||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def getBackground(context: Context, args: Arguments): Array[AnyRef] =
|
def getBackground(context: Context, args: Arguments): Array[AnyRef] =
|
||||||
screen(s => result(s.background.value, s.background.isPalette))
|
screen(s => result(s.getBackgroundColor, s.isBackgroundFromPalette))
|
||||||
|
|
||||||
def setBackground(context: Context, args: Arguments): Array[AnyRef] = {
|
def setBackground(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
val color = args.checkInteger(0)
|
val color = args.checkInteger(0)
|
||||||
screen(s => {
|
screen(s => {
|
||||||
val background = s.background = PackedColor.Color(color, args.count > 1 && args.checkBoolean(1))
|
val oldColor = s.getBackgroundColor
|
||||||
result(background.value, background.isPalette)
|
val oldIsPalette = s.isBackgroundFromPalette
|
||||||
|
s.setBackgroundColor(color, args.count > 1 && args.checkBoolean(1))
|
||||||
|
result(oldColor, oldIsPalette)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def getForeground(context: Context, args: Arguments): Array[AnyRef] =
|
def getForeground(context: Context, args: Arguments): Array[AnyRef] =
|
||||||
screen(s => result(s.foreground.value, s.foreground.isPalette))
|
screen(s => result(s.getForegroundColor, s.isForegroundFromPalette))
|
||||||
|
|
||||||
def setForeground(context: Context, args: Arguments): Array[AnyRef] = {
|
def setForeground(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
val color = args.checkInteger(0)
|
val color = args.checkInteger(0)
|
||||||
screen(s => {
|
screen(s => {
|
||||||
val foreground = s.foreground = PackedColor.Color(color, args.count > 1 && args.checkBoolean(1))
|
val oldColor = s.getForegroundColor
|
||||||
result(foreground.value, foreground.isPalette)
|
val oldIsPalette = s.isForegroundFromPalette
|
||||||
|
s.setForegroundColor(color, args.count > 1 && args.checkBoolean(1))
|
||||||
|
result(oldColor, oldIsPalette)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def getPaletteColor(context: Context, args: Arguments): Array[AnyRef] = {
|
def getPaletteColor(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
val index = args.checkInteger(0)
|
val index = args.checkInteger(0)
|
||||||
screen(s => result(s.getPalette(index)))
|
screen(s => result(s.getPaletteColor(index)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
@ -105,38 +112,39 @@ abstract class GraphicsCard extends ManagedComponent {
|
|||||||
val index = args.checkInteger(0)
|
val index = args.checkInteger(0)
|
||||||
val color = args.checkInteger(1)
|
val color = args.checkInteger(1)
|
||||||
context.pause(0.1)
|
context.pause(0.1)
|
||||||
screen(s => result(s.setPalette(index, color)))
|
screen(s => {
|
||||||
|
val oldColor = s.getPaletteColor(index)
|
||||||
|
s.setPaletteColor(index, color)
|
||||||
|
result(oldColor)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def getDepth(context: Context, args: Arguments): Array[AnyRef] =
|
def getDepth(context: Context, args: Arguments): Array[AnyRef] =
|
||||||
screen(s => result(PackedColor.Depth.bits(s.format.depth)))
|
screen(s => result(PackedColor.Depth.bits(s.getColorDepth)))
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
def setDepth(context: Context, args: Arguments): Array[AnyRef] = {
|
def setDepth(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
val depth = args.checkInteger(0)
|
val depth = args.checkInteger(0)
|
||||||
screen(s => result(s.format = depth match {
|
screen(s => {
|
||||||
case 1 => PackedColor.Depth.format(PackedColor.Depth.OneBit)
|
val oldDepth = s.getColorDepth
|
||||||
case 4 if maxDepth >= PackedColor.Depth.FourBit => PackedColor.Depth.format(PackedColor.Depth.FourBit)
|
depth match {
|
||||||
case 8 if maxDepth >= PackedColor.Depth.EightBit => PackedColor.Depth.format(PackedColor.Depth.EightBit)
|
case 1 => s.setColorDepth(ColorDepth.OneBit)
|
||||||
case _ => throw new IllegalArgumentException("unsupported depth")
|
case 4 if maxDepth.ordinal >= ColorDepth.FourBit.ordinal => s.setColorDepth(ColorDepth.FourBit)
|
||||||
}))
|
case 8 if maxDepth.ordinal >= ColorDepth.EightBit.ordinal => s.setColorDepth(ColorDepth.EightBit)
|
||||||
|
case _ => throw new IllegalArgumentException("unsupported depth")
|
||||||
|
}
|
||||||
|
result(oldDepth)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def maxDepth(context: Context, args: Arguments): Array[AnyRef] =
|
def maxDepth(context: Context, args: Arguments): Array[AnyRef] =
|
||||||
screen(s => result(PackedColor.Depth(math.min(maxDepth.id, s.maxDepth.id)) match {
|
screen(s => result(PackedColor.Depth.bits(ColorDepth.values.apply(math.min(maxDepth.ordinal, s.getMaximumColorDepth.ordinal)))))
|
||||||
case PackedColor.Depth.OneBit => 1
|
|
||||||
case PackedColor.Depth.FourBit => 4
|
|
||||||
case PackedColor.Depth.EightBit => 8
|
|
||||||
}))
|
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def getResolution(context: Context, args: Arguments): Array[AnyRef] =
|
def getResolution(context: Context, args: Arguments): Array[AnyRef] =
|
||||||
screen(s => {
|
screen(s => result(s.getWidth, s.getHeight))
|
||||||
val (w, h) = s.resolution
|
|
||||||
result(w, h)
|
|
||||||
})
|
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
def setResolution(context: Context, args: Arguments): Array[AnyRef] = {
|
def setResolution(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
@ -147,35 +155,24 @@ abstract class GraphicsCard extends ManagedComponent {
|
|||||||
// the minimum of screen and GPU resolution.
|
// the minimum of screen and GPU resolution.
|
||||||
if (w < 1 || h < 1 || w > mw || h > mw || h * w > mw * mh)
|
if (w < 1 || h < 1 || w > mw || h > mw || h * w > mw * mh)
|
||||||
throw new IllegalArgumentException("unsupported resolution")
|
throw new IllegalArgumentException("unsupported resolution")
|
||||||
screen(s => result(s.resolution = (w, h)))
|
screen(s => result(s.setResolution(w, h)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def maxResolution(context: Context, args: Arguments): Array[AnyRef] =
|
def maxResolution(context: Context, args: Arguments): Array[AnyRef] =
|
||||||
screen(s => {
|
screen(s => {
|
||||||
val (gmw, gmh) = maxResolution
|
val (gmw, gmh) = maxResolution
|
||||||
val (smw, smh) = s.maxResolution
|
val smw = s.getMaximumWidth
|
||||||
|
val smh = s.getMaximumHeight
|
||||||
result(math.min(gmw, smw), math.min(gmh, smh))
|
result(math.min(gmw, smw), math.min(gmh, smh))
|
||||||
})
|
})
|
||||||
|
|
||||||
@Callback
|
|
||||||
def getSize(context: Context, args: Arguments): Array[AnyRef] =
|
|
||||||
screen(s => s.owner match {
|
|
||||||
case screen: tileentity.Screen => result(screen.width, screen.height)
|
|
||||||
case _ => result(1, 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def get(context: Context, args: Arguments): Array[AnyRef] = {
|
def get(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
val x = args.checkInteger(0) - 1
|
val x = args.checkInteger(0) - 1
|
||||||
val y = args.checkInteger(1) - 1
|
val y = args.checkInteger(1) - 1
|
||||||
screen(s => {
|
screen(s => {
|
||||||
val char = s.get(x, y)
|
result(s.get(x, y), s.getForegroundColor, s.getBackgroundColor, s.isForegroundFromPalette, s.isBackgroundFromPalette)
|
||||||
val color = s.color(y)(x)
|
|
||||||
val format = s.format
|
|
||||||
val foreground = PackedColor.unpackForeground(color, format)
|
|
||||||
val background = PackedColor.unpackBackground(color, format)
|
|
||||||
result(char, foreground, background)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,15 +235,14 @@ abstract class GraphicsCard extends ManagedComponent {
|
|||||||
if (message.name == "computer.stopped" && node.isNeighborOf(message.source)) {
|
if (message.name == "computer.stopped" && node.isNeighborOf(message.source)) {
|
||||||
screenInstance match {
|
screenInstance match {
|
||||||
case Some(buffer) => buffer.synchronized {
|
case Some(buffer) => buffer.synchronized {
|
||||||
val (w, h) = buffer.resolution
|
val w = buffer.getWidth
|
||||||
buffer.foreground = PackedColor.Color(0xFFFFFF)
|
val h = buffer.getHeight
|
||||||
|
buffer.setForegroundColor(0xFFFFFF)
|
||||||
message.source.host match {
|
message.source.host match {
|
||||||
case machine: machine.Machine if machine.lastError != null =>
|
case machine: machine.Machine if machine.lastError != null =>
|
||||||
if (buffer.format.depth > PackedColor.Depth.OneBit) buffer.background = PackedColor.Color(0x0000FF)
|
if (buffer.getColorDepth.ordinal > ColorDepth.OneBit.ordinal) buffer.setBackgroundColor(0x0000FF)
|
||||||
else buffer.background = PackedColor.Color(0x000000)
|
else buffer.setBackgroundColor(0x000000)
|
||||||
if (buffer.buffer.fill(0, 0, w, h, ' ')) {
|
buffer.fill(0, 0, w, h, ' ')
|
||||||
buffer.owner.onScreenFill(0, 0, w, h, ' ')
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
val message = "Unrecoverable error:\n" + StatCollector.translateToLocal(machine.lastError) + "\n"
|
val message = "Unrecoverable error:\n" + StatCollector.translateToLocal(machine.lastError) + "\n"
|
||||||
val wrapRegEx = s"(.{1,${math.max(1, w - 2)}})\\s".r
|
val wrapRegEx = s"(.{1,${math.max(1, w - 2)}})\\s".r
|
||||||
@ -254,18 +250,15 @@ abstract class GraphicsCard extends ManagedComponent {
|
|||||||
for ((line, idx) <- lines.zipWithIndex) {
|
for ((line, idx) <- lines.zipWithIndex) {
|
||||||
val col = (w - line.length) / 2
|
val col = (w - line.length) / 2
|
||||||
val row = (h - lines.length) / 2 + idx
|
val row = (h - lines.length) / 2 + idx
|
||||||
buffer.buffer.set(col, row, line)
|
buffer.set(col, row, line)
|
||||||
buffer.owner.onScreenSet(col, row, line)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
case t: Throwable => t.printStackTrace()
|
case t: Throwable => t.printStackTrace()
|
||||||
}
|
}
|
||||||
case _ =>
|
case _ =>
|
||||||
buffer.background = PackedColor.Color(0x000000)
|
buffer.setBackgroundColor(0x000000)
|
||||||
if (buffer.buffer.fill(0, 0, w, h, ' ')) {
|
buffer.fill(0, 0, w, h, ' ')
|
||||||
buffer.owner.onScreenFill(0, 0, w, h, ' ')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case _ =>
|
case _ =>
|
||||||
@ -319,8 +312,8 @@ object GraphicsCard {
|
|||||||
// the save file - a Bad Thing (TM).
|
// the save file - a Bad Thing (TM).
|
||||||
|
|
||||||
class Tier1 extends GraphicsCard {
|
class Tier1 extends GraphicsCard {
|
||||||
val maxDepth = Settings.screenDepthsByTier(0)
|
protected val maxDepth = Settings.screenDepthsByTier(0)
|
||||||
val maxResolution = Settings.screenResolutionsByTier(0)
|
protected val maxResolution = Settings.screenResolutionsByTier(0)
|
||||||
|
|
||||||
@Callback(direct = true, limit = 1)
|
@Callback(direct = true, limit = 1)
|
||||||
override def copy(context: Context, args: Arguments) = super.copy(context, args)
|
override def copy(context: Context, args: Arguments) = super.copy(context, args)
|
||||||
@ -339,8 +332,8 @@ object GraphicsCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Tier2 extends GraphicsCard {
|
class Tier2 extends GraphicsCard {
|
||||||
val maxDepth = Settings.screenDepthsByTier(1)
|
protected val maxDepth = Settings.screenDepthsByTier(1)
|
||||||
val maxResolution = Settings.screenResolutionsByTier(1)
|
protected val maxResolution = Settings.screenResolutionsByTier(1)
|
||||||
|
|
||||||
@Callback(direct = true, limit = 2)
|
@Callback(direct = true, limit = 2)
|
||||||
override def copy(context: Context, args: Arguments) = super.copy(context, args)
|
override def copy(context: Context, args: Arguments) = super.copy(context, args)
|
||||||
@ -359,8 +352,8 @@ object GraphicsCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Tier3 extends GraphicsCard {
|
class Tier3 extends GraphicsCard {
|
||||||
val maxDepth = Settings.screenDepthsByTier(2)
|
protected val maxDepth = Settings.screenDepthsByTier(2)
|
||||||
val maxResolution = Settings.screenResolutionsByTier(2)
|
protected val maxResolution = Settings.screenResolutionsByTier(2)
|
||||||
|
|
||||||
@Callback(direct = true, limit = 4)
|
@Callback(direct = true, limit = 4)
|
||||||
override def copy(context: Context, args: Arguments) = super.copy(context, args)
|
override def copy(context: Context, args: Arguments) = super.copy(context, args)
|
||||||
|
@ -5,16 +5,17 @@ import java.net._
|
|||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import java.nio.channels.SocketChannel
|
import java.nio.channels.SocketChannel
|
||||||
import java.util.regex.Matcher
|
import java.util.regex.Matcher
|
||||||
|
import li.cil.oc.{OpenComputers, Settings}
|
||||||
import li.cil.oc.api
|
import li.cil.oc.api
|
||||||
import li.cil.oc.api.Network
|
import li.cil.oc.api.Network
|
||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
|
import li.cil.oc.api.prefab.AbstractValue
|
||||||
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
import li.cil.oc.util.ExtendedNBT._
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
import li.cil.oc.util.ThreadPoolFactory
|
import li.cil.oc.util.ThreadPoolFactory
|
||||||
import li.cil.oc.{OpenComputers, Settings}
|
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
import net.minecraft.server.MinecraftServer
|
import net.minecraft.server.MinecraftServer
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import li.cil.oc.api.prefab.AbstractValue
|
|
||||||
|
|
||||||
class InternetCard extends ManagedComponent {
|
class InternetCard extends ManagedComponent {
|
||||||
val node = Network.newNode(this, Visibility.Network).
|
val node = Network.newNode(this, Visibility.Network).
|
||||||
|
@ -2,23 +2,31 @@ package li.cil.oc.server.component
|
|||||||
|
|
||||||
import cpw.mods.fml.common.IPlayerTracker
|
import cpw.mods.fml.common.IPlayerTracker
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
|
import li.cil.oc.api
|
||||||
import li.cil.oc.api.Network
|
import li.cil.oc.api.Network
|
||||||
|
import li.cil.oc.api.component.Keyboard.UsabilityChecker
|
||||||
import li.cil.oc.api.network.{Node, Visibility, Message}
|
import li.cil.oc.api.network.{Node, Visibility, Message}
|
||||||
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
import net.minecraft.entity.player.EntityPlayer
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
import net.minecraftforge.common.MinecraftForge
|
import net.minecraftforge.common.MinecraftForge
|
||||||
import net.minecraftforge.event.{Event, ForgeSubscribe}
|
import net.minecraftforge.event.{Event, ForgeSubscribe}
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
|
import li.cil.oc.server.component
|
||||||
|
|
||||||
// TODO key up when screen is disconnected from which the key down came
|
// TODO key up when screen is disconnected from which the key down came
|
||||||
// TODO key up after load for anything that was pressed
|
// TODO key up after load for anything that was pressed
|
||||||
|
|
||||||
abstract class Keyboard extends ManagedComponent {
|
class Keyboard(val owner: component.Container) extends ManagedComponent with api.component.Keyboard {
|
||||||
val node = Network.newNode(this, Visibility.Network).
|
val node = Network.newNode(this, Visibility.Network).
|
||||||
withComponent("keyboard").
|
withComponent("keyboard").
|
||||||
create()
|
create()
|
||||||
|
|
||||||
val pressedKeys = mutable.Map.empty[EntityPlayer, mutable.Map[Integer, Character]]
|
val pressedKeys = mutable.Map.empty[EntityPlayer, mutable.Map[Integer, Character]]
|
||||||
|
|
||||||
|
var usableOverride: Option[api.component.Keyboard.UsabilityChecker] = None
|
||||||
|
|
||||||
|
override def setUsableOverride(callback: UsabilityChecker) = usableOverride = Option(callback)
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
@ForgeSubscribe
|
@ForgeSubscribe
|
||||||
@ -92,7 +100,10 @@ abstract class Keyboard extends ManagedComponent {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
def isUseableByPlayer(p: EntityPlayer): Boolean
|
def isUseableByPlayer(p: EntityPlayer) = usableOverride match {
|
||||||
|
case Some(callback) => callback.isUsableByPlayer(this, p)
|
||||||
|
case _ => p.getDistanceSq(owner.x + 0.5, owner.y + 0.5, owner.z + 0.5) <= 64
|
||||||
|
}
|
||||||
|
|
||||||
protected def signal(args: AnyRef*) =
|
protected def signal(args: AnyRef*) =
|
||||||
node.sendToReachable("computer.checked_signal", args: _*)
|
node.sendToReachable("computer.checked_signal", args: _*)
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package li.cil.oc.server.component
|
package li.cil.oc.server.component
|
||||||
|
|
||||||
|
import li.cil.oc.Settings
|
||||||
import li.cil.oc.api.Network
|
import li.cil.oc.api.Network
|
||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
import scala.collection.convert.WrapAsScala._
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
import li.cil.oc.Settings
|
|
||||||
import li.cil.oc.server.network.QuantumNetwork
|
import li.cil.oc.server.network.QuantumNetwork
|
||||||
|
import scala.collection.convert.WrapAsScala._
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
|
||||||
class LinkedCard extends ManagedComponent {
|
class LinkedCard extends ManagedComponent {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package li.cil.oc.server.component
|
package li.cil.oc.server.component
|
||||||
|
|
||||||
|
import li.cil.oc.Settings
|
||||||
import li.cil.oc.api
|
import li.cil.oc.api
|
||||||
import li.cil.oc.api.Network
|
import li.cil.oc.api.Network
|
||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
import li.cil.oc.util.ExtendedNBT._
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
import net.minecraft.nbt._
|
import net.minecraft.nbt._
|
||||||
import scala.collection.convert.WrapAsScala._
|
import scala.collection.convert.WrapAsScala._
|
||||||
|
@ -2,8 +2,9 @@ package li.cil.oc.server.component
|
|||||||
|
|
||||||
import li.cil.oc.api.Network
|
import li.cil.oc.api.Network
|
||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
import net.minecraftforge.common.ForgeDirection
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
import li.cil.oc.common.tileentity.traits.RedstoneAware
|
import li.cil.oc.common.tileentity.traits.RedstoneAware
|
||||||
|
import net.minecraftforge.common.ForgeDirection
|
||||||
|
|
||||||
class Redstone(val owner: RedstoneAware) extends ManagedComponent {
|
class Redstone(val owner: RedstoneAware) extends ManagedComponent {
|
||||||
val node = Network.newNode(this, Visibility.Network).
|
val node = Network.newNode(this, Visibility.Network).
|
||||||
|
@ -2,6 +2,7 @@ package li.cil.oc.server.component
|
|||||||
|
|
||||||
import li.cil.oc.api.Network
|
import li.cil.oc.api.Network
|
||||||
import li.cil.oc.api.network.Visibility
|
import li.cil.oc.api.network.Visibility
|
||||||
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
|
|
||||||
class UpgradeAngel extends ManagedComponent {
|
class UpgradeAngel extends ManagedComponent {
|
||||||
val node = Network.newNode(this, Visibility.Network).
|
val node = Network.newNode(this, Visibility.Network).
|
||||||
|
@ -4,8 +4,9 @@ import cpw.mods.fml.common.registry.GameRegistry
|
|||||||
import li.cil.oc.api.Network
|
import li.cil.oc.api.Network
|
||||||
import li.cil.oc.api.machine.Robot
|
import li.cil.oc.api.machine.Robot
|
||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
import net.minecraft.entity.player.EntityPlayer
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
import net.minecraft.inventory.{Container, InventoryCrafting}
|
import net.minecraft.inventory
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.item.crafting.CraftingManager
|
import net.minecraft.item.crafting.CraftingManager
|
||||||
import net.minecraft.tileentity.TileEntity
|
import net.minecraft.tileentity.TileEntity
|
||||||
@ -24,7 +25,7 @@ class UpgradeCrafting(val owner: TileEntity with Robot) extends ManagedComponent
|
|||||||
result(CraftingInventory.craft(count))
|
result(CraftingInventory.craft(count))
|
||||||
}
|
}
|
||||||
|
|
||||||
private object CraftingInventory extends InventoryCrafting(new Container {
|
private object CraftingInventory extends inventory.InventoryCrafting(new inventory.Container {
|
||||||
override def canInteractWith(player: EntityPlayer) = true
|
override def canInteractWith(player: EntityPlayer) = true
|
||||||
}, 3, 3) {
|
}, 3, 3) {
|
||||||
var amountPossible = 0
|
var amountPossible = 0
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package li.cil.oc.server.component
|
package li.cil.oc.server.component
|
||||||
|
|
||||||
|
import li.cil.oc.{OpenComputers, Settings, api}
|
||||||
import li.cil.oc.api.Network
|
import li.cil.oc.api.Network
|
||||||
import li.cil.oc.api.machine.Robot
|
import li.cil.oc.api.machine.Robot
|
||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
import li.cil.oc.util.ExtendedNBT._
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
import li.cil.oc.{OpenComputers, api, Settings}
|
|
||||||
import net.minecraft.entity.item.EntityItem
|
import net.minecraft.entity.item.EntityItem
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package li.cil.oc.server.component
|
package li.cil.oc.server.component
|
||||||
|
|
||||||
import li.cil.oc.api.network._
|
|
||||||
import li.cil.oc.api.{Rotatable, Network}
|
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
|
import li.cil.oc.api.{Rotatable, Network}
|
||||||
|
import li.cil.oc.api.network._
|
||||||
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
import li.cil.oc.util.ExtendedNBT._
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
import net.minecraft.tileentity.TileEntity
|
import net.minecraft.tileentity.TileEntity
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package li.cil.oc.server.component
|
package li.cil.oc.server.component
|
||||||
|
|
||||||
import li.cil.oc.api.network._
|
|
||||||
import li.cil.oc.api.{Rotatable, Network}
|
import li.cil.oc.api.{Rotatable, Network}
|
||||||
|
import li.cil.oc.api.network._
|
||||||
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
import net.minecraft.tileentity.{TileEntity, TileEntitySign}
|
import net.minecraft.tileentity.{TileEntity, TileEntitySign}
|
||||||
|
|
||||||
class UpgradeSign(val owner: TileEntity) extends ManagedComponent {
|
class UpgradeSign(val owner: TileEntity) extends ManagedComponent {
|
||||||
|
@ -3,6 +3,7 @@ package li.cil.oc.server.component
|
|||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
import li.cil.oc.api.Network
|
import li.cil.oc.api.Network
|
||||||
import li.cil.oc.api.network.Visibility
|
import li.cil.oc.api.network.Visibility
|
||||||
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
import net.minecraft.tileentity.TileEntity
|
import net.minecraft.tileentity.TileEntity
|
||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
import net.minecraft.world.biome.BiomeGenDesert
|
import net.minecraft.world.biome.BiomeGenDesert
|
||||||
|
@ -10,7 +10,6 @@ import li.cil.oc.api.network._
|
|||||||
import li.cil.oc.api.{fs, machine, FileSystem, Network}
|
import li.cil.oc.api.{fs, machine, FileSystem, Network}
|
||||||
import li.cil.oc.common.tileentity
|
import li.cil.oc.common.tileentity
|
||||||
import li.cil.oc.server
|
import li.cil.oc.server
|
||||||
import li.cil.oc.server.component.ManagedComponent
|
|
||||||
import li.cil.oc.server.fs.CompositeReadOnlyFileSystem
|
import li.cil.oc.server.fs.CompositeReadOnlyFileSystem
|
||||||
import li.cil.oc.server.PacketSender
|
import li.cil.oc.server.PacketSender
|
||||||
import li.cil.oc.util.ExtendedNBT._
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
@ -26,6 +25,7 @@ import scala.Some
|
|||||||
import li.cil.oc.server.network.{ArgumentsImpl, Callbacks}
|
import li.cil.oc.server.network.{ArgumentsImpl, Callbacks}
|
||||||
import li.cil.oc.server.driver.Registry
|
import li.cil.oc.server.driver.Registry
|
||||||
import net.minecraft.entity.player.EntityPlayer
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
|
|
||||||
class Machine(val owner: Owner, val rom: Option[ManagedEnvironment], constructor: Constructor[_ <: Architecture]) extends ManagedComponent with machine.Machine with Runnable {
|
class Machine(val owner: Owner, val rom: Option[ManagedEnvironment], constructor: Constructor[_ <: Architecture]) extends ManagedComponent with machine.Machine with Runnable {
|
||||||
val node = Network.newNode(this, Visibility.Network).
|
val node = Network.newNode(this, Visibility.Network).
|
||||||
|
@ -3,7 +3,6 @@ package li.cil.oc.server.component.robot
|
|||||||
import li.cil.oc.{Items, api, OpenComputers, Settings}
|
import li.cil.oc.{Items, api, OpenComputers, Settings}
|
||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
import li.cil.oc.common.tileentity
|
import li.cil.oc.common.tileentity
|
||||||
import li.cil.oc.server.component.ManagedComponent
|
|
||||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||||
import li.cil.oc.util.ExtendedNBT._
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
import net.minecraft.block.{BlockFluid, Block}
|
import net.minecraft.block.{BlockFluid, Block}
|
||||||
@ -18,6 +17,7 @@ import net.minecraftforge.common.{MinecraftForge, ForgeDirection}
|
|||||||
import net.minecraftforge.event.world.BlockEvent
|
import net.minecraftforge.event.world.BlockEvent
|
||||||
import net.minecraftforge.fluids.FluidRegistry
|
import net.minecraftforge.fluids.FluidRegistry
|
||||||
import scala.collection.convert.WrapAsScala._
|
import scala.collection.convert.WrapAsScala._
|
||||||
|
import li.cil.oc.common.component.ManagedComponent
|
||||||
|
|
||||||
class Robot(val robot: tileentity.Robot) extends ManagedComponent {
|
class Robot(val robot: tileentity.Robot) extends ManagedComponent {
|
||||||
val node = api.Network.newNode(this, Visibility.Neighbors).
|
val node = api.Network.newNode(this, Visibility.Neighbors).
|
||||||
|
@ -5,13 +5,12 @@ import li.cil.oc.api.driver.Slot
|
|||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import li.cil.oc.util.mods.Mods
|
import li.cil.oc.util.mods.Mods
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.TileEntity
|
|
||||||
import stargatetech2.api.bus.IBusDevice
|
import stargatetech2.api.bus.IBusDevice
|
||||||
|
|
||||||
object AbstractBusCard extends Item {
|
object AbstractBusCard extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("abstractBusCard"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("abstractBusCard"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) = if (Mods.StargateTech2.isAvailable) container match {
|
override def createEnvironment(stack: ItemStack, container: component.Container) = if (Mods.StargateTech2.isAvailable) container match {
|
||||||
case device: IBusDevice => new component.AbstractBus(device)
|
case device: IBusDevice => new component.AbstractBus(device)
|
||||||
case _ => null
|
case _ => null
|
||||||
}
|
}
|
||||||
|
@ -7,16 +7,16 @@ import li.cil.oc.api.fs.Label
|
|||||||
import li.cil.oc.util.mods.{ComputerCraft15, Mods}
|
import li.cil.oc.util.mods.{ComputerCraft15, Mods}
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
import net.minecraft.tileentity.TileEntity
|
import li.cil.oc.server.component
|
||||||
|
|
||||||
object CC15Media extends Item {
|
object CC15Media extends Item {
|
||||||
override def slot(stack: ItemStack) = Slot.Disk
|
override def slot(stack: ItemStack) = Slot.Disk
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) =
|
override def createEnvironment(stack: ItemStack, container: component.Container) =
|
||||||
if (Mods.ComputerCraft15.isAvailable && ComputerCraft15.isDisk(stack) && container != null) {
|
if (Mods.ComputerCraft15.isAvailable && ComputerCraft15.isDisk(stack) && container != null) {
|
||||||
val address = addressFromTag(dataTag(stack))
|
val address = addressFromTag(dataTag(stack))
|
||||||
val mount = ComputerCraft15.createDiskMount(stack, container.getWorldObj)
|
val mount = ComputerCraft15.createDiskMount(stack, container.world)
|
||||||
Option(oc.api.FileSystem.asManagedEnvironment(mount, new ComputerCraftLabel(stack), container)) match {
|
Option(oc.api.FileSystem.asManagedEnvironment(mount, new ComputerCraftLabel(stack), container.tileEntity.orNull)) match {
|
||||||
case Some(environment) =>
|
case Some(environment) =>
|
||||||
environment.node.asInstanceOf[oc.server.network.Node].address = address
|
environment.node.asInstanceOf[oc.server.network.Node].address = address
|
||||||
environment
|
environment
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
package li.cil.oc.server.driver.item
|
package li.cil.oc.server.driver.item
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.TileEntity
|
|
||||||
import li.cil.oc.util.mods.{ComputerCraft16, Mods}
|
import li.cil.oc.util.mods.{ComputerCraft16, Mods}
|
||||||
import li.cil.oc
|
import li.cil.oc
|
||||||
import li.cil.oc.api.fs.Label
|
import li.cil.oc.api.fs.Label
|
||||||
import dan200.computercraft.api.media.IMedia
|
import dan200.computercraft.api.media.IMedia
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
import li.cil.oc.api.driver.Slot
|
import li.cil.oc.api.driver.Slot
|
||||||
|
import li.cil.oc.server.component
|
||||||
|
|
||||||
object CC16Media extends Item {
|
object CC16Media extends Item {
|
||||||
override def slot(stack: ItemStack) = Slot.Disk
|
override def slot(stack: ItemStack) = Slot.Disk
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) =
|
override def createEnvironment(stack: ItemStack, container: component.Container) =
|
||||||
if (Mods.ComputerCraft16.isAvailable && ComputerCraft16.isDisk(stack) && container != null) {
|
if (Mods.ComputerCraft16.isAvailable && ComputerCraft16.isDisk(stack) && container != null) {
|
||||||
val address = addressFromTag(dataTag(stack))
|
val address = addressFromTag(dataTag(stack))
|
||||||
val mount = ComputerCraft16.createDiskMount(stack, container.getWorldObj)
|
val mount = ComputerCraft16.createDiskMount(stack, container.world)
|
||||||
Option(oc.api.FileSystem.asManagedEnvironment(mount, new ComputerCraftLabel(stack), container)) match {
|
Option(oc.api.FileSystem.asManagedEnvironment(mount, new ComputerCraftLabel(stack), container.tileEntity.orNull)) match {
|
||||||
case Some(environment) =>
|
case Some(environment) =>
|
||||||
environment.node.asInstanceOf[oc.server.network.Node].address = address
|
environment.node.asInstanceOf[oc.server.network.Node].address = address
|
||||||
environment
|
environment
|
||||||
|
@ -7,13 +7,13 @@ import li.cil.oc.common.item.{FloppyDisk, HardDiskDrive}
|
|||||||
import li.cil.oc.{api, Settings, Items}
|
import li.cil.oc.{api, Settings, Items}
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
import net.minecraft.tileentity.TileEntity
|
import li.cil.oc.server.component
|
||||||
|
|
||||||
object FileSystem extends Item {
|
object FileSystem extends Item {
|
||||||
override def worksWith(stack: ItemStack) =
|
override def worksWith(stack: ItemStack) =
|
||||||
isOneOf(stack, api.Items.get("hdd1"), api.Items.get("hdd2"), api.Items.get("hdd3"), api.Items.get("floppy"))
|
isOneOf(stack, api.Items.get("hdd1"), api.Items.get("hdd2"), api.Items.get("hdd3"), api.Items.get("floppy"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) =
|
override def createEnvironment(stack: ItemStack, container: component.Container) =
|
||||||
Items.multi.subItem(stack) match {
|
Items.multi.subItem(stack) match {
|
||||||
case Some(hdd: HardDiskDrive) => createEnvironment(stack, hdd.kiloBytes * 1024, container)
|
case Some(hdd: HardDiskDrive) => createEnvironment(stack, hdd.kiloBytes * 1024, container)
|
||||||
case Some(disk: FloppyDisk) => createEnvironment(stack, Settings.get.floppySize * 1024, container)
|
case Some(disk: FloppyDisk) => createEnvironment(stack, Settings.get.floppySize * 1024, container)
|
||||||
@ -33,13 +33,13 @@ object FileSystem extends Item {
|
|||||||
case _ => 0
|
case _ => 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private def createEnvironment(stack: ItemStack, capacity: Int, container: TileEntity) = {
|
private def createEnvironment(stack: ItemStack, capacity: Int, container: component.Container) = {
|
||||||
// We have a bit of a chicken-egg problem here, because we want to use the
|
// We have a bit of a chicken-egg problem here, because we want to use the
|
||||||
// node's address as the folder name... so we generate the address here,
|
// node's address as the folder name... so we generate the address here,
|
||||||
// if necessary. No one will know, right? Right!?
|
// if necessary. No one will know, right? Right!?
|
||||||
val address = addressFromTag(dataTag(stack))
|
val address = addressFromTag(dataTag(stack))
|
||||||
val fs = oc.api.FileSystem.fromSaveDirectory(address, capacity, Settings.get.bufferChanges)
|
val fs = oc.api.FileSystem.fromSaveDirectory(address, capacity, Settings.get.bufferChanges)
|
||||||
val environment = oc.api.FileSystem.asManagedEnvironment(fs, new ItemLabel(stack), container)
|
val environment = oc.api.FileSystem.asManagedEnvironment(fs, new ItemLabel(stack), container.tileEntity.orNull)
|
||||||
if (environment != null) {
|
if (environment != null) {
|
||||||
environment.node.asInstanceOf[oc.server.network.Node].address = address
|
environment.node.asInstanceOf[oc.server.network.Node].address = address
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,11 @@ import li.cil.oc.{api, Items, common}
|
|||||||
import li.cil.oc.api.driver.Slot
|
import li.cil.oc.api.driver.Slot
|
||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
|
|
||||||
|
|
||||||
object GraphicsCard extends Item {
|
object GraphicsCard extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("graphicsCard1"), api.Items.get("graphicsCard2"), api.Items.get("graphicsCard3"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("graphicsCard1"), api.Items.get("graphicsCard2"), api.Items.get("graphicsCard3"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: MCTileEntity) =
|
override def createEnvironment(stack: ItemStack, container: component.Container) =
|
||||||
Items.multi.subItem(stack) match {
|
Items.multi.subItem(stack) match {
|
||||||
case Some(gpu: common.item.GraphicsCard) => gpu.tier match {
|
case Some(gpu: common.item.GraphicsCard) => gpu.tier match {
|
||||||
case 0 => new component.GraphicsCard.Tier1()
|
case 0 => new component.GraphicsCard.Tier1()
|
||||||
|
@ -4,12 +4,11 @@ import li.cil.oc.api
|
|||||||
import li.cil.oc.api.driver.Slot
|
import li.cil.oc.api.driver.Slot
|
||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.TileEntity
|
|
||||||
|
|
||||||
object InternetCard extends Item {
|
object InternetCard extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("internetCard"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("internetCard"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) = new component.InternetCard()
|
override def createEnvironment(stack: ItemStack, container: component.Container) = new component.InternetCard()
|
||||||
|
|
||||||
override def slot(stack: ItemStack) = Slot.Card
|
override def slot(stack: ItemStack) = Slot.Card
|
||||||
|
|
||||||
|
@ -5,6 +5,11 @@ import li.cil.oc.api.driver
|
|||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
import net.minecraft.tileentity.TileEntity
|
||||||
|
import li.cil.oc.api.network.ManagedEnvironment
|
||||||
|
import li.cil.oc.server.component.Container
|
||||||
|
import li.cil.oc.server.component.Container.{EntityContainer, TileEntityContainer}
|
||||||
|
import net.minecraft.entity.Entity
|
||||||
|
|
||||||
trait Item extends driver.Item {
|
trait Item extends driver.Item {
|
||||||
override def tier(stack: ItemStack) = 0
|
override def tier(stack: ItemStack) = 0
|
||||||
@ -12,6 +17,12 @@ trait Item extends driver.Item {
|
|||||||
override def dataTag(stack: ItemStack) = Item.dataTag(stack)
|
override def dataTag(stack: ItemStack) = Item.dataTag(stack)
|
||||||
|
|
||||||
protected def isOneOf(stack: ItemStack, items: api.detail.ItemInfo*) = items.contains(api.Items.get(stack))
|
protected def isOneOf(stack: ItemStack, items: api.detail.ItemInfo*) = items.contains(api.Items.get(stack))
|
||||||
|
|
||||||
|
final override def createEnvironment(stack: ItemStack, container: TileEntity) = createEnvironment(stack, TileEntityContainer(container))
|
||||||
|
|
||||||
|
final override def createEnvironment(stack: ItemStack, container: Entity) = createEnvironment(stack, EntityContainer(container))
|
||||||
|
|
||||||
|
protected def createEnvironment(stack: ItemStack, container: Container): ManagedEnvironment
|
||||||
}
|
}
|
||||||
|
|
||||||
object Item {
|
object Item {
|
||||||
|
15
src/main/scala/li/cil/oc/server/driver/item/Keyboard.scala
Normal file
15
src/main/scala/li/cil/oc/server/driver/item/Keyboard.scala
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package li.cil.oc.server.driver.item
|
||||||
|
|
||||||
|
import li.cil.oc.api
|
||||||
|
import li.cil.oc.api.driver.Slot
|
||||||
|
import li.cil.oc.server.component
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
|
||||||
|
object Keyboard extends Item {
|
||||||
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("keyboard"))
|
||||||
|
|
||||||
|
override def createEnvironment(stack: ItemStack, container: component.Container) = new component.Keyboard(container)
|
||||||
|
|
||||||
|
// Only allow programmatic 'installation' of the keyboard as an item.
|
||||||
|
override def slot(stack: ItemStack) = Slot.None
|
||||||
|
}
|
@ -4,12 +4,11 @@ import li.cil.oc.api
|
|||||||
import li.cil.oc.api.driver.Slot
|
import li.cil.oc.api.driver.Slot
|
||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.TileEntity
|
|
||||||
|
|
||||||
object LinkedCard extends Item {
|
object LinkedCard extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("linkedCard"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("linkedCard"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) = new component.LinkedCard()
|
override def createEnvironment(stack: ItemStack, container: component.Container) = new component.LinkedCard()
|
||||||
|
|
||||||
override def slot(stack: ItemStack) = Slot.Card
|
override def slot(stack: ItemStack) = Slot.Card
|
||||||
|
|
||||||
|
@ -4,19 +4,19 @@ import li.cil.oc
|
|||||||
import li.cil.oc.api.driver.Slot
|
import li.cil.oc.api.driver.Slot
|
||||||
import li.cil.oc.{api, OpenComputers, Settings}
|
import li.cil.oc.{api, OpenComputers, Settings}
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.TileEntity
|
import li.cil.oc.server.component
|
||||||
|
|
||||||
object Loot extends Item {
|
object Loot extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("lootDisk"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("lootDisk"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) =
|
override def createEnvironment(stack: ItemStack, container: component.Container) =
|
||||||
createEnvironment(stack, 0, container)
|
createEnvironment(stack, 0, container)
|
||||||
|
|
||||||
override def slot(stack: ItemStack) = Slot.Disk
|
override def slot(stack: ItemStack) = Slot.Disk
|
||||||
|
|
||||||
override def tier(stack: ItemStack) = 0
|
override def tier(stack: ItemStack) = 0
|
||||||
|
|
||||||
private def createEnvironment(stack: ItemStack, capacity: Int, container: TileEntity) = {
|
private def createEnvironment(stack: ItemStack, capacity: Int, container: component.Container) = {
|
||||||
if (stack.hasTagCompound) {
|
if (stack.hasTagCompound) {
|
||||||
val path = "loot/" + stack.getTagCompound.getString(Settings.namespace + "lootPath")
|
val path = "loot/" + stack.getTagCompound.getString(Settings.namespace + "lootPath")
|
||||||
val label =
|
val label =
|
||||||
@ -25,7 +25,7 @@ object Loot extends Item {
|
|||||||
}
|
}
|
||||||
else null
|
else null
|
||||||
val fs = oc.api.FileSystem.fromClass(OpenComputers.getClass, Settings.resourceDomain, path)
|
val fs = oc.api.FileSystem.fromClass(OpenComputers.getClass, Settings.resourceDomain, path)
|
||||||
oc.api.FileSystem.asManagedEnvironment(fs, label, container)
|
oc.api.FileSystem.asManagedEnvironment(fs, label, container.tileEntity.orNull)
|
||||||
}
|
}
|
||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@ import li.cil.oc.{api, Items}
|
|||||||
import li.cil.oc.api.driver
|
import li.cil.oc.api.driver
|
||||||
import li.cil.oc.api.driver.Slot
|
import li.cil.oc.api.driver.Slot
|
||||||
import li.cil.oc.common.item
|
import li.cil.oc.common.item
|
||||||
|
import li.cil.oc.server.component
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.TileEntity
|
|
||||||
|
|
||||||
object Memory extends Item with driver.Memory {
|
object Memory extends Item with driver.Memory {
|
||||||
override def amount(stack: ItemStack) = Items.multi.subItem(stack) match {
|
override def amount(stack: ItemStack) = Items.multi.subItem(stack) match {
|
||||||
@ -15,7 +15,7 @@ object Memory extends Item with driver.Memory {
|
|||||||
|
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("ram1"), api.Items.get("ram2"), api.Items.get("ram3"), api.Items.get("ram4"), api.Items.get("ram5"), api.Items.get("ram6"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("ram1"), api.Items.get("ram2"), api.Items.get("ram3"), api.Items.get("ram4"), api.Items.get("ram5"), api.Items.get("ram6"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) = null
|
override def createEnvironment(stack: ItemStack, container: component.Container) = null
|
||||||
|
|
||||||
override def slot(stack: ItemStack) = Slot.Memory
|
override def slot(stack: ItemStack) = Slot.Memory
|
||||||
|
|
||||||
|
@ -4,12 +4,11 @@ import li.cil.oc.api
|
|||||||
import li.cil.oc.api.driver.Slot
|
import li.cil.oc.api.driver.Slot
|
||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
|
|
||||||
|
|
||||||
object NetworkCard extends Item {
|
object NetworkCard extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("lanCard"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("lanCard"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: MCTileEntity) = new component.NetworkCard()
|
override def createEnvironment(stack: ItemStack, container: component.Container) = new component.NetworkCard()
|
||||||
|
|
||||||
override def slot(stack: ItemStack) = Slot.Card
|
override def slot(stack: ItemStack) = Slot.Card
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
package li.cil.oc.server.driver.item
|
package li.cil.oc.server.driver.item
|
||||||
|
|
||||||
|
import li.cil.oc.{api, Settings, Items}
|
||||||
import li.cil.oc.api.driver
|
import li.cil.oc.api.driver
|
||||||
import li.cil.oc.api.driver.Slot
|
import li.cil.oc.api.driver.Slot
|
||||||
import li.cil.oc.common.item
|
import li.cil.oc.common.item
|
||||||
import li.cil.oc.{api, Settings, Items}
|
import li.cil.oc.server.component
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.TileEntity
|
|
||||||
|
|
||||||
object Processor extends Item with driver.Processor {
|
object Processor extends Item with driver.Processor {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("cpu1"), api.Items.get("cpu2"), api.Items.get("cpu3"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("cpu1"), api.Items.get("cpu2"), api.Items.get("cpu3"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) = null
|
override def createEnvironment(stack: ItemStack, container: component.Container) = null
|
||||||
|
|
||||||
override def slot(stack: ItemStack) = Slot.Processor
|
override def slot(stack: ItemStack) = Slot.Processor
|
||||||
|
|
||||||
|
@ -5,16 +5,15 @@ import li.cil.oc.api.driver.Slot
|
|||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import li.cil.oc.util.mods.BundledRedstone
|
import li.cil.oc.util.mods.BundledRedstone
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
|
|
||||||
import li.cil.oc.common.tileentity.traits.{RedstoneAware, BundledRedstoneAware}
|
import li.cil.oc.common.tileentity.traits.{RedstoneAware, BundledRedstoneAware}
|
||||||
|
|
||||||
object RedstoneCard extends Item {
|
object RedstoneCard extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("redstoneCard"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("redstoneCard"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: MCTileEntity) =
|
override def createEnvironment(stack: ItemStack, container: component.Container) =
|
||||||
container match {
|
container.tileEntity match {
|
||||||
case redstone: BundledRedstoneAware if BundledRedstone.isAvailable => new component.BundledRedstone(redstone)
|
case Some(redstone: BundledRedstoneAware) if BundledRedstone.isAvailable => new component.BundledRedstone(redstone)
|
||||||
case redstone: RedstoneAware => new component.Redstone(redstone)
|
case Some(redstone: RedstoneAware) => new component.Redstone(redstone)
|
||||||
case _ => null
|
case _ => null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
src/main/scala/li/cil/oc/server/driver/item/Screen.scala
Normal file
16
src/main/scala/li/cil/oc/server/driver/item/Screen.scala
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package li.cil.oc.server.driver.item
|
||||||
|
|
||||||
|
import li.cil.oc.api
|
||||||
|
import li.cil.oc.api.driver.Slot
|
||||||
|
import li.cil.oc.common.component
|
||||||
|
import li.cil.oc.server.component.Container
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
|
||||||
|
object Screen extends Item {
|
||||||
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("screen1"), api.Items.get("screen2"), api.Items.get("screen3"))
|
||||||
|
|
||||||
|
override def createEnvironment(stack: ItemStack, container: Container) = new component.TextBuffer(container)
|
||||||
|
|
||||||
|
// Only allow programmatic 'installation' of the screen as an item.
|
||||||
|
override def slot(stack: ItemStack) = Slot.None
|
||||||
|
}
|
@ -4,12 +4,11 @@ import li.cil.oc.api
|
|||||||
import li.cil.oc.api.driver.Slot
|
import li.cil.oc.api.driver.Slot
|
||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.TileEntity
|
|
||||||
|
|
||||||
object UpgradeAngel extends Item {
|
object UpgradeAngel extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("angelUpgrade"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("angelUpgrade"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) = new component.UpgradeAngel()
|
override def createEnvironment(stack: ItemStack, container: component.Container) = new component.UpgradeAngel()
|
||||||
|
|
||||||
override def slot(stack: ItemStack) = Slot.Upgrade
|
override def slot(stack: ItemStack) = Slot.Upgrade
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,13 @@ import li.cil.oc.api.driver.Slot
|
|||||||
import li.cil.oc.api.machine.Robot
|
import li.cil.oc.api.machine.Robot
|
||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.TileEntity
|
|
||||||
|
|
||||||
object UpgradeCrafting extends Item {
|
object UpgradeCrafting extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("craftingUpgrade"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("craftingUpgrade"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) =
|
override def createEnvironment(stack: ItemStack, container: component.Container) =
|
||||||
container match {
|
container.tileEntity match {
|
||||||
case robot: Robot => new component.UpgradeCrafting(robot)
|
case Some(robot: Robot) => new component.UpgradeCrafting(robot)
|
||||||
case _ => null
|
case _ => null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,14 +5,15 @@ import li.cil.oc.api.driver.Slot
|
|||||||
import li.cil.oc.api.machine.Robot
|
import li.cil.oc.api.machine.Robot
|
||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.TileEntity
|
|
||||||
|
|
||||||
object UpgradeGenerator extends Item {
|
object UpgradeGenerator extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("generatorUpgrade"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("generatorUpgrade"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) = container match {
|
override def createEnvironment(stack: ItemStack, container: component.Container) =
|
||||||
case robot: Robot => new component.UpgradeGenerator(robot)
|
container.tileEntity match {
|
||||||
}
|
case Some(robot: Robot) => new component.UpgradeGenerator(robot)
|
||||||
|
case _ => null
|
||||||
|
}
|
||||||
|
|
||||||
override def slot(stack: ItemStack) = Slot.Upgrade
|
override def slot(stack: ItemStack) = Slot.Upgrade
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,15 @@ import li.cil.oc.api.driver.Slot
|
|||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import li.cil.oc.api
|
import li.cil.oc.api
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.TileEntity
|
|
||||||
|
|
||||||
object UpgradeNavigation extends Item {
|
object UpgradeNavigation extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("navigationUpgrade"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("navigationUpgrade"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) =
|
override def createEnvironment(stack: ItemStack, container: component.Container) =
|
||||||
new component.UpgradeNavigation(container)
|
container.tileEntity match {
|
||||||
|
case Some(tileEntity) => new component.UpgradeNavigation(tileEntity)
|
||||||
|
case _ => null
|
||||||
|
}
|
||||||
|
|
||||||
override def slot(stack: ItemStack) = Slot.Upgrade
|
override def slot(stack: ItemStack) = Slot.Upgrade
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,15 @@ import li.cil.oc.api
|
|||||||
import li.cil.oc.api.driver.Slot
|
import li.cil.oc.api.driver.Slot
|
||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
|
|
||||||
|
|
||||||
object UpgradeSign extends Item {
|
object UpgradeSign extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("signUpgrade"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("signUpgrade"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: MCTileEntity) = new component.UpgradeSign(container)
|
override def createEnvironment(stack: ItemStack, container: component.Container) =
|
||||||
|
container.tileEntity match {
|
||||||
|
case Some(tileEntity) => new component.UpgradeSign(tileEntity)
|
||||||
|
case _ => null
|
||||||
|
}
|
||||||
|
|
||||||
override def slot(stack: ItemStack) = Slot.Upgrade
|
override def slot(stack: ItemStack) = Slot.Upgrade
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,15 @@ import li.cil.oc.api
|
|||||||
import li.cil.oc.api.driver.Slot
|
import li.cil.oc.api.driver.Slot
|
||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
|
|
||||||
|
|
||||||
object UpgradeSolarGenerator extends Item {
|
object UpgradeSolarGenerator extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("solarGeneratorUpgrade"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("solarGeneratorUpgrade"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: MCTileEntity) = new component.UpgradeSolarGenerator(container)
|
override def createEnvironment(stack: ItemStack, container: component.Container) =
|
||||||
|
container.tileEntity match {
|
||||||
|
case Some(tileEntity) => new component.UpgradeSolarGenerator(tileEntity)
|
||||||
|
case _ => null
|
||||||
|
}
|
||||||
|
|
||||||
override def slot(stack: ItemStack) = Slot.Upgrade
|
override def slot(stack: ItemStack) = Slot.Upgrade
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,15 @@ import li.cil.oc.api
|
|||||||
import li.cil.oc.api.driver.Slot
|
import li.cil.oc.api.driver.Slot
|
||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.tileentity.TileEntity
|
|
||||||
|
|
||||||
object WirelessNetworkCard extends Item {
|
object WirelessNetworkCard extends Item {
|
||||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("wlanCard"))
|
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("wlanCard"))
|
||||||
|
|
||||||
override def createEnvironment(stack: ItemStack, container: TileEntity) =
|
override def createEnvironment(stack: ItemStack, container: component.Container) =
|
||||||
if (container != null) new component.WirelessNetworkCard(container) else null
|
container.tileEntity match {
|
||||||
|
case Some(tileEntity) => new component.WirelessNetworkCard(tileEntity)
|
||||||
|
case _ => null
|
||||||
|
}
|
||||||
|
|
||||||
override def slot(stack: ItemStack) = Slot.Card
|
override def slot(stack: ItemStack) = Slot.Card
|
||||||
|
|
||||||
|
@ -2,22 +2,21 @@ package li.cil.oc.util
|
|||||||
|
|
||||||
import li.cil.oc.api.Persistable
|
import li.cil.oc.api.Persistable
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
import li.cil.oc.api.component.Screen.ColorDepth
|
||||||
|
|
||||||
object PackedColor {
|
object PackedColor {
|
||||||
|
|
||||||
object Depth extends Enumeration {
|
object Depth {
|
||||||
val OneBit, FourBit, EightBit = Value
|
def bits(depth: ColorDepth) = depth match {
|
||||||
|
case ColorDepth.OneBit => 1
|
||||||
def bits(depth: Depth.Value) = depth match {
|
case ColorDepth.FourBit => 4
|
||||||
case OneBit => 1
|
case ColorDepth.EightBit => 8
|
||||||
case FourBit => 4
|
|
||||||
case EightBit => 8
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def format(depth: Depth.Value) = depth match {
|
def format(depth: ColorDepth) = depth match {
|
||||||
case OneBit => SingleBitFormat
|
case ColorDepth.OneBit => SingleBitFormat
|
||||||
case FourBit => new MutablePaletteFormat
|
case ColorDepth.FourBit => new MutablePaletteFormat
|
||||||
case EightBit => new HybridFormat
|
case ColorDepth.EightBit => new HybridFormat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +32,7 @@ object PackedColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trait ColorFormat extends Persistable {
|
trait ColorFormat extends Persistable {
|
||||||
def depth: Depth.Value
|
def depth: ColorDepth
|
||||||
|
|
||||||
def inflate(value: Int): Int
|
def inflate(value: Int): Int
|
||||||
|
|
||||||
@ -45,7 +44,7 @@ object PackedColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object SingleBitFormat extends ColorFormat {
|
object SingleBitFormat extends ColorFormat {
|
||||||
override def depth = Depth.OneBit
|
override def depth = ColorDepth.OneBit
|
||||||
|
|
||||||
override def inflate(value: Int) = if (value == 0) 0x000000 else 0xFFFFFF
|
override def inflate(value: Int) = if (value == 0) 0x000000 else 0xFFFFFF
|
||||||
|
|
||||||
@ -72,7 +71,7 @@ object PackedColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class MutablePaletteFormat extends PaletteFormat {
|
class MutablePaletteFormat extends PaletteFormat {
|
||||||
override def depth = Depth.FourBit
|
override def depth = ColorDepth.FourBit
|
||||||
|
|
||||||
def apply(index: Int) = palette(index)
|
def apply(index: Int) = palette(index)
|
||||||
|
|
||||||
@ -106,7 +105,7 @@ object PackedColor {
|
|||||||
this(i) = (shade << rShift32) | (shade << gShift32) | (shade << bShift32)
|
this(i) = (shade << rShift32) | (shade << gShift32) | (shade << bShift32)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def depth = Depth.EightBit
|
override def depth = ColorDepth.EightBit
|
||||||
|
|
||||||
override def inflate(value: Int) =
|
override def inflate(value: Int) =
|
||||||
if (value < palette.length) super.inflate(value)
|
if (value < palette.length) super.inflate(value)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package li.cil.oc.util
|
package li.cil.oc.util
|
||||||
|
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
|
import li.cil.oc.api.component.Screen.ColorDepth
|
||||||
import net.minecraft.nbt._
|
import net.minecraft.nbt._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -178,7 +179,7 @@ class TextBuffer(var width: Int, var height: Int, initialFormat: PackedColor.Col
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val depth = PackedColor.Depth(nbt.getInteger("depth") max 0 min PackedColor.Depth.maxId)
|
val depth = ColorDepth.values.apply(nbt.getInteger("depth") min (ColorDepth.values.length - 1) max 0)
|
||||||
_format = PackedColor.Depth.format(depth)
|
_format = PackedColor.Depth.format(depth)
|
||||||
_format.load(nbt)
|
_format.load(nbt)
|
||||||
foreground = PackedColor.Color(nbt.getInteger("foreground"), nbt.getBoolean("foregroundIsPalette"))
|
foreground = PackedColor.Color(nbt.getInteger("foreground"), nbt.getBoolean("foregroundIsPalette"))
|
||||||
@ -209,7 +210,7 @@ class TextBuffer(var width: Int, var height: Int, initialFormat: PackedColor.Col
|
|||||||
}
|
}
|
||||||
nbt.setTag("buffer", b)
|
nbt.setTag("buffer", b)
|
||||||
|
|
||||||
nbt.setInteger("depth", _format.depth.id)
|
nbt.setInteger("depth", _format.depth.ordinal)
|
||||||
_format.save(nbt)
|
_format.save(nbt)
|
||||||
nbt.setInteger("foreground", _foreground.value)
|
nbt.setInteger("foreground", _foreground.value)
|
||||||
nbt.setBoolean("foregroundIsPalette", _foreground.isPalette)
|
nbt.setBoolean("foregroundIsPalette", _foreground.isPalette)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user