From b6dbef709554b9d123d48d5e5b2831f28958ee01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Fri, 20 Feb 2015 21:11:28 +0100 Subject: [PATCH 01/14] Wrap external NBT loading with try-catch to avoid corrupting block if external NBT data is corrupt. Closes #926. --- src/main/scala/li/cil/oc/common/SaveHandler.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/scala/li/cil/oc/common/SaveHandler.scala b/src/main/scala/li/cil/oc/common/SaveHandler.scala index b16a850d4..c7fb5b454 100644 --- a/src/main/scala/li/cil/oc/common/SaveHandler.scala +++ b/src/main/scala/li/cil/oc/common/SaveHandler.scala @@ -83,11 +83,16 @@ object SaveHandler { def loadNBT(nbt: NBTTagCompound, name: String): NBTTagCompound = { val data = load(nbt, name) - if (data.length > 0) { + if (data.length > 0) try { val bais = new ByteArrayInputStream(data) val dis = new DataInputStream(bais) CompressedStreamTools.read(dis) } + catch { + case t: Throwable => + OpenComputers.log.warn("There was an error trying to restore a block's state from external data. This indicates that data was somehow corrupted.", t) + new NBTTagCompound() + } else new NBTTagCompound() } From a24d31e1fad84275c452b9293543df833a1138bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Fri, 20 Feb 2015 21:11:46 +0100 Subject: [PATCH 02/14] Bump version. --- build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.properties b/build.properties index 05b250f75..35511b616 100644 --- a/build.properties +++ b/build.properties @@ -1,7 +1,7 @@ minecraft.version=1.7.10 forge.version=10.13.2.1236 -oc.version=1.5.0 +oc.version=1.5.1 oc.subversion=dev ae2.version=rv1-stable-1 From e1fe1259890d98210730a4b743472a76fc747736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sat, 21 Feb 2015 16:05:41 +0100 Subject: [PATCH 03/14] Added fix I forgot to backport, fixes broken flight height computation. Closes #927. --- src/main/scala/li/cil/oc/common/event/RobotCommonHandler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/li/cil/oc/common/event/RobotCommonHandler.scala b/src/main/scala/li/cil/oc/common/event/RobotCommonHandler.scala index 45a077fd2..e0f8771be 100644 --- a/src/main/scala/li/cil/oc/common/event/RobotCommonHandler.scala +++ b/src/main/scala/li/cil/oc/common/event/RobotCommonHandler.scala @@ -31,7 +31,7 @@ object RobotCommonHandler { val maxFlyingHeight = Settings.get.limitFlightHeight def isMovingDown = e.direction == ForgeDirection.DOWN def hasAdjacentBlock(pos: BlockPosition) = ForgeDirection.VALID_DIRECTIONS.exists(side => world.isSideSolid(pos.offset(side), side.getOpposite)) - def isWithinFlyingHeight(pos: BlockPosition) = (1 to maxFlyingHeight).exists(n => !world.isAirBlock(pos.offset(e.direction.getOpposite, n))) + def isWithinFlyingHeight(pos: BlockPosition) = (1 to maxFlyingHeight).exists(n => !world.isAirBlock(pos.offset(ForgeDirection.DOWN, n))) val startPos = BlockPosition(robot) val targetPos = startPos.offset(e.direction) // New movement rules as of 1.5: From 28aeaf4313d2e5734266cd0fe4fb7d5194abbd05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 23 Feb 2015 14:39:28 +0100 Subject: [PATCH 04/14] Fixed typos / information in manpages, closes #928. --- src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/df | 2 +- .../resources/assets/opencomputers/loot/OpenOS/usr/man/primary | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/df b/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/df index eb8a3b82d..5fc6e477f 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/df +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/df @@ -5,7 +5,7 @@ SYNOPSIS df [FILE]... DESCRIPTION - `cp` allows copying single files on a filesystem and across filesystems. + `df` outputs disk space information for the file systems containing the specified files. If no file names are given it returns the information for all currently mounted file systems. EXAMPLES df diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/primary b/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/primary index 6eedccd42..b868f738a 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/primary +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/primary @@ -6,7 +6,7 @@ SYNOPSIS primary TYPE ADDRESS DESCRIPTION - This program allows reading the address of the current primary component of the specified type. It also allows chaning the current primary component for a specified type by providing the (abbreviated) address of the new primary component. + This program allows reading the address of the current primary component of the specified type. It also allows changing the current primary component for a specified type by providing the (abbreviated) address of the new primary component. EXAMPLES primary gpu From e83e572854f988216c6cd0a0f8876e9e0d7d242b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 23 Feb 2015 15:02:29 +0100 Subject: [PATCH 05/14] Force periodically sending power info if it changed at all to avoid incorrect values being displayed when 100% is hit when charging, e.g., closes #932. --- .../tileentity/traits/PowerInformation.scala | 16 +++++++++++++++- .../scala/li/cil/oc/server/PacketSender.scala | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/PowerInformation.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/PowerInformation.scala index 671032e37..653307475 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/PowerInformation.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/PowerInformation.scala @@ -2,12 +2,15 @@ package li.cil.oc.common.tileentity.traits import cpw.mods.fml.relauncher.Side import cpw.mods.fml.relauncher.SideOnly +import li.cil.oc.Settings import li.cil.oc.server.{PacketSender => ServerPacketSender} import net.minecraft.nbt.NBTTagCompound trait PowerInformation extends TileEntity { private var lastSentRatio = -1.0 + private var ticksUntilSync = 0 + def globalBuffer: Double def globalBuffer_=(value: Double): Unit @@ -18,12 +21,23 @@ trait PowerInformation extends TileEntity { protected def updatePowerInformation() { val ratio = if (globalBufferSize > 0) globalBuffer / globalBufferSize else 0 - if (lastSentRatio < 0 || math.abs(lastSentRatio - ratio) > (5.0 / 100.0)) { + if (shouldSync(ratio) || hasChangedSignificantly(ratio)) { lastSentRatio = ratio ServerPacketSender.sendPowerState(this) } } + private def hasChangedSignificantly(ratio: Double) = lastSentRatio < 0 || math.abs(lastSentRatio - ratio) > (5.0 / 100.0) + + private def shouldSync(ratio: Double) = { + ticksUntilSync -= 1 + if (ticksUntilSync <= 0) { + ticksUntilSync = (100 / Settings.get.tickFrequency).toInt max 1 + lastSentRatio != ratio + } + else false + } + @SideOnly(Side.CLIENT) override def readFromNBTForClient(nbt: NBTTagCompound) { super.readFromNBTForClient(nbt) diff --git a/src/main/scala/li/cil/oc/server/PacketSender.scala b/src/main/scala/li/cil/oc/server/PacketSender.scala index b7981467e..68e1df349 100644 --- a/src/main/scala/li/cil/oc/server/PacketSender.scala +++ b/src/main/scala/li/cil/oc/server/PacketSender.scala @@ -220,7 +220,7 @@ object PacketSender { val pb = new SimplePacketBuilder(PacketType.PowerState) pb.writeTileEntity(t) - pb.writeDouble(t.globalBuffer) + pb.writeDouble(math.round(t.globalBuffer)) pb.writeDouble(t.globalBufferSize) pb.sendToPlayersNearTileEntity(t) From e96348f66581bebe870855019f686f515cfbdb43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 23 Feb 2015 15:38:50 +0100 Subject: [PATCH 06/14] Added note wrt. tablets in chargers to charger tooltip. --- src/main/resources/assets/opencomputers/lang/de_DE.lang | 2 +- src/main/resources/assets/opencomputers/lang/en_US.lang | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/opencomputers/lang/de_DE.lang b/src/main/resources/assets/opencomputers/lang/de_DE.lang index 7767f84d3..6e3375830 100644 --- a/src/main/resources/assets/opencomputers/lang/de_DE.lang +++ b/src/main/resources/assets/opencomputers/lang/de_DE.lang @@ -195,7 +195,7 @@ oc:tooltip.Cable=Ein billiger Weg, verschiedene Blöcke miteinander zu verbinden oc:tooltip.Capacitor=Speichert Energie für spätere Verwendung. Kann extrem schnell befüllt und entleert werden. oc:tooltip.CardBase=Wie der Name schon sagt, werden alle Erweiterungskarten hieraus hergestellt. oc:tooltip.Case=Das Computergehäuse ist der essentielle Grundbaustein für einen Computer. §fErweiterungskarten§7, §fRAM§7 und §fFestplatten§7 können in einem Gehäuse installiert werden.[nl] Slots: §f%s§7 -oc:tooltip.Charger=Lädt Roboter mit Energie aus Kondensatoren auf. Die Ladegeschwindigkeit hängt vom eingehenden §fRedstonesignal§7 ab, wobei kein Signal "nicht laden" und ein Signal mit maximaler Stärke "schnellstmöglich laden" heißt. +oc:tooltip.Charger=Lädt Roboter mit Energie aus Kondensatoren auf. Die Ladegeschwindigkeit hängt vom eingehenden §fRedstonesignal§7 ab, wobei kein Signal "nicht laden" und ein Signal mit maximaler Stärke "schnellstmöglich laden" heißt. Erlaubt es auch Tablets zu laden, und ermöglicht Zugriff auf Festplatten in Tablets. oc:tooltip.CircuitBoard=Mühsam ernährt sich das Eichhörnchen. Wenn es groß wird, wird es mal eine gedruckte Leiterplatte. oc:tooltip.ControlUnit=Klingt wichtig, ist es auch. Man baut daraus immerhin CPUs. Wie könnte es da nicht wichtig sein. oc:tooltip.ComponentBus=Diese Erweiterung erlaubt es es Servern, mit noch mehr Komponenten gleichzeitig zu kommunizieren, ähnlich wie CPUs.[nl] Supported components: §f%s§7 diff --git a/src/main/resources/assets/opencomputers/lang/en_US.lang b/src/main/resources/assets/opencomputers/lang/en_US.lang index f417561f8..8b1c56259 100644 --- a/src/main/resources/assets/opencomputers/lang/en_US.lang +++ b/src/main/resources/assets/opencomputers/lang/en_US.lang @@ -219,7 +219,7 @@ oc:tooltip.Cable=A cheap way of connecting blocks. oc:tooltip.Capacitor=Stores energy for later use. Can be filled and emptied very quickly. oc:tooltip.CardBase=As the name indicates, this is the basic building block for all expansion cards. oc:tooltip.Case=The Computer Case is the basic building block for computers and houses the computer's §fextension cards§7, §fRAM§7 and §fhard disks§7.[nl] Slots: §f%s§7 -oc:tooltip.Charger=Transfers energy from capacitors into adjacent robots and drones. The transfer rate depends on the incoming §fredstone signal§7, where no signal means don't charge devices, and maximum strength means charge at full speed. +oc:tooltip.Charger=Transfers energy from capacitors into adjacent robots and drones. The transfer rate depends on the incoming §fredstone signal§7, where no signal means don't charge devices, and maximum strength means charge at full speed. Can also be used to charge tablets and access hard drives in tablets. oc:tooltip.CircuitBoard=Now we're getting somewhere. Can be etched to obtain a printed circuit board. oc:tooltip.ControlUnit=This is the unit that... controls... stuff. You need it to build a CPU. So yeah, totally important. oc:tooltip.ComponentBus=This expansion allows servers to communicate with more components at the same time, similar to how CPUs do.[nl] Supported components: §f%s§7 From 507b882f47949ef32db1e5297ab535d03f2fac2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 23 Feb 2015 17:45:29 +0100 Subject: [PATCH 07/14] Backported change to robot movement / execution logic so that it runs in a tick handler instead of the tile entity's update method. May help with issue #808 or break things horribly (not that I've seen any indication of the latter in the tests I did). --- .../scala/li/cil/oc/common/EventHandler.scala | 14 ++++++++++ .../li/cil/oc/common/tileentity/Robot.scala | 13 ++++++++++ .../common/tileentity/traits/Computer.scala | 26 ++++++++++++------- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/main/scala/li/cil/oc/common/EventHandler.scala b/src/main/scala/li/cil/oc/common/EventHandler.scala index bad067260..3be2e4b54 100644 --- a/src/main/scala/li/cil/oc/common/EventHandler.scala +++ b/src/main/scala/li/cil/oc/common/EventHandler.scala @@ -15,6 +15,7 @@ import li.cil.oc.api.detail.ItemInfo import li.cil.oc.client.renderer.PetRenderer import li.cil.oc.client.{PacketSender => ClientPacketSender} import li.cil.oc.common.item.data.MicrocontrollerData +import li.cil.oc.common.tileentity.Robot import li.cil.oc.common.tileentity.traits.power import li.cil.oc.integration.Mods import li.cil.oc.integration.util @@ -40,6 +41,12 @@ object EventHandler { var totalWorldTicks = 0L + private val runningRobots = mutable.Set.empty[Robot] + + def onRobotStart(robot: Robot): Unit = runningRobots += robot + + def onRobotStopped(robot: Robot): Unit = runningRobots -= robot + def schedule(tileEntity: TileEntity) { if (SideTracker.isServer) pending.synchronized { pending += (() => Network.joinOrCreateNetwork(tileEntity)) @@ -108,6 +115,13 @@ object EventHandler { case t: Throwable => OpenComputers.log.warn("Error in scheduled tick action.", t) } }) + + val invalid = mutable.ArrayBuffer.empty[Robot] + runningRobots.foreach(robot => { + if (robot.isInvalid) invalid += robot + else robot.machine.update() + }) + runningRobots --= invalid } @SubscribeEvent diff --git a/src/main/scala/li/cil/oc/common/tileentity/Robot.scala b/src/main/scala/li/cil/oc/common/tileentity/Robot.scala index f5ce170df..845b50831 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Robot.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Robot.scala @@ -13,6 +13,7 @@ import li.cil.oc.api.event.RobotMoveEvent import li.cil.oc.api.internal import li.cil.oc.api.network._ import li.cil.oc.client.gui +import li.cil.oc.common.EventHandler import li.cil.oc.common.Slot import li.cil.oc.common.Tier import li.cil.oc.common.inventory.InventorySelection @@ -402,6 +403,16 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand } } + // The robot's machine is updated in a tick handler, to avoid delayed tile + // entity creation when moving, which would screw over all the things... + override protected def updateComputer(): Unit = {} + + override protected def onRunningChanged(): Unit = { + super.onRunningChanged() + if (isRunning) EventHandler.onRobotStart(this) + else EventHandler.onRobotStopped(this) + } + override protected def initialize() { if (isServer) { // Ensure we have a node address, because the proxy needs this to initialize @@ -419,6 +430,7 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand case _ => } } + else EventHandler.onRobotStopped(this) } // ----------------------------------------------------------------------- // @@ -452,6 +464,7 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand // robot's proxy instance. _isOutputEnabled = hasRedstoneCard _isAbstractBusAvailable = hasAbstractBusCard + if (isRunning) EventHandler.onRobotStart(this) } // Side check for Waila (and other mods that may call this client side). diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala index 65f34d1a6..954634278 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala @@ -98,19 +98,18 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B // ----------------------------------------------------------------------- // - override def updateEntity() { + override def updateEntity(): Unit = { + // If we're not yet in a network we might have just been loaded from disk, + // meaning there may be other tile entities that also have not re-joined + // the network. We skip the update this round to allow other tile entities + // to join the network, too, avoiding issues of missing nodes (e.g. in the + // GPU which would otherwise loose track of its screen). if (isServer && isConnected) { - // If we're not yet in a network we might have just been loaded from disk, - // meaning there may be other tile entities that also have not re-joined - // the network. We skip the update this round to allow other tile entities - // to join the network, too, avoiding issues of missing nodes (e.g. in the - // GPU which would otherwise loose track of its screen). - machine.update() + updateComputer() if (_isRunning != machine.isRunning) { _isRunning = machine.isRunning - markDirty() - ServerPacketSender.sendComputerState(this) + onRunningChanged() } updateComponents() @@ -119,6 +118,15 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B super.updateEntity() } + protected def updateComputer(): Unit = { + machine.update() + } + + protected def onRunningChanged(): Unit = { + markDirty() + ServerPacketSender.sendComputerState(this) + } + // ----------------------------------------------------------------------- // override def readFromNBTForServer(nbt: NBTTagCompound) { From b34ec529bdfff142530561631d6fa24b6c4fe2e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Feb 2015 02:30:42 +0100 Subject: [PATCH 08/14] Fixed slot offset in crafting upgrade. Reworked code adding stuff to player inventories a bit to ensure it gets properly synced to clients. --- .../scala/li/cil/oc/common/EventHandler.scala | 15 +++----------- .../container/DynamicComponentSlot.scala | 4 ++-- .../scala/li/cil/oc/common/item/Present.scala | 11 ++-------- .../li/cil/oc/server/component/Agent.scala | 6 ++---- .../oc/server/component/UpgradeCrafting.scala | 12 +++++------ .../scala/li/cil/oc/util/InventoryUtils.scala | 20 ++++++++++++++++++- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/main/scala/li/cil/oc/common/EventHandler.scala b/src/main/scala/li/cil/oc/common/EventHandler.scala index 3be2e4b54..5a44d1a8d 100644 --- a/src/main/scala/li/cil/oc/common/EventHandler.scala +++ b/src/main/scala/li/cil/oc/common/EventHandler.scala @@ -221,15 +221,7 @@ object EventHandler { // Presents! val present = api.Items.get("present").createItemStack(1) e.player.worldObj.playSoundAtEntity(e.player, "note.pling", 0.2f, 1f) - if (e.player.inventory.addItemStackToInventory(present)) { - e.player.inventory.markDirty() - if (e.player.openContainer != null) { - e.player.openContainer.detectAndSendChanges() - } - } - else { - e.player.dropPlayerItemWithRandomChoice(present, false) - } + InventoryUtils.addToPlayerInventory(present, e.player) } case _ => // Nope. } @@ -250,9 +242,8 @@ object EventHandler { for (slot <- 0 until e.craftMatrix.getSizeInventory) { val stack = e.craftMatrix.getStackInSlot(slot) if (api.Items.get(stack) == item) { - callback(stack).foreach(extra => if (!e.player.inventory.addItemStackToInventory(extra)) { - e.player.dropPlayerItemWithRandomChoice(extra, false) - }) + callback(stack).foreach(extra => + InventoryUtils.addToPlayerInventory(extra, e.player)) } } true diff --git a/src/main/scala/li/cil/oc/common/container/DynamicComponentSlot.scala b/src/main/scala/li/cil/oc/common/container/DynamicComponentSlot.scala index 81c8e1291..0d296d213 100644 --- a/src/main/scala/li/cil/oc/common/container/DynamicComponentSlot.scala +++ b/src/main/scala/li/cil/oc/common/container/DynamicComponentSlot.scala @@ -3,6 +3,7 @@ package li.cil.oc.common.container import li.cil.oc.client.gui.Icons import li.cil.oc.common import li.cil.oc.common.InventorySlots.InventorySlot +import li.cil.oc.util.InventoryUtils import li.cil.oc.util.SideTracker import net.minecraft.entity.player.EntityPlayer import net.minecraft.inventory.IInventory @@ -36,8 +37,7 @@ class DynamicComponentSlot(val container: Player, inventory: IInventory, index: if (SideTracker.isServer && getHasStack && !isItemValid(getStack)) { val stack = getStack putStack(null) - player.inventory.addItemStackToInventory(stack) - player.dropPlayerItemWithRandomChoice(stack, false) + InventoryUtils.addToPlayerInventory(stack, player) } } } diff --git a/src/main/scala/li/cil/oc/common/item/Present.scala b/src/main/scala/li/cil/oc/common/item/Present.scala index 3548b129d..8b921790d 100644 --- a/src/main/scala/li/cil/oc/common/item/Present.scala +++ b/src/main/scala/li/cil/oc/common/item/Present.scala @@ -4,6 +4,7 @@ import java.util.Random import li.cil.oc.OpenComputers import li.cil.oc.api +import li.cil.oc.util.InventoryUtils import li.cil.oc.util.ItemUtils import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack @@ -20,15 +21,7 @@ class Present(val parent: Delegator) extends Delegate { if (!world.isRemote) { world.playSoundAtEntity(player, "random.levelup", 0.2f, 1f) val present = Present.nextPresent() - if (player.inventory.addItemStackToInventory(present)) { - player.inventory.markDirty() - if (player.openContainer != null) { - player.openContainer.detectAndSendChanges() - } - } - else { - player.dropPlayerItemWithRandomChoice(present, false) - } + InventoryUtils.addToPlayerInventory(present, player) } } stack diff --git a/src/main/scala/li/cil/oc/server/component/Agent.scala b/src/main/scala/li/cil/oc/server/component/Agent.scala index 11d8b7a3e..974a07359 100644 --- a/src/main/scala/li/cil/oc/server/component/Agent.scala +++ b/src/main/scala/li/cil/oc/server/component/Agent.scala @@ -11,6 +11,7 @@ import li.cil.oc.server.agent.Player import li.cil.oc.util.BlockPosition import li.cil.oc.util.ExtendedArguments._ import li.cil.oc.util.ExtendedWorld._ +import li.cil.oc.util.InventoryUtils import net.minecraft.entity.Entity import net.minecraft.entity.EntityLivingBase import net.minecraft.entity.item.EntityMinecart @@ -280,10 +281,7 @@ trait Agent extends traits.WorldControl with traits.InventoryControl with traits entity.captureDrops = false for (drop <- entity.capturedDrops) { val stack = drop.getEntityItem - player.inventory.addItemStackToInventory(stack) - if (stack.stackSize > 0) { - player.dropPlayerItemWithRandomChoice(stack, inPlace = false) - } + InventoryUtils.addToPlayerInventory(stack, player) } entity.capturedDrops.clear() } diff --git a/src/main/scala/li/cil/oc/server/component/UpgradeCrafting.scala b/src/main/scala/li/cil/oc/server/component/UpgradeCrafting.scala index a4fa3ab94..0c6020fc2 100644 --- a/src/main/scala/li/cil/oc/server/component/UpgradeCrafting.scala +++ b/src/main/scala/li/cil/oc/server/component/UpgradeCrafting.scala @@ -9,6 +9,7 @@ import li.cil.oc.api.machine.Callback import li.cil.oc.api.machine.Context import li.cil.oc.api.network._ import li.cil.oc.api.prefab +import li.cil.oc.util.InventoryUtils import net.minecraft.entity.player.EntityPlayer import net.minecraft.inventory import net.minecraft.item.ItemStack @@ -67,10 +68,9 @@ class UpgradeCrafting(val host: EnvironmentHost with internal.Robot) extends pre } } save() - val inventory = host.player.inventory - inventory.addItemStackToInventory(result) + InventoryUtils.addToPlayerInventory(result, host.player) for (stack <- surplus) { - inventory.addItemStackToInventory(stack) + InventoryUtils.addToPlayerInventory(stack, host.player) } load() } @@ -79,7 +79,7 @@ class UpgradeCrafting(val host: EnvironmentHost with internal.Robot) extends pre } def load() { - val inventory = host.player.inventory + val inventory = host.mainInventory() amountPossible = Int.MaxValue for (slot <- 0 until getSizeInventory) { val stack = inventory.getStackInSlot(toParentSlot(slot)) @@ -91,7 +91,7 @@ class UpgradeCrafting(val host: EnvironmentHost with internal.Robot) extends pre } def save() { - val inventory = host.player.inventory + val inventory = host.mainInventory() for (slot <- 0 until getSizeInventory) { inventory.setInventorySlotContents(toParentSlot(slot), getStackInSlot(slot)) } @@ -100,7 +100,7 @@ class UpgradeCrafting(val host: EnvironmentHost with internal.Robot) extends pre private def toParentSlot(slot: Int) = { val col = slot % 3 val row = slot / 3 - row * 4 + col + 4 // first four are always: tool, card, disk, upgrade + row * 4 + col } } diff --git a/src/main/scala/li/cil/oc/util/InventoryUtils.scala b/src/main/scala/li/cil/oc/util/InventoryUtils.scala index b224504a2..d06862471 100644 --- a/src/main/scala/li/cil/oc/util/InventoryUtils.scala +++ b/src/main/scala/li/cil/oc/util/InventoryUtils.scala @@ -3,6 +3,7 @@ package li.cil.oc.util import li.cil.oc.util.ExtendedWorld._ import net.minecraft.entity.item.EntityItem import net.minecraft.entity.item.EntityMinecartContainer +import net.minecraft.entity.player.EntityPlayer import net.minecraft.inventory.IInventory import net.minecraft.inventory.ISidedInventory import net.minecraft.item.ItemStack @@ -233,7 +234,7 @@ object InventoryUtils { /** * Utility method for dumping all inventory contents into the world. */ - def dropAllSlots(position: BlockPosition, inventory: IInventory) { + def dropAllSlots(position: BlockPosition, inventory: IInventory): Unit = { for (slot <- 0 until inventory.getSizeInventory) { Option(inventory.getStackInSlot(slot)) match { case Some(stack) if stack.stackSize > 0 => @@ -244,6 +245,23 @@ object InventoryUtils { } } + /** + * Try inserting an item stack into a player inventory. If that fails, drop it into the world. + */ + def addToPlayerInventory(stack: ItemStack, player: EntityPlayer): Unit = { + if (stack != null) { + if (player.inventory.addItemStackToInventory(stack)) { + player.inventory.markDirty() + if (player.openContainer != null) { + player.openContainer.detectAndSendChanges() + } + } + if (stack.stackSize > 0) { + player.dropPlayerItemWithRandomChoice(stack, false) + } + } + } + /** * Utility method for spawning an item stack in the world. */ From cefa0464dc1011787e0587edd1b0d2f52924f13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Feb 2015 02:31:13 +0100 Subject: [PATCH 09/14] Made inventory trait a bit more flexible. --- src/main/scala/li/cil/oc/common/inventory/Inventory.scala | 8 +++++--- .../li/cil/oc/common/inventory/ItemStackInventory.scala | 8 +++++--- .../scala/li/cil/oc/common/tileentity/Assembler.scala | 2 +- .../li/cil/oc/common/tileentity/traits/Inventory.scala | 4 +++- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/main/scala/li/cil/oc/common/inventory/Inventory.scala b/src/main/scala/li/cil/oc/common/inventory/Inventory.scala index 465bdb6fb..a7cb503f2 100644 --- a/src/main/scala/li/cil/oc/common/inventory/Inventory.scala +++ b/src/main/scala/li/cil/oc/common/inventory/Inventory.scala @@ -11,6 +11,8 @@ import net.minecraftforge.common.util.Constants.NBT trait Inventory extends IInventory { def items: Array[Option[ItemStack]] + def updateItems(slot: Int, stack: ItemStack) = items(slot) = Option(stack) + // ----------------------------------------------------------------------- // override def getStackInSlot(slot: Int) = @@ -45,7 +47,7 @@ trait Inventory extends IInventory { } val oldStack = items(slot) - items(slot) = None + updateItems(slot, null) if (oldStack.isDefined) { onItemRemoved(slot, oldStack.get) } @@ -53,7 +55,7 @@ trait Inventory extends IInventory { if (stack.stackSize > getInventoryStackLimit) { stack.stackSize = getInventoryStackLimit } - items(slot) = Some(stack) + updateItems(slot, stack) } if (items(slot).isDefined) { @@ -84,7 +86,7 @@ trait Inventory extends IInventory { nbt.getTagList(Settings.namespace + "items", NBT.TAG_COMPOUND).foreach((slotNbt: NBTTagCompound) => { val slot = slotNbt.getByte("slot") if (slot >= 0 && slot < items.length) { - items(slot) = Option(ItemUtils.loadStack(slotNbt.getCompoundTag("item"))) + updateItems(slot, ItemUtils.loadStack(slotNbt.getCompoundTag("item"))) } }) } diff --git a/src/main/scala/li/cil/oc/common/inventory/ItemStackInventory.scala b/src/main/scala/li/cil/oc/common/inventory/ItemStackInventory.scala index 2c318defd..bff8b9b74 100644 --- a/src/main/scala/li/cil/oc/common/inventory/ItemStackInventory.scala +++ b/src/main/scala/li/cil/oc/common/inventory/ItemStackInventory.scala @@ -11,7 +11,9 @@ trait ItemStackInventory extends Inventory { // The item stack that provides the inventory. def container: ItemStack - lazy val items = Array.fill[Option[ItemStack]](getSizeInventory)(None) + private lazy val inventory = Array.fill[Option[ItemStack]](getSizeInventory)(None) + + override def items = inventory // Initialize the list automatically if we have a container. if (container != null) { @@ -24,14 +26,14 @@ trait ItemStackInventory extends Inventory { container.setTagCompound(new NBTTagCompound()) } for (i <- 0 until items.length) { - items(i) = None + updateItems(i, null) } if (container.getTagCompound.hasKey(Settings.namespace + "items")) { val list = container.getTagCompound.getTagList(Settings.namespace + "items", NBT.TAG_COMPOUND) for (i <- 0 until (list.tagCount min items.length)) { val tag = list.getCompoundTagAt(i) if (!tag.hasNoTags) { - items(i) = Option(ItemUtils.loadStack(tag)) + updateItems(i, ItemUtils.loadStack(tag)) } } } diff --git a/src/main/scala/li/cil/oc/common/tileentity/Assembler.scala b/src/main/scala/li/cil/oc/common/tileentity/Assembler.scala index bce44c7bf..06abb09ef 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Assembler.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Assembler.scala @@ -83,7 +83,7 @@ class Assembler extends traits.Environment with traits.PowerAcceptor with traits requiredEnergy = totalRequiredEnergy ServerPacketSender.sendRobotAssembling(this, assembling = true) - for (slot <- 0 until getSizeInventory) items(slot) = None + for (slot <- 0 until getSizeInventory) updateItems(slot, null) markDirty() true diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Inventory.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Inventory.scala index 8e9f9f6fc..0f606649f 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/Inventory.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Inventory.scala @@ -9,7 +9,9 @@ import net.minecraft.nbt.NBTTagCompound import net.minecraftforge.common.util.ForgeDirection trait Inventory extends TileEntity with inventory.Inventory { - lazy val items = Array.fill[Option[ItemStack]](getSizeInventory)(None) + private lazy val inventory = Array.fill[Option[ItemStack]](getSizeInventory)(None) + + def items = inventory // ----------------------------------------------------------------------- // From a6f74272c55dcbd5bf61f3984bf22ead6b21dfe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Feb 2015 02:33:12 +0100 Subject: [PATCH 10/14] Allow swapping EEPROM in MCU by shift-rightclicking the block with the EEPROM to insert in hand. Closes #920. --- .../cil/oc/common/block/Microcontroller.scala | 34 ++++++++++++++----- .../scala/li/cil/oc/common/item/EEPROM.scala | 4 +++ .../item/data/MicrocontrollerData.scala | 12 +++++-- .../common/tileentity/Microcontroller.scala | 19 ++++++++++- 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/main/scala/li/cil/oc/common/block/Microcontroller.scala b/src/main/scala/li/cil/oc/common/block/Microcontroller.scala index 7397115b3..c4c475bcd 100644 --- a/src/main/scala/li/cil/oc/common/block/Microcontroller.scala +++ b/src/main/scala/li/cil/oc/common/block/Microcontroller.scala @@ -3,6 +3,7 @@ package li.cil.oc.common.block import java.util import li.cil.oc.Settings +import li.cil.oc.api import li.cil.oc.client.KeyBindings import li.cil.oc.common.Tier import li.cil.oc.common.item.data.MicrocontrollerData @@ -10,6 +11,7 @@ import li.cil.oc.common.tileentity import li.cil.oc.integration.util.NEI import li.cil.oc.integration.util.Wrench import li.cil.oc.util.BlockPosition +import li.cil.oc.util.InventoryUtils import li.cil.oc.util.Rarity import net.minecraft.entity.EntityLivingBase import net.minecraft.entity.player.EntityPlayer @@ -68,16 +70,32 @@ class Microcontroller(protected implicit val tileTag: ClassTag[tileentity.Microc override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = { - if (!player.isSneaking && !Wrench.holdsApplicableWrench(player, BlockPosition(x, y, z))) { - if (!world.isRemote) { - world.getTileEntity(x, y, z) match { - case mcu: tileentity.Microcontroller => - if (mcu.machine.isRunning) mcu.machine.stop() - else mcu.machine.start() - case _ => + if (!Wrench.holdsApplicableWrench(player, BlockPosition(x, y, z))) { + if (!player.isSneaking) { + if (!world.isRemote) { + world.getTileEntity(x, y, z) match { + case mcu: tileentity.Microcontroller => + if (mcu.machine.isRunning) mcu.machine.stop() + else mcu.machine.start() + case _ => + } } + true } - true + else if (api.Items.get(player.getHeldItem) == api.Items.get("eeprom")) { + if (!world.isRemote) { + world.getTileEntity(x, y, z) match { + case mcu: tileentity.Microcontroller => + val newEeprom = player.inventory.decrStackSize(player.inventory.currentItem, 1) + mcu.changeEEPROM(newEeprom) match { + case Some(oldEeprom) => InventoryUtils.addToPlayerInventory(oldEeprom, player) + case _ => + } + } + } + true + } + else false } else false } diff --git a/src/main/scala/li/cil/oc/common/item/EEPROM.scala b/src/main/scala/li/cil/oc/common/item/EEPROM.scala index e9959db44..1e3d5dc89 100644 --- a/src/main/scala/li/cil/oc/common/item/EEPROM.scala +++ b/src/main/scala/li/cil/oc/common/item/EEPROM.scala @@ -1,9 +1,13 @@ package li.cil.oc.common.item import li.cil.oc.Settings +import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack +import net.minecraft.world.World class EEPROM extends SimpleItem { + override def doesSneakBypassUse(world: World, x: Int, y: Int, z: Int, player: EntityPlayer): Boolean = true + override def getItemStackDisplayName(stack: ItemStack): String = { if (stack.hasTagCompound) { val tag = stack.getTagCompound diff --git a/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala b/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala index a8657920f..b61ec4aba 100644 --- a/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala +++ b/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala @@ -17,20 +17,26 @@ class MicrocontrollerData extends ItemData { var tier = Tier.One - var components = Array.empty[ItemStack] + var components = Array[ItemStack](null) var storedEnergy = 0 override def load(nbt: NBTTagCompound) { tier = nbt.getByte(Settings.namespace + "tier") components = nbt.getTagList(Settings.namespace + "components", NBT.TAG_COMPOUND). - toArray[NBTTagCompound].map(ItemUtils.loadStack) + toArray[NBTTagCompound].map(ItemUtils.loadStack).filter(_ != null) storedEnergy = nbt.getInteger(Settings.namespace + "storedEnergy") + + // Reserve slot for EEPROM if necessary, avoids having to resize the + // components array in the MCU tile entity, which isn't possible currently. + if (!components.exists(stack => api.Items.get(stack) == api.Items.get("eeprom"))) { + components :+= null + } } override def save(nbt: NBTTagCompound) { nbt.setByte(Settings.namespace + "tier", tier.toByte) - nbt.setNewTagList(Settings.namespace + "components", components.toIterable) + nbt.setNewTagList(Settings.namespace + "components", components.filter(_ != null).toIterable) nbt.setInteger(Settings.namespace + "storedEnergy", storedEnergy) } diff --git a/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala b/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala index b33b7ae67..3e5efb0a6 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala @@ -221,7 +221,9 @@ class Microcontroller extends traits.PowerAcceptor with traits.Hub with traits.C nbt.setNewCompoundTag("info", info.save) } - override lazy val items = info.components.map(Option(_)) + override def items = info.components.map(Option(_)) + + override def updateItems(slot: Int, stack: ItemStack): Unit = info.components(slot) = stack override def getSizeInventory = info.components.length @@ -232,4 +234,19 @@ class Microcontroller extends traits.PowerAcceptor with traits.Hub with traits.C // Nope. override def decrStackSize(slot: Int, amount: Int) = null + + // For hotswapping EEPROMs. + def changeEEPROM(newEeprom: ItemStack) = { + val oldEepromIndex = info.components.indexWhere(api.Items.get(_) == api.Items.get("eeprom")) + if (oldEepromIndex >= 0) { + val oldEeprom = info.components(oldEepromIndex) + super.setInventorySlotContents(oldEepromIndex, newEeprom) + Some(oldEeprom) + } + else { + assert(info.components(getSizeInventory - 1) == null) + super.setInventorySlotContents(getSizeInventory - 1, newEeprom) + None + } + } } From 4f5bfe184a9585b43744edea07ce87a35d107fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Feb 2015 02:38:59 +0100 Subject: [PATCH 11/14] Fixed creative items derping in creative tab when switching worlds (e.g. joining server after having been in a single player world). --- src/main/scala/li/cil/oc/common/init/Items.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/li/cil/oc/common/init/Items.scala b/src/main/scala/li/cil/oc/common/init/Items.scala index 8b48f7cc3..4e18a8a7c 100644 --- a/src/main/scala/li/cil/oc/common/init/Items.scala +++ b/src/main/scala/li/cil/oc/common/init/Items.scala @@ -280,7 +280,7 @@ object Items extends ItemAPI { def init() { multi = new item.Delegator() { - lazy val configuredItems = Array( + def configuredItems = Array( createOpenOS(), createLuaBios(), createConfiguredDrone(), From d1d4a8a7e5c59b4d8c299b36086fe3dcb84db459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Fri, 20 Feb 2015 01:00:56 +0100 Subject: [PATCH 12/14] Fixed robot tool usage. Conflicts: src/main/scala/li/cil/oc/server/agent/Player.scala --- src/main/scala/li/cil/oc/server/agent/Player.scala | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/scala/li/cil/oc/server/agent/Player.scala b/src/main/scala/li/cil/oc/server/agent/Player.scala index 6f93da12d..a0ba23533 100644 --- a/src/main/scala/li/cil/oc/server/agent/Player.scala +++ b/src/main/scala/li/cil/oc/server/agent/Player.scala @@ -153,7 +153,7 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc // ----------------------------------------------------------------------- // override def attackTargetEntityWithCurrentItem(entity: Entity) { - callUsingItemInSlot(0, stack => entity match { + callUsingItemInSlot(agent.equipmentInventory, 0, stack => entity match { case player: EntityPlayer if !canAttackPlayer(player) => // Avoid player damage. case _ => val event = new RobotAttackEntityEvent.Pre(agent, entity) @@ -173,7 +173,7 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc } false } - !cancel && callUsingItemInSlot(0, stack => { + !cancel && callUsingItemInSlot(agent.equipmentInventory, 0, stack => { val result = isItemUseAllowed(stack) && (entity.interactFirst(this) || (entity match { case living: EntityLivingBase if getCurrentEquippedItem != null => getCurrentEquippedItem.interactWithEntity(this, living) case _ => false @@ -186,7 +186,7 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc } def activateBlockOrUseItem(x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float, duration: Double): ActivationType.Value = { - callUsingItemInSlot(0, stack => { + callUsingItemInSlot(agent.equipmentInventory, 0, stack => { if (shouldCancel(() => ForgeEventFactory.onPlayerInteract(this, Action.RIGHT_CLICK_BLOCK, x, y, z, side, world))) { return ActivationType.None } @@ -216,7 +216,7 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc } def useEquippedItem(duration: Double) = { - callUsingItemInSlot(0, stack => { + callUsingItemInSlot(agent.equipmentInventory, 0, stack => { if (!shouldCancel(() => ForgeEventFactory.onPlayerInteract(this, Action.RIGHT_CLICK_AIR, 0, 0, 0, 0, world))) { tryUseItem(stack, duration) } @@ -260,7 +260,7 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc } def placeBlock(slot: Int, x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float): Boolean = { - callUsingItemInSlot(slot, stack => { + callUsingItemInSlot(agent.mainInventory, slot, stack => { if (shouldCancel(() => ForgeEventFactory.onPlayerInteract(this, Action.RIGHT_CLICK_BLOCK, x, y, z, side, world))) { return false } @@ -270,7 +270,7 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc } def clickBlock(x: Int, y: Int, z: Int, side: Int): Double = { - callUsingItemInSlot(0, stack => { + callUsingItemInSlot(agent.equipmentInventory, 0, stack => { if (shouldCancel(() => ForgeEventFactory.onPlayerInteract(this, Action.LEFT_CLICK_BLOCK, x, y, z, side, world))) { return 0 } @@ -392,7 +392,7 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc } } - private def callUsingItemInSlot[T](slot: Int, f: (ItemStack) => T, repair: Boolean = true) = { + private def callUsingItemInSlot[T](inventory: IInventory, slot: Int, f: (ItemStack) => T, repair: Boolean = true) = { val itemsBefore = adjacentItems val stack = inventory.getStackInSlot(slot) val oldStack = if (stack != null) stack.copy() else null From 20bb0a062df7b3e8ba1670e46d9d8ced4b6d52c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 25 Feb 2015 02:23:36 +0100 Subject: [PATCH 13/14] Improved rc script system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Łukasz Magiera --- .../opencomputers/loot/OpenOS/bin/rc.lua | 5 +- .../opencomputers/loot/OpenOS/lib/rc.lua | 60 +++++++++++++++++-- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/bin/rc.lua b/src/main/resources/assets/opencomputers/loot/OpenOS/bin/rc.lua index 1d138cb63..c5a5422e7 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/bin/rc.lua +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/bin/rc.lua @@ -1,8 +1,8 @@ local rc = require('rc') local args = table.pack(...) -if args.n < 2 then - io.write("Usage: rc [args...]") +if args.n < 1 then + io.write("Usage: rc [command] [args...]") return end @@ -11,3 +11,4 @@ local result, reason = rc.runCommand(table.unpack(args)) if not result then io.stderr:write(reason .. "\n") end + diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/rc.lua b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/rc.lua index c674ec819..e03a0ab8c 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/rc.lua +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/rc.lua @@ -1,4 +1,5 @@ local fs = require('filesystem') +local serialization = require('serialization') -- Keeps track of loaded scripts to retain local values between invocation -- of their command callbacks. @@ -18,6 +19,19 @@ local function loadConfig() return nil, reason end +local function saveConfig(conf) + local file, reason = io.open('/etc/rc.cfg', 'w') + if not file then + return nil, reason + end + for key, value in pairs(conf) do + file:write(tostring(key) .. " = " .. serialization.serialize(value) .. "\n") + end + + file:close() + return true +end + function rc.load(name, args) if loaded[name] then return loaded[name] @@ -39,14 +53,47 @@ function rc.unload(name) loaded[name] = nil end -local function rawRunCommand(name, cmd, args, ...) +local function rawRunCommand(conf, name, cmd, args, ...) local result, what = rc.load(name, args) if result then - if type(result[cmd]) == "function" then - result, what = xpcall(result[cmd], debug.traceback, ...) - if result then + if not cmd then + io.output():write("Commands for service " .. name .. "\n") + for command, val in pairs(result) do + if type(val) == "function" then + io.output():write(tostring(command) .. " ") + end + end + return true + elseif type(result[cmd]) == "function" then + res, what = xpcall(result[cmd], debug.traceback, ...) + if res then return true end + elseif cmd == "restart" and type(result["stop"]) == "function" and type(result["start"]) == "function" then + res, what = xpcall(result["stop"], debug.traceback, ...) + if res then + res, what = xpcall(result["start"], debug.traceback, ...) + if res then + return true + end + end + elseif cmd == "enable" then + conf.enabled = conf.enabled or {} + for _, _name in ipairs(conf.enabled) do + if name == _name then + return nil, "Service already enabled" + end + end + conf.enabled[#conf.enabled + 1] = name + return saveConfig(conf) + elseif cmd == "disable" then + conf.enabled = conf.enabled or {} + for n, _name in ipairs(conf.enabled) do + if name == _name then + table.remove(conf.enabled, n) + end + end + return saveConfig(conf) else what = "Command '" .. cmd .. "' not found in daemon '" .. name .. "'" end @@ -59,7 +106,7 @@ function rc.runCommand(name, cmd, ...) if not conf then return nil, reason end - return rawRunCommand(name, cmd, conf[name], ...) + return rawRunCommand(conf, name, cmd, conf[name], ...) end function rc.allRunCommand(cmd, ...) @@ -69,9 +116,10 @@ function rc.allRunCommand(cmd, ...) end local results = {} for _, name in ipairs(conf.enabled or {}) do - results[name] = table.pack(rawRunCommand(name, cmd, conf[name], ...)) + results[name] = table.pack(rawRunCommand(conf, name, cmd, conf[name], ...)) end return results end return rc + From dcc17687d571ed16244fe6c646263ec4908268f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 25 Feb 2015 02:24:41 +0100 Subject: [PATCH 14/14] Added man file for rc script system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Łukasz Magiera --- .../opencomputers/loot/OpenOS/usr/man/rc | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/rc diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/rc b/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/rc new file mode 100644 index 000000000..35a52cfcc --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/rc @@ -0,0 +1,36 @@ +NAME + rc - Manage services + +SYNOPSIS + rc SERVICE COMMAND [ARGS...] + +DESCRIPTION + Controls services in /etc/rc.d/ + Common commands are start/stop/restart, there are also special commands enable/disable. A command is global function in executable file that is stored in /etc/rc.d/ directory. Service cen define own commands. + +COMMANDS + start + This command starts specified service, executed automatically for all enbled services when system boots. + + stop + This command stops specified service. + + restart + This command restarts specified service. This command doesn't have to be implemented by services when start and stop commands are present. + + enable + This command enables specified service. Executing this command won't start the service. It's implemented by the rc library, but can be overridden by service. + + disable + This command disables specified service. Executing this command won't stop the service. It's implemented by the rc library, but can be overridden by service. + +EXAMPLES + rc example + Lists commands of example service. + + rc example start + Starts example setvice. + + rc example enable + Makes example start on system boot. +