diff --git a/src/main/java/li/cil/oc/api/API.java b/src/main/java/li/cil/oc/api/API.java index 1b33af798..f6408a4a4 100644 --- a/src/main/java/li/cil/oc/api/API.java +++ b/src/main/java/li/cil/oc/api/API.java @@ -11,7 +11,7 @@ import li.cil.oc.api.detail.*; */ public class API { public static final String ID_OWNER = "OpenComputers|Core"; - public static final String VERSION = "4.1.0"; + public static final String VERSION = "4.1.1"; public static DriverAPI driver = null; public static FileSystemAPI fileSystem = null; diff --git a/src/main/java/li/cil/oc/api/internal/Drone.java b/src/main/java/li/cil/oc/api/internal/Drone.java index 75075500d..ee76ba2b6 100644 --- a/src/main/java/li/cil/oc/api/internal/Drone.java +++ b/src/main/java/li/cil/oc/api/internal/Drone.java @@ -17,7 +17,7 @@ import li.cil.oc.api.network.Environment; * i.e. without having to link against internal classes. This also means * that you should not implement this. */ -public interface Drone extends EnvironmentHost { +public interface Drone extends EnvironmentHost, Rotatable { /** * The machine currently hosted by this drone. */ diff --git a/src/main/resources/assets/opencomputers/textures/entity/drone.png b/src/main/resources/assets/opencomputers/textures/entity/drone.png deleted file mode 100644 index d26229b5c..000000000 Binary files a/src/main/resources/assets/opencomputers/textures/entity/drone.png and /dev/null differ diff --git a/src/main/resources/assets/opencomputers/textures/model/drone.png b/src/main/resources/assets/opencomputers/textures/model/drone.png new file mode 100644 index 000000000..f8074e3cd Binary files /dev/null and b/src/main/resources/assets/opencomputers/textures/model/drone.png differ diff --git a/src/main/scala/li/cil/oc/client/renderer/entity/ModelQuadcopter.scala b/src/main/scala/li/cil/oc/client/renderer/entity/ModelQuadcopter.scala index c1cd175fa..0e7054f67 100644 --- a/src/main/scala/li/cil/oc/client/renderer/entity/ModelQuadcopter.scala +++ b/src/main/scala/li/cil/oc/client/renderer/entity/ModelQuadcopter.scala @@ -11,7 +11,7 @@ import net.minecraft.util.Vec3 import org.lwjgl.opengl.GL11 final class ModelQuadcopter extends ModelBase { - val texture = new ResourceLocation(Settings.resourceDomain, "textures/entity/drone.png") + val texture = new ResourceLocation(Settings.resourceDomain, "textures/model/drone.png") val body = new ModelRenderer(this, "body") val wing0 = new ModelRenderer(this, "wing0") @@ -109,6 +109,15 @@ final class ModelQuadcopter extends ModelBase { light3.rotateAngleX = drone.flapAngles(3)(0) light3.rotateAngleZ = drone.flapAngles(3)(1) + // Additive blending for the lights. + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE) + // Light color. + val lightColor = drone.lightColor + val r = ((lightColor >>> 16) & 0xFF).toByte + val g = ((lightColor >>> 8) & 0xFF).toByte + val b = ((lightColor >>> 0) & 0xFF).toByte + GL11.glColor3ub(r, g, b) + light0.render(scale) light1.render(scale) light2.render(scale) @@ -147,6 +156,9 @@ final class ModelQuadcopter extends ModelBase { light3.rotateAngleX = tilt light3.rotateAngleZ = -tilt + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE) + GL11.glColor3ub(0x66.toByte, 0xDD.toByte, 0x55.toByte) + light0.render(scale) light1.render(scale) light2.render(scale) diff --git a/src/main/scala/li/cil/oc/common/entity/Drone.scala b/src/main/scala/li/cil/oc/common/entity/Drone.scala index c57642e3e..5ef57c725 100644 --- a/src/main/scala/li/cil/oc/common/entity/Drone.scala +++ b/src/main/scala/li/cil/oc/common/entity/Drone.scala @@ -35,7 +35,10 @@ import net.minecraft.world.World import net.minecraft.util.EnumFacing import net.minecraftforge.fluids.IFluidTank -class Drone(val world: World) extends Entity(world) with MachineHost with internal.Drone { +// internal.Rotatable is also in internal.Drone, but it wasn't since the start +// so this is to ensure it is implemented here, in the very unlikely case that +// someone decides to ship that specific version of the API. +class Drone(val world: World) extends Entity(world) with MachineHost with internal.Drone with internal.Rotatable { // Some basic constants. val gravity = 0.05f // low for slow fall (float down) @@ -127,6 +130,14 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern // ----------------------------------------------------------------------- // + override def facing() = ForgeDirection.SOUTH + + override def toLocal(value: ForgeDirection) = value + + override def toGlobal(value: ForgeDirection) = value + + // ----------------------------------------------------------------------- // + override def cpuArchitecture = info.components.map(stack => (stack, Driver.driverFor(stack, getClass))).collectFirst { case (stack, driver: Processor) if driver.slot(stack) == Slot.CPU => driver.architecture(stack) }.orNull @@ -185,6 +196,8 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern dataWatcher.addObject(10, "") // Inventory size for client. dataWatcher.addObject(11, byte2Byte(0: Byte)) + // Light color. + dataWatcher.addObject(12, int2Integer(0x66DD55)) } def initializeAfterPlacement(stack: ItemStack, player: EntityPlayer, position: Vec3) { @@ -221,6 +234,7 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern def globalBufferSize = dataWatcher.getWatchableObjectInt(9) def statusText = dataWatcher.getWatchableObjectString(10) def inventorySize = dataWatcher.getWatchableObjectByte(11) & 0xFF + def lightColor = dataWatcher.getWatchableObjectInt(12) def setRunning(value: Boolean) = dataWatcher.updateObject(2, byte2Byte(if (value) 1: Byte else 0: Byte)) // Round target values to low accuracy to avoid floating point errors accumulating. @@ -233,6 +247,7 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern def globalBufferSize_=(value: Int) = dataWatcher.updateObject(9, int2Integer(value)) def statusText_=(value: String) = dataWatcher.updateObject(10, Option(value).map(_.lines.map(_.take(10)).take(2).mkString("\n")).getOrElse("")) def inventorySize_=(value: Int) = dataWatcher.updateObject(11, byte2Byte(value.toByte)) + def lightColor_=(value: Int) = dataWatcher.updateObject(12, int2Integer(value)) @SideOnly(Side.CLIENT) override def func_180426_a(x: Double, y: Double, z: Double, yaw: Float, pitch: Float, data: Int, unused: Boolean) { @@ -425,6 +440,7 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern selectedSlot = nbt.getByte("selectedSlot") & 0xFF selectedTank = nbt.getByte("selectedTank") & 0xFF statusText = nbt.getString("statusText") + lightColor = nbt.getInteger("lightColor") } override def writeEntityToNBT(nbt: NBTTagCompound) { @@ -444,5 +460,6 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern nbt.setByte("selectedSlot", selectedSlot.toByte) nbt.setByte("selectedTank", selectedTank.toByte) nbt.setString("statusText", statusText) + nbt.setInteger("lightColor", lightColor) } } diff --git a/src/main/scala/li/cil/oc/server/component/Drone.scala b/src/main/scala/li/cil/oc/server/component/Drone.scala index 800278c73..ee9e5aa44 100644 --- a/src/main/scala/li/cil/oc/server/component/Drone.scala +++ b/src/main/scala/li/cil/oc/server/component/Drone.scala @@ -58,6 +58,16 @@ class Drone(val host: entity.Drone) extends prefab.ManagedEnvironment with trait result(host.statusText) } + @Callback(doc = "function():number -- Get the current color of the flap lights as an integer encoded RGB value (0xRRGGBB).") + def getLightColor(context: Context, args: Arguments): Array[AnyRef] = result(host.lightColor) + + @Callback(doc = "function(value:number):number -- Set the color of the flap lights to the specified integer encoded RGB value (0xRRGGBB).") + def setLightColor(context: Context, args: Arguments): Array[AnyRef] = { + host.lightColor = args.checkInteger(0) + context.pause(0.1) + result(host.lightColor) + } + // ----------------------------------------------------------------------- // @Callback(doc = "function(dx:number, dy:number, dz:number) -- Change the target position by the specified offset.") diff --git a/src/main/scala/li/cil/oc/server/component/UpgradeInventoryController.scala b/src/main/scala/li/cil/oc/server/component/UpgradeInventoryController.scala index 07373fc63..bf9821497 100644 --- a/src/main/scala/li/cil/oc/server/component/UpgradeInventoryController.scala +++ b/src/main/scala/li/cil/oc/server/component/UpgradeInventoryController.scala @@ -57,20 +57,19 @@ object UpgradeInventoryController { override def inventory = host.dynamicInventory - override def selectedSlot = host.selectedSlot + override def selectedSlot = host.selectedSlot - host.actualSlot(0) - override def selectedSlot_=(value: Int) = host.selectedSlot = value + override def selectedSlot_=(value: Int) = host.selectedSlot = host.actualSlot(value) override protected def checkSideForAction(args: Arguments, n: Int) = host.toGlobal(args.checkSideForAction(n)) @Callback(doc = """function():boolean -- Swaps the equipped tool with the content of the currently selected inventory slot.""") def equip(context: Context, args: Arguments): Array[AnyRef] = { - if (host.inventorySize > 0) { - val selectedSlot = host.selectedSlot + if (inventory.getSizeInventory > 0) { val equipped = host.getStackInSlot(0) - val selected = host.getStackInSlot(selectedSlot) + val selected = inventory.getStackInSlot(selectedSlot) host.setInventorySlotContents(0, selected) - host.setInventorySlotContents(selectedSlot, equipped) + inventory.setInventorySlotContents(selectedSlot, equipped) result(true) } else result(false) diff --git a/src/main/scala/li/cil/oc/server/component/traits/InventoryWorldControlMk2.scala b/src/main/scala/li/cil/oc/server/component/traits/InventoryWorldControlMk2.scala index 1aee2f33e..f94ab65c9 100644 --- a/src/main/scala/li/cil/oc/server/component/traits/InventoryWorldControlMk2.scala +++ b/src/main/scala/li/cil/oc/server/component/traits/InventoryWorldControlMk2.scala @@ -25,11 +25,11 @@ trait InventoryWorldControlMk2 extends InventoryAware with WorldAware with SideR } else if (stack.stackSize == 0) { // Dropped whole stack. - inventory.setInventorySlotContents(selectedSlot, null) + this.inventory.setInventorySlotContents(selectedSlot, null) } else { // Dropped partial stack. - inventory.markDirty() + this.inventory.markDirty() } context.pause(Settings.get.dropDelay)