Merge branch 'master-MC1.8' of github.com:MightyPirates/OpenComputers into OC1.5-MC1.8

Conflicts:
	build.properties
This commit is contained in:
Florian Nücke 2015-08-30 17:53:09 +02:00
commit fa720be2a4
141 changed files with 3128 additions and 432 deletions

Binary file not shown.

View File

@ -45,12 +45,13 @@ def getGitRef() {
if (System.getenv("BUILD_NUMBER") != null)
version += ".${System.getenv("BUILD_NUMBER")}"
else
version += "-" + getGitRef()
if (config.oc.subversion != null && config.oc.subversion != "")
version += "-${config.oc.subversion}"
if (System.getenv("BUILD_NUMBER") == null)
version += "+" + getGitRef()
ext.simpleVersion = version
version = "MC${config.minecraft.version}-${project.version}"
@ -238,6 +239,7 @@ idea.module.scopes.PROVIDED.plus += [configurations.provided]
sourceSets {
main {
scala {
exclude 'li/cil/oc/integration/agricraft/**'
exclude 'li/cil/oc/integration/appeng/**'
exclude 'li/cil/oc/integration/bloodmagic/**'
exclude 'li/cil/oc/integration/bluepower/**'

View File

@ -1,7 +1,7 @@
minecraft.version=1.8
forge.version=11.14.3.1450
oc.version=1.5.15
oc.version=1.5.16
oc.subversion=
ae2.version=rv2-beta-26

View File

@ -12,7 +12,7 @@ import li.cil.oc.api.detail.*;
*/
public class API {
public static final String ID_OWNER = "OpenComputers|Core";
public static final String VERSION = "5.5.3";
public static final String VERSION = "5.5.4";
public static DriverAPI driver = null;
public static FileSystemAPI fileSystem = null;

View File

@ -0,0 +1,27 @@
package li.cil.oc.api.driver.item;
import li.cil.oc.api.machine.Architecture;
import net.minecraft.item.ItemStack;
/**
* May be implemented in processor drivers of processors that can be reconfigured.
* <p/>
* This is the case for OC's built-in CPUs, for example, which can be reconfigured
* to any registered architecture. It a CPU has such a driver, it may also be
* reconfigured by the machine it is running in (e.g. in the Lua case via
* <tt>computer.setArchitecture</tt>).
*/
public interface MutableProcessor extends Processor {
/**
* Get a list of all architectures supported by this processor.
*/
java.util.Collection<Class<? extends Architecture>> allArchitectures();
/**
* Set the architecture to use for the specified processor.
*
* @param stack the processor to set the architecture for.
* @param architecture the architecture to use on the processor.
*/
void setArchitecture(ItemStack stack, Class<? extends Architecture> architecture);
}

View File

@ -126,10 +126,10 @@ opencomputers {
# happen.
startupDelay: 0.25
# The maximum size of the byte array that can be stored on EEPROMs.
# The maximum size of the byte array that can be stored on EEPROMs as executable data..
eepromSize: 4096
# The maximum size of the byte array that can be stored on EEPROMs.
# The maximum size of the byte array that can be stored on EEPROMs as configuration data.
eepromDataSize: 256
# The number of components the different CPU tiers support. This list
@ -767,6 +767,10 @@ opencomputers {
# Per-byte cost for ECDSA operation is controlled by `complex` value,
# because data is hashed with SHA256 before signing/verifying
dataCardAsymmetric: 10.0
# Energy required for one transposer operation (regardless of the number
# of items / fluid volume moved).
transposer: 1
}
# The rate at which different blocks accept external power. All of these
@ -1191,6 +1195,11 @@ opencomputers {
# properties, i.e. througput, frequency and buffer size.
# Valid values are: 0 = none, 1 = tier 1, 2 = tier 2, 3 = tier 3.
serverRackSwitchTier: 1
# Enforced delay when changing a redstone emitting component's output,
# such as the redstone card and redstone I/O block. Lowering this can
# have very negative impact on server TPS, so beware.
redstoneDelay: 0.1
}
# Settings for mod integration (the mod previously known as OpenComponents).

View File

@ -0,0 +1,5 @@
{
"variants": {
"normal": { "model": "opencomputers:relay" }
}
}

View File

@ -0,0 +1,5 @@
{
"variants": {
"normal": { "model": "opencomputers:transposer" }
}
}

View File

@ -2,6 +2,8 @@
![AAA](oredict:oc:accessPoint)
*This block is deprecated and will be removed in a future version.* Craft it into a [relay](relay.md) to avoid losing it.
The access point is the wireless version of the [switch](switch.md). It can be used to separate subnetworks so that machines in them will not see [components](../general/computer.md) in other networks, while still allowing to send network messages to the machines in other networks.
In addition to that, this block can act as a repeater: it can re-send wired messages as wired messages to other devices; or wireless messages as wired or wireless messages.

View File

@ -36,10 +36,9 @@ Keep in mind that some of these may not be available, depending on the recipe se
* [Disassembler](disassembler.md)
## Networking
* [Access Point](accessPoint.md)
* [Cable](cable.md)
* [Net Splitter](netSplitter.md)
* [Switch](switch.md)
* [Relay](relay.md)
## Power management
* [Capacitor](capacitor.md)

View File

@ -2,6 +2,6 @@
![*.net *.split](oredict:oc:netSplitter)
The net splitter is a device that allows controlling connectivity between subnetworks. Unlike the [switch](switch.md) or [power converter](powerConverter.md) it directly connects adjacent subnetworks, i.e. components can be accessed. Each side's connectivity can be toggled using a wrench (e.g. the [scrench](../item/wrench.md)). When a redstone signal is applied to the net splitter, all sides' connectivity is inverted.
The net splitter is a device that allows controlling connectivity between subnetworks. Unlike the [relay](relay.md) or [power converter](powerConverter.md) it directly connects adjacent subnetworks, i.e. components can be accessed. Each side's connectivity can be toggled using a wrench (e.g. the [scrench](../item/wrench.md)). When a redstone signal is applied to the net splitter, all sides' connectivity is inverted.
This block can therefore be used to toggle connectivity to certain parts of a component network. Use a [redstone I/O block](redstone.md) or [redstone cards](../item/redstoneCard1.md) to automate the net splitter.

View File

@ -0,0 +1,13 @@
# Relay
![Building bridges.](oredict:oc:relay)
The relay can be used to allow different subnetworks to send network messages to each other, without exposing components to [computers](../general/computer.md) in other networks. Keeping components local is usually a good idea, to avoid [computers](../general/computer.md) using the wrong [screen](screen1.md) or to avoid component overflows to happen (causing [computers](../general/computer.md) to crash and refuse to boot up).
The relay can be upgraded by inserting a [wireless network card](../item/wlanCard.md) to also relay messages wirelessly. Wireless messages can be received and relayed by other relays with a wireless network card, or by [computers](../general/computer.md) with a wireless network card.
Alternatively the relay can be upgraded using [linked cards](../item/linkedCard.md). In this case it will forward messages through the tunnel provided by the linked card, too; at the usual cost, so make sure the relay is sufficiently powered.
Relays do *not* keep track of which packets they forwarded recently, so avoid cycles in your network or you may receive the same packet multiple times. Due to the limited buffer size of relays, sending messages too frequently will result in packet loss. You can upgrade your relays to increase the speed with which they relay messages, as well as their internal message queue size.
Packets are only re-sent a certain number of times, so chaining an arbitrary number of relays is not possible. By default, a packet will be re-sent up to five times.

View File

@ -6,4 +6,4 @@ A server rack houses up to four [servers](../item/server1.md). A [server](../ite
Each [server](../item/server1.md) in a server rack can only communicate with one "face" of the server rack at a time - or none at all. Which side each [server](../item/server1.md) is connected to can be configured in the server rack's GUI. Beware that the sides are from the point of view of the server rack, i.e. if you are looking at the front of the server rack, `sides.right` will be to your left and vice versa.
Server racks act as [switch](switch.md) and [power distributor](powerDistributor.md) in one. The switch mode of the server rack can be configured in its GUI, with the two options being internal and external. In external mode the server rack will behave like a normal [switch](switch.md). In internal mode, messages are only passed to the [servers](../item/server1.md) in the rack, and will not be automatically relayed to the other faces of the rack. [Servers](../item/server1.md) will still be able to send messages to each other. This allows using server racks as advanced [switches](switch.md) that can perform filter and mapping operations, for example.
Server racks act as [relay](relay.md) and [power distributor](powerDistributor.md) in one. The switch mode of the server rack can be configured in its GUI, with the two options being internal and external. In external mode the server rack will behave like a normal [relay](relay.md). In internal mode, messages are only passed to the [servers](../item/server1.md) in the rack, and will not be automatically relayed to the other faces of the rack. [Servers](../item/server1.md) will still be able to send messages to each other. This allows using server racks as advanced [relays](relay.md) that can perform filter and mapping operations, for example.

View File

@ -2,6 +2,8 @@
![Building bridges.](oredict:oc:switch)
*This block is deprecated and will be removed in a future version.* Craft it into a [relay](relay.md) to avoid losing it.
The switch can be used to allow different subnetworks to send network messages to each other, without exposing components to [computers](../general/computer.md) in other networks. Keeping components local is usually a good idea, to avoid [computers](../general/computer.md) using the wrong [screen](screen1.md) or to avoid component overflows to happen (causing [computers](../general/computer.md) to crash and refuse to boot up).
There is also a wireless variation of this block, called the [access point](accessPoint.md), which will also relay messages wirelessly. Wireless messages can be received and relayed by other [access points](accessPoint.md), or by [computers](../general/computer.md) with a [wireless network card](../item/wlanCard.md).

View File

@ -0,0 +1,9 @@
# Transposer
![Such a poser.](oredict:oc:transposer)
The transposer bridges the gap between redstone controlled hoppers and [robots](robot.md), allowing [computer](../general/computer.md)-controlled transferral of items and fluids between adjacent blocks.
*Note that this block has no internal inventory.*
Besides moving things around, it can also be used to inspect the contents of the adjacent inventories, like an [adapter](adapter.md) with an [inventory controller upgrade](../item/inventoryControllerUpgrade.md) could, and the contents of adjacent tanks, like and adapter with a [tank controller upgrade](../item/tankControllerUpgrade.md) could.

View File

@ -2,4 +2,4 @@
![Enter the network.](oredict:oc:lanCard)
The network card allows [computers](../general/computer.md) to send and receive network messages. Messages (or packets) can be broadcasted to all receiving nodes in a subnetwork, or sent to a specific node with a specified address. [Switches](../block/switch.md) and [access points](../block/accessPoint.md) can be used to bridge multiple subnetworks by relaying messages between the subnetworks they are connected to. It is also possible to send a targeted message if the receiver is in another subnetwork, if the networks are connected via one or more [switches](../block/switch.md).
The network card allows [computers](../general/computer.md) to send and receive network messages. Messages (or packets) can be broadcasted to all receiving nodes in a subnetwork, or sent to a specific node with a specified address. [Relays](../block/relay.md) can be used to bridge multiple subnetworks by relaying messages between the subnetworks they are connected to. It is also possible to send a targeted message if the receiver is in another subnetwork, if the networks are connected via one or more [relays](../block/relay.md).

View File

@ -2,6 +2,8 @@
![AAA](oredict:oc:accessPoint)
*Этот блок устарел и будет удален в следующих версиях.* Замените его на [ретранслятор](relay.md).
Точки доступа, это беспроводные версии [коммутаторов](switch.md). Они могут быть использованы, когда требуется разделить подсети, чтобы устройства не видели [компоненты](../general/computer.md) в других сетях, однако сохраняя при этом возможность передачи сообщений между подсетями.
В дополнение к этому, точки доступа могут использоваться как повторители: они могут перенаправлять сообщения из проводной линии другим устройствам; или беспроводные сообщения как проводные, так и беспроводные.

View File

@ -39,6 +39,7 @@
* [Точка доступа](accessPoint.md)
* [Кабель](cable.md)
* [Сетевой переключатель](netSplitter.md)
* [Ретранслятор](relay.md)
* [Коммутатор](switch.md)
## Управление питанием

View File

@ -2,6 +2,6 @@
![*.net *.split](oredict:oc:netSplitter)
Сетевой переключатель позволяет контролировать соединение между подсетями. В отличие от [коммутатора](switch.md) или [конвертера энергии](powerConverter.md) позволяет непосредственно соединить подсети, делая при этом доступными все компоненты. Соединение каждой стороны переключается [ключем](../item/wrench.md). При подаче редстоун-сигнала все соединения инвертируются.
Сетевой переключатель позволяет контролировать соединение между подсетями. В отличие от [ретранслятора](relay.md) или [конвертера энергии](powerConverter.md) позволяет непосредственно соединить подсети, делая при этом доступными все компоненты. Соединение каждой стороны переключается [ключем](../item/wrench.md). При подаче редстоун-сигнала все соединения инвертируются.
Таким образом, этот блок может быть использован для переключения соединения определенных компонентов сети. Используйте [редстоун-I/O](redstone.md) или [редстоун карты](../item/redstoneCard1.md) для автоматизации сетевого переключателя.

View File

@ -0,0 +1,13 @@
# Ретранслятор
![Строит мосты.](oredict:oc:relay)
Ретранслятор используется для передачи сообщений между несколькими подсетями, изолируя компоненты [компьютеров](../general/computer.md) в других сетях. Сохранение компонентов, как правило, хорошая идея, что не позволяет [компьютерам](../general/computer.md) использовать неверный [монитор](screen1.md) или не позволяет перенагружать их (в результате чего [компьютеры](../general/computer.md) выключатся и отказываются загружаться).
Может быть улучшен добавлением [беспроводной сетевой карты](../item/wlanCard.md), что позволит ретранслировать беспроводные сообщения. Сообщения, переданные по беспроводной линии могут быть получены или перенаправлены другими ретрансляторами или [компьютерами](../general/computer.md) с [беспроводной сетевой картой](../item/wlanCard.md).
Также ретранслятор может быть улучшен с помощью [соединенной карты](../item/linkedCard.md). Это позволит передавать сообщения внутри туннеля, предоставленного картой, также; с обычными затратами энергии, поэтому убедитесь, что на ретранслятор поступает нужное количество энергии.
Ретрансляторы *не* отслеживают, какие пакеты и куда они передали, поэтому для в сети могут образовываться петли или вы можете получать одно сообщение несколько раз. Из-за ограниченного буфера сообщений коммутатора, частое отправление сообщений приводит к их потере. Вы можете улучшить ретранслятор для увеличения скорости обработки сообщений, а также увеличения размера сообщений.
Сообщения, могут перенаправлены всего несколько раз, поэтому цепочки с произвольным количеством ретрансляторов невозможны. По умолчанию, сообщение может быть перенаправлено пять раз.

View File

@ -6,4 +6,4 @@
Каждый [сервер](../item/server1.md) в серверной стойке может взаимодействовать только с одной "стороной" стойки или ни с какой. К какой стороне, какой [сервер](../item/server1.md) подключен, настраивается в интерфейсе стойки. Будьте внимательны, стороны считаются относительно самой стойки, например, если вы смотрите на стойку спереди, то `правая сторона` стойки для вас будет слева.
Серверные стойки взаимодействуют с [коммутаторами](switch.md) и [распределителями энергии](powerDistributor.md). Переключатель режимов работы стойки, может быть настроен в интерфейсе самой стойки, он имеет 2 режима: внешний и внутренний. Во внешнем режиме сервер будет работать как обычный [коммутатор](switch.md). Во внутреннем режиме, сообщения будут передаваться только к [серверам](../item/server1.md) в стойке и не будут автоматически связаны со сторонами стойки. [Серверы](../item/server1.md) все также будут иметь возможность передачи сообщений друг другу. Это позволяет использовать серверные стойки как продвинутые [коммутаторы](switch.md) для операций фильтрации и направления данных, например.
Серверные стойки взаимодействуют с [ретрансляторами](relay.md) и [распределителями энергии](powerDistributor.md). Переключатель режимов работы стойки, может быть настроен в интерфейсе самой стойки, он имеет 2 режима: внешний и внутренний. Во внешнем режиме сервер будет работать как обычный [ретранслятор](relay.md). Во внутреннем режиме, сообщения будут передаваться только к [серверам](../item/server1.md) в стойке и не будут автоматически связаны со сторонами стойки. [Серверы](../item/server1.md) все также будут иметь возможность передачи сообщений друг другу. Это позволяет использовать серверные стойки как продвинутые [ретрансляторы](relay.md) для операций фильтрации и направления данных, например.

View File

@ -2,6 +2,8 @@
![Строит мосты.](oredict:oc:switch)
*Этот блок устарел и будет удален в следующих версиях.* Замените его на [ретранслятор](relay.md).
Коммутатор используется для передачи сообщений между несколькими подсетями, не используя компоненты [компьютеров](../general/computer.md) в других сетях. Сохранение компонентов, как правило, хорошая идея, что не позволяет [компьютерам](../general/computer.md) использовать неверный [монитор](screen1.md) или не позволяет перенагружать их (в результате чего [компьютеры](../general/computer.md) выключатся и отказываются загружаться).
Также есть беспроводная версия коммутатора, называемая [точка доступа](accessPoint.md), с ее помощью сообщения передаются по беспроводной линии. Сообщения, переданные по беспроводной линии могут быть получены или перенаправлены другими [точками доступа](accessPoint.md) или [компьютерами](../general/computer.md) с [беспроводной сетевой картой](../item/wlanCard.md).

View File

@ -0,0 +1,9 @@
# Транспозер
![Такая проблемка.](oredict:oc:transposer)
Транспозер заполняет пробел между воронками, контролируемыми редстоун-сигналом и [роботами](robot.md), позволяя [компьютерам](../general/computer.md) контролировать перемещение предметов и жидкостей между соседними блоками.
*Данный блок не имеет внутреннего инвентаря.*
Кроме перемещения блоков, он также может быть использован для проверки содержимого соседних инвентарей, подобно [адаптеру](adapter.md) с [контроллером инвентаря](../item/inventoryControllerUpgrade.md), и содержимого соседних хранилищ жидкости, подобно адаптеру с [контроллером жидкости](../item/tankControllerUpgrade.md).

View File

@ -2,4 +2,4 @@
![Войди в сеть.](oredict:oc:lanCard)
Сетевая карта позволяет [компьютерам](../general/computer.md) отправлять и получать сетевые сообщения. Сообщения (или пакеты) будут отправлены всем принимающим устройствам в подсети или конкретной сетевой карте (после указания ее адреса). [Коммутаторы](../block/switch.md) и [точки доступа](../block/accessPoint.md) могут быть использованы для связи нескольких подсетей друг с другом, для передачи сообщений в них. Также возможно отправить письмо получателю, даже если он находится в другой подсети, если сеть подключена к одному или нескольким [коммутаторам](../block/switch.md).
Сетевая карта позволяет [компьютерам](../general/computer.md) отправлять и получать сетевые сообщения. Сообщения (или пакеты) будут отправлены всем принимающим устройствам в подсети или конкретной сетевой карте (при указании её адреса). [Ретрансляторы](../block/relay.md) могут быть использованы для связи нескольких подсетей друг с другом и передачи сообщений. Также возможно отправить письмо получателю, даже если он находится в другой подсети, если сеть подключена к одному или нескольким [ретрасляторами](../block/relay.md).

View File

@ -3,7 +3,7 @@
# Use [nl] to for a line break.
# Blocks
tile.oc.accessPoint.name=Access Point
tile.oc.accessPoint.name=§cAccess Point§7
tile.oc.adapter.name=Adapter
tile.oc.assembler.name=Electronics Assembler
tile.oc.cable.name=Cable
@ -23,20 +23,22 @@ tile.oc.hologram2.name=Hologram Projector (Tier 2)
tile.oc.keyboard.name=Keyboard
tile.oc.microcontroller.name=Microcontroller
tile.oc.motionSensor.name=Motion Sensor
tile.oc.netSplitter.name=Net Splitter
tile.oc.powerConverter.name=Power Converter
tile.oc.powerDistributor.name=Power Distributor
tile.oc.print.name=3D Print
tile.oc.printer.name=3D Printer
tile.oc.raid.name=Raid
tile.oc.redstone.name=Redstone I/O
tile.oc.relay.name=Relay
tile.oc.robot.name=Robot
tile.oc.robotAfterimage.name=Robot
tile.oc.screen1.name=Screen (Tier 1)
tile.oc.screen2.name=Screen (Tier 2)
tile.oc.screen3.name=Screen (Tier 3)
tile.oc.serverRack.name=Server Rack
tile.oc.switch.name=Switch
tile.oc.netSplitter.name=Net Splitter
tile.oc.switch.name=§cSwitch§7
tile.oc.transposer.name=Transposer
tile.oc.waypoint.name=Waypoint
# Items
@ -235,6 +237,7 @@ oc:container.Disassembler=Disassembler
oc:container.DiskDrive=Disk Drive
oc:container.Printer=Printer
oc:container.Raid=Raid
oc:container.Relay=Relay
oc:container.Server=Server
oc:container.ServerRack=Server Rack
oc:container.Switch=Switch
@ -328,6 +331,7 @@ oc:tooltip.RedstoneCard.RedNet=§fRedNet§7 is §asupported§7.
oc:tooltip.RedstoneCard.WirelessCBE=§fWireless Redstone (ChickenBones)§7 is §asupported§7.
oc:tooltip.RedstoneCard.WirelessSV=§fWireless Redstone (SlimeVoid)§7 is §asupported§7.
oc:tooltip.RedstoneCard=Allows reading and emitting redstone signals around the computer or robot.
oc:tooltip.Relay=Allows connecting different networks to each other. Only network messages will be passed along, components will not be visible through this. Use this to separate networks while still allowing communication using Network Cards, for example.
oc:tooltip.Robot=Unlike computers, robots can move around and interact with the world much like a player can.[nl] §cCan not connect to external components.§7
# The underscore makes sure this isn't hidden with the rest of the tooltip.
oc:tooltip.Robot_Level=§fLevel§7: §a%s§7
@ -345,6 +349,7 @@ oc:tooltip.Tier=§8Tier %s
oc:tooltip.NetSplitter=Acts as a dynamic connector. Connectivity of each side can be toggled by hitting it with a wrench. Connectivity of all sides can be inverted by applying a redstone signal.
oc:tooltip.TooLong=Hold [§f%s§7] for a detailed tooltip.
oc:tooltip.Transistor=A basic element in most other computer parts. It's a bit twisted, but it does the job.
oc:tooltip.Transposer=Allows automated transferral of items and fluids between adjacent inventories and fluid containers.
oc:tooltip.UpgradeAngel=Allows robots to place blocks in thin air, even if there is no point of reference.
oc:tooltip.UpgradeBattery=Increase the amount of energy a device can store, allowing it work longer without having to be recharged. [nl] Capacity: §f%s§7
oc:tooltip.UpgradeChunkloader=If a robot moves in a forest and no one is around to see it, does it really move? This upgrades makes sure it does. It keeps the chunk a device is in loaded, but continually consumes energy while active.

View File

@ -3,7 +3,7 @@
# Use [nl] to for a line break.
# Blocks
tile.oc.accessPoint.name=Точка доступа
tile.oc.accessPoint.name=§cТочка доступа§7
tile.oc.adapter.name=Адаптер
tile.oc.assembler.name=Сборщик роботов
tile.oc.cable.name=Кабель
@ -23,6 +23,7 @@ tile.oc.hologram2.name=Голографический проектор (2-ой
tile.oc.keyboard.name=Клавиатура
tile.oc.microcontroller.name=Микроконтроллер
tile.oc.motionSensor.name=Датчик движения
tile.oc.netSplitter.name=Сетевой переключатель
tile.oc.powerConverter.name=Преобразователь энергии
tile.oc.powerDistributor.name=Распределитель энергии
tile.oc.print.name=3D модель
@ -35,8 +36,8 @@ tile.oc.screen1.name=Монитор (1-ый уровень)
tile.oc.screen2.name=Монитор (2-ой уровень)
tile.oc.screen3.name=Монитор (3-ий уровень)
tile.oc.serverRack.name=Серверная стойка
tile.oc.switch.name=Коммутатор
tile.oc.netSplitter.name=Сетевой переключатель
tile.oc.switch.name=§cКоммутатор§7
tile.oc.transposer.name=Транспозер
tile.oc.waypoint.name=Путевая точка
# Items
@ -232,6 +233,7 @@ oc:container.Disassembler=Разборщик
oc:container.DiskDrive=Дисковод
oc:container.Printer=Принтер
oc:container.Raid=RAID
oc:container.Relay=Ретранслятор
oc:container.Server=Сервер
oc:container.ServerRack=Серверная стойка
oc:container.Switch=Коммутатор
@ -325,6 +327,7 @@ oc:tooltip.RedstoneCard.RedNet=Мод §fRedNet§7 §aподдерживаетс
oc:tooltip.RedstoneCard.WirelessCBE=Мод §fWireless Redstone (ChickenBones)§7 §aподдерживается§7.
oc:tooltip.RedstoneCard.WirelessSV=Мод §fWireless Redstone (SlimeVoid)§7 §aподдерживается§7.
oc:tooltip.RedstoneCard=Позволяет принимать и излучать сигналы красного камня вокруг компьютера или робота.
oc:tooltip.Relay=Позволяет соединять различные сети между собой. Передаются только сообщения, компоненты между сетями недоступны. Используйте его для разделения сетей с возможностью пересылать сообщения между ними.
oc:tooltip.Robot=В отличие от компьютеров, роботы могут передвигаться и взаимодействовать с миром, как игрок.[nl] §cНе могут взаимодействовать с внешними компонентами.§7
# The underscore makes sure this isn't hidden with the rest of the tooltip.
oc:tooltip.Robot_Level=§fУровень§7: §a%s§7.
@ -342,6 +345,7 @@ oc:tooltip.Tier=§8Уровень %s
oc:tooltip.NetSplitter=Работает как переключатель. Соединение каждой стороны переключается ключем. При подаче сигнала красного камня все соединения инвертируются.
oc:tooltip.TooLong=Удерживайте [§f%s§7], чтобы отобразить описание.
oc:tooltip.Transistor=Базовый элемент для других частей компьютера. Он немного деформирован, но отлично выполняет свою работу.
oc:tooltip.Transposer=Позволяет автоматизировать перемещение блоков и жидкостей между соседними инвентарями и хранилищами жидкости.
oc:tooltip.UpgradeAngel=Позволяет роботам размещать блоки в воздухе, даже если отсутствует точка опоры.
oc:tooltip.UpgradeBattery=Увеличивает количество энергии, которую робот может хранить, это позволяет ему работать дольше без перезарядки.
oc:tooltip.UpgradeChunkloader=Если робот движется в лесу и никто его не видит, действительно ли он движется? Это улучшение гарантирует, что движется. Оно держит чанк, на котором находится робот, загруженным, но постоянно потребляет энергию.

View File

@ -31,6 +31,16 @@ function term.clear()
cursorX, cursorY = 1, 1
end
function term.reset()
if term.isAvailable() then
local maxw, maxh = component.gpu.maxResolution()
component.gpu.setResolution(maxw, maxh)
component.gpu.setBackground(0x000000)
component.gpu.setForeground(0xFFFFFF)
term.clear()
end
end
function term.clearLine()
if term.isAvailable() then
local w = component.gpu.getResolution()

View File

@ -12,7 +12,7 @@ Most programs can be interrupted by pressing Ctrl+Alt+C.
Paste the contents of the clipboard using the middle mouse button or a configurable key (default: insert).
Computers will consume less power while idling - i.e. when os.sleep(n > 0.05) is called.
Screens will consume more power the more lit characters they display.
Most blocks act as 'cables' - use switches and power distributers to create separate networks.
Most blocks act as 'cables' - use relays and power distributors to create separate networks.
Welcome to the dark side - here, have some cookies.
Screens can display Unicode - paste the special chars or use unicode.char.
Run `help` or `man programname` for ingame help on programs shipped with OpenOS - start with `man man`.
@ -25,4 +25,4 @@ Have you tried turning it off and on again?
To disable this greeting, install OpenOS to a writeable medium and delete `/etc/motd`.
Did you know OpenComputers has a forum? No? Well, it's at http://oc.cil.li/.
Please report bugs on the Github issue tracker, thank you!
Beware of cycles when building networks, or you may get duplicate messages!
Beware of cycles when building networks, or you may get duplicate messages!

View File

@ -8,7 +8,7 @@ if #args == 0 then
until not read
else
for i = 1, #args do
local file, reason = io.open(args[i])
local file, reason = io.open(args[i],"rb")--TODO: make b an option
if not file then
io.stderr:write(reason .. "\n")
return

View File

@ -67,6 +67,8 @@ for n = 1, options.count do
end
if options.wait then
os.sleep(tonumber(options.wait))
else
os.sleep(0)
end
end

View File

@ -5,7 +5,8 @@ local text = require("text")
local args, options = shell.parse(...)
local function formatSize(size)
if not options.h then
size = tonumber(size) or size
if not options.h or type(size) ~= "number" then
return tostring(size)
end
local sizes = {"", "K", "M", "G"}

View File

@ -73,6 +73,7 @@ local code = ""
codeHandler = function(char)
if char == "[" then code = code .. char
elseif char == "0" then code = code .. char
elseif char == "3" then code = code .. char
elseif code == "[" and char == "A" then
charHandler = baseHandler
if y - 1 < 1 then return end
@ -139,6 +140,16 @@ codeHandler = function(char)
out:write(text)
out:close()
end
elseif code == "[3" and char == "~" then
charHandler = baseHandler
if x > unicode.len(lines[y]) then
lines[y] = lines[y] .. (lines[y + 1] or "")
table.remove(lines, y + 1)
render(y, atline + edith - y)
return
end
lines[y] = lines[y]:sub(1, x-1) .. lines[y]:sub(x+1)
render(y, 1)
else
charHandler = baseHandler
end
@ -149,7 +160,7 @@ baseHandler = function(char)
code = ""
charHandler = codeHandler
elseif char == "\n" then
line = lines[y]
local line = lines[y]
lines[y] = unicode.sub(line or "", 1, x - 1)
table.insert(lines, y + 1, unicode.sub(line or "", x))
x = 1

View File

@ -199,6 +199,8 @@ local commandList = {}
-- \x1b9[Row];[Col];[Height];[Width]F -- fill
-- \x1b9[Row];[Col];[Height];[Width];[Dest Row];[Dest Col]c -- copy
--Add fake gpu component for compat(?)
function charHandlers.control(char)
if char == "\x1b" then
commandList = {}

View File

@ -2,6 +2,21 @@ local network = require "network"
local computer = require "computer"
local args = {...}
local function formatSize(size)
size = tonumber(size) or size
if type(size) ~= "number" then
return tostring(size)
end
local sizes = {"", "K", "M", "G"}
local unit = 1
local power = 1024
while size > power and unit < #sizes do
unit = unit + 1
size = size / power
end
return math.floor(size * 10) / 10 .. sizes[unit]
end
local function align(txt)return txt .. (" "):sub(#txt+1)end
if #args < 1 then
@ -14,7 +29,7 @@ if #args < 1 then
local pktIn, pktOut, bytesIn, bytesOut = network.info.getInterfaceInfo(node)
print(" RX packets:"..tostring(pktIn))
print(" TX packets:"..tostring(pktOut))
print(" RX bytes:"..tostring(bytesIn).." TX bytes:"..tostring(bytesOut))
print(" RX bytes: ".. tostring(bytesIn) .. " (" ..formatSize(bytesIn).. ") TX bytes: " ..tostring(bytesOut) .. " (".. formatSize(bytesOut) .. ")")
end
elseif args[1] == "bind" and args[2] then
print("Address attached")

View File

@ -1,13 +1,28 @@
--Plan9k userspace init for pipes kernel
--TODO: pcall all + emergency shell(or do it higher, in pipes)
local pipes = require("pipes")
local component = require("component")
local filesystem = require("filesystem")
local component = require("component")
os.setenv("LIBPATH", "/lib/?.lua;/usr/lib/?.lua;/home/lib/?.lua;./?.lua;/lib/?/init.lua;/usr/lib/?/init.lua;/home/lib/?/init.lua;./?/init.lua")
os.setenv("PATH", "/usr/local/bin:/usr/bin:/bin:.")
os.setenv("PWD", "/")
os.setenv("PS1", "\x1b[33m$PWD\x1b[31m#\x1b[39m ")
pipes.log("INIT: Mounting filesystems")
if filesystem.exists("/etc/fstab") then
for entry in io.lines("/etc/fstab") do
if entry:sub(1,1) ~= "#" then
end
end
end
pipes.log("INIT: Starting terminals")
if not filesystem.exists("/root") then
filesystem.makeDirectory("/root")
end
@ -37,7 +52,6 @@ end
local sin, sout
local screens = component.list("screen")
for gpu in component.list("gpu") do
local screen = screens()
@ -85,7 +99,11 @@ end
pcall(services)
local kout = io.popen(function()
pipes.setThreadName("/bin/tee.lua")
if filesystem.exists("/kern.log") then
filesystem.remove("/kern.log.old")
filesystem.rename("/kern.log", "/kern.log.old")
end
pipes.setThreadName("[init]/logd")
io.output(sout)
loadfile("/bin/tee.lua", nil, _G)("/kern.log")
end, "w")

View File

@ -1,5 +1,8 @@
local serialization = require("serialization")
local term = require("term")
local fs = require("filesystem")
local args = {...}
local env = setmetatable({}, {__index = _ENV})
@ -10,6 +13,13 @@ local function optrequire(...)
end
end
if args[1] and fs.exists(args[1]) then --non standard, require -i !!!
local f = io.open(args[1])
local code = load(f:read("*all"), "="..args[1], "t", env)
f:close()
xpcall(code, debug.traceback)
end
local hist = {}
while true do
io.write(tostring(env._PROMPT or "lua> "))

View File

@ -0,0 +1,44 @@
local term = require("term")
function usage()
print(
[[Usage:
more [options] ...
A file perusal filter for CRT viewing.]])
end
local args = {...}
local file = args[1]
if not file then usage() return end
file = io.open(file)
if not file then
print("File not found")
return
end
term.clear()
local _, h = term.getResolution()
io.write("\x1b[1;1H")
print("...",h)
for i = 1, h - 2 do
local line = file:read("*l")
if not line then print("input end")return end
print(line)
end
io.write("\x1b47m\x1b30m--More--\x1b39m\x1b49m")
while true do
local c = io.read(1)
if c == "\n" then
local line = file:read("*l")
if not line then return end
print("\r\x1b[K" .. line)
io.write("\x1b47m\x1b30m--More--\x1b39m\x1b49m")
elseif c == "q" then
return
end
end

View File

@ -203,6 +203,7 @@ while run do
if term.getCursor() > 1 then
io.write("\n")
end
io.write("\x1b49m\x1b39m")
io.write(expand(os.getenv("PS1")))
local cmd = term.read(history)--io.read("*l")
--print("--IN: ", cmd)

View File

@ -3,7 +3,7 @@ local args = {...}
local f = io.open(args[1], "a")
while true do
local data = io.read(1)
local data = io.read("*L")
if not data then
f:close()
return
@ -11,7 +11,7 @@ while true do
if io.input().remaining() > 0 then
data = data .. io.read(io.input().remaining())
end
io.write(data)
f:write(data)
f:flush()
io.write(data)
end

View File

@ -9,7 +9,6 @@ proxy.isReadOnly = function() return true end
proxy.rename = function() error("Permission Denied") end
proxy.remove = function() error("Permission Denied") end
proxy.setLabel = function() error("Permission Denied") end
proxy.seek = function() error("Not supported") end
proxy.size = function(path)
local seg = kernel.modules.vfs.segments(path)
local file = data
@ -22,7 +21,17 @@ proxy.getLabel = function() return "devfs" end
local allocator, handles = kernel.modules.util.getAllocator()
proxy.exists = function()end
proxy.exists = function(path)
local seg = kernel.modules.vfs.segments(path)
local file = data
for _, d in pairs(seg) do
if not file[d] then
return false
end
file = file[d]
end
return file and true or false
end
proxy.open = function(path)
local seg = kernel.modules.vfs.segments(path)
local file = data
@ -48,6 +57,9 @@ end
proxy.write = function(h, ...)
return handles[h].file.write(handles[h], ...)
end
proxy.seek = function(h, ...)
return handles[h].file.seek(handles[h], ...)
end
proxy.isDirectory = function(path)
local seg = kernel.modules.vfs.segments(path)
local dir = data
@ -69,8 +81,8 @@ proxy.list = function(path)
error("File is not a directory")
end
local list = {}
for f in pairs(dir) do
list[#list + 1] = f
for f, node in pairs(dir) do
list[#list + 1] = f .. (node.__type and "" or "/")
end
return list
end
@ -80,6 +92,12 @@ data.null = {
__type = "f",
write = function()end
}
data.kmsg = {
__type = "f",
write = function(h, data)
kernel.io.println(data)
end
}
data.zero = {
__type = "f",
read = function(h, c)

View File

@ -15,6 +15,7 @@ proxy.getLabel = function() return "procfs" end
local allocator, handles = kernel.modules.util.getAllocator()
proxy.exists = function()end
proxy.open = function(path)
local seg = kernel.modules.vfs.segments(path)
local file = data
@ -32,16 +33,21 @@ proxy.open = function(path)
end
return hnd.id
end
proxy.read = function(h, n)
return handles[h]:read(n)
end
proxy.close = function(h)
allocator:unset(handles[h])
end
proxy.write = function() error("Permission Denied") end
proxy.isDirectory = function()
end
proxy.list = function(path)
local seg = kernel.modules.vfs.segments(path)
local dir = data
@ -51,11 +57,11 @@ proxy.list = function(path)
local list = {}
for pid, thr in pairs(kernel.modules.threading.threads) do
if thr.coro and dir == data then
list[#list + 1] = tostring(pid)
list[#list + 1] = tostring(pid) .. "/"
end
end
for f in pairs(dir) do
list[#list + 1] = f
for f, node in pairs(dir) do
list[#list + 1] = f .. (type(node) == "table" and "/" or "")
end
return list
end
@ -72,13 +78,36 @@ data.cpuinfo = function()
"cpu family : 1\n" ..
"model : 1\n" ..
"model name : OpenComputers Lua CPU @ unkown Tier\n" ..
"microcode : 0x52\n" ..
"microcode : " .. (string.pack and "0x53" or "0x52") .. "\n" ..
"physical id : 0\n"
end
data.uptime = function()
return tostring(computer.uptime())
end
setmetatable(data, {__index = function(_, k)
if tonumber(k) and kernel.modules.threading.threads[tonumber(k)] and kernel.modules.threading.threads[tonumber(k)].coro then
return {comm = function()return kernel.modules.threading.threads[tonumber(k)].name end}
return {
comm = function()return kernel.modules.threading.threads[tonumber(k)].name end,
limits = function()
local limits = "Limit Units Soft Limit\n"
limits = limits .. "Max pending signals signals " .. kernel.modules.threading.threads[tonumber(k)].maxPendingSignals .. "\n"
limits = limits .. "Max open files files " .. kernel.modules.threading.threads[tonumber(k)].maxOpenFiles .. "\n"
return limits
end,
status = function()
local status = ""
status = status .. "Name: " .. kernel.modules.threading.threads[tonumber(k)].name .. "\n"
status = status .. "State: " .. coroutine.status(kernel.modules.threading.threads[tonumber(k)].coro) .. "\n"
status = status .. "Pid: " .. kernel.modules.threading.threads[tonumber(k)].pid .. "\n"
status = status .. "Uid: " .. kernel.modules.threading.threads[tonumber(k)].uid .. "\n"
--TODO: count actual signals
status = status .. "SigQ: " .. #kernel.modules.threading.threads[tonumber(k)].eventQueue .. "/" .. kernel.modules.threading.threads[tonumber(k)].maxPendingSignals .. "\n"
return status
end
}
end
end})

View File

@ -51,6 +51,7 @@ function kernel.userspace.os.spawn(prog, ...)
local thread = kernel.modules.threading.spawn(prog, 0, name, isThread, _, ...)
thread.io_output = kernel.modules.threading.currentThread.io_output
thread.io_input = kernel.modules.threading.currentThread.io_input
thread.io_error = kernel.modules.threading.currentThread.io_error
return thread.pid
end
@ -78,6 +79,7 @@ end
function kernel.userspace.os.exit()
kernel.modules.threading.kill(kernel.modules.threading.currentThread.pid)
coroutine.yield("yield", 0)
end
function kernel.userspace.os.sleep(time)
@ -142,7 +144,12 @@ end
kernel.userspace.coroutine = {}
kernel.userspace.coroutine.yield = function(...)
return coroutine.yield(...)--TODO: FIX; move to debug
end
--lua 5.3 <-> 5.2 compat
kernel.userspace.bit32 = bit32 or load([[return {
band = function(a, b) return a & b end,
bor = function(a, b) return a | b end,
bxor = function(a, b) return a ~ b end,
bnot = function(a) return ~a end,
rshift = function(a, n) return a >> n end,
lshift = function(a, n) return a << n end,
}]])()

View File

@ -39,18 +39,17 @@ end
local function pathSearcher(module)
local filepath, reason = kernel.userspace.package.searchpath(module, kernel.userspace.os.getenv("LIBPATH"))
if filepath then
local loader, reason = kernel.userspace.loadfile(filepath, "bt", setmetatable({},{__index = kernel.userspace}))
local loader
loader, reason = kernel.userspace.loadfile(filepath, "bt", setmetatable({},{__index = kernel.userspace}))
if loader then
local state, mod = pcall(loader)
local state
state, reason = pcall(loader)
if state then
return mod
else
kernel.io.println("Module '" .. tostring(module) .. "' loading failed: " .. tostring(mod))
return reason
end
end
else
return nil, reason
end
return nil, reason
end
kernel.userspace.package.searchers[#kernel.userspace.package.searchers + 1] = preloadSearcher
@ -65,19 +64,23 @@ kernel.userspace.require = function(module)
if kernel.userspace.package.loading[module] then
error("Already loading "..tostring(module))
else
local reason
kernel.userspace.package.loading[module] = true
for _, searcher in ipairs(kernel.userspace.package.searchers) do
local res, mod, reason = pcall(searcher, module)
if res and mod then
local success, mod, res = pcall(searcher, module)
if success and mod then
kernel.userspace.package.loading[module] = nil
kernel.userspace.package.loaded[module] = mod
return mod
elseif not mod and reason then
kernel.io.println("Searcher for '" .. tostring(module) .. "' loading failed: " .. tostring(reason))
elseif (not success) and mod then
reason = mod
elseif res then
reason = res
end
end
kernel.userspace.package.loading[module] = nil
error("Could not load module " .. tostring(module))
error(string.format("Could not load module '%s': %s", module, reason or "module returned nil"))
end
end
end

View File

@ -0,0 +1,47 @@
cards = {}
local function buildDevfs()
for file in pairs(kernel.modules.devfs.data) do
if file == "urandom" then
kernel.modules.devfs.data[file] = nil
end
end
kernel.modules.devfs.data["urandom"] = {
__type = "f",
read = function(h, len)
return component.invoke(cards[1], "random", len)
end
}
end
local function onComponentAdded(_, address, componentType)
if componentType == "data" then
cards[#cards + 1] = address
buildDevfs()
end
end
local function onComponentRemoved(_, address, componentType)
if componentType == "data" then
local t
for i, card in ipairs(cards) do
if card == address then
t = i
break
end
end
table.remove(cards, t)
buildDevfs()
end
end
--function start()
--for card, t in component.list("data") do
-- onComponentAdded(_, card, t)
--end
--end
kernel.modules.keventd.listen("component_added", onComponentAdded)
kernel.modules.keventd.listen("component_removed", onComponentRemoved)

View File

@ -0,0 +1,117 @@
drives = {}
function writeSectors(drive, data, at)
local sectorSize = component.invoke(drive, "getSectorSize")
repeat
local atSector = math.floor((at - 1) / sectorSize) + 1
local inSectorStart = (at - 1) % sectorSize + 1
local writable = math.min(#data, sectorSize - inSectorStart + 1)
local old = component.invoke(drive, "readSector", atSector)
local before = old:sub(0, inSectorStart - 1)
local after = old:sub(inSectorStart + writable)
local toWrite = before .. data:sub(1, writable) .. after
data = data:sub(writable + 1)
kernel.io.println("Wd: " .. atSector .. "/" .. #toWrite .. ": "..inSectorStart.." [ " .. writable .. " ] "..(inSectorStart + writable) .. " #old="..#old)
component.invoke(drive, "writeSector", atSector, toWrite)
at = at + writable
until #data < 1
end
function readSectors(drive, at, len)
local data = ""
local sectorSize = component.invoke(drive, "getSectorSize")
repeat
local atSector = math.floor(at / sectorSize) + 1
sector = component.invoke(drive, "readSector", atSector)
kernel.io.println("Rsect " .. atSector .. ": " .. tostring((at - 1) % sectorSize + 1) .. " -> " .. tostring(math.min((at - 1) % sectorSize + len - #data, sectorSize)))
local read = sector:sub((at - 1) % sectorSize + 1, math.min((at - 1) % sectorSize + len - #data, sectorSize))
data = data .. read
at = at + #read
until #data >= len
return data
end
local function buildDevfs()
for file in pairs(kernel.modules.devfs.data) do
if file:match("^sd") then
kernel.modules.devfs.data[file] = nil
end
end
for k, drive in ipairs(drives) do
kernel.modules.devfs.data["sd" .. string.char(k + 96)] = {
__type = "f",
open = function(hnd)
--component.invoke(drive, "seek", -math.huge)
hnd.drive = drive
hnd.pos = 1
--kernel.io.println("Od: " .. hnd.pos .. "/" .. component.invoke(drive, "getCapacity"))
end,
size = function()
return component.invoke(drive, "getCapacity")
end,
write = function(h, data)
writeSectors(drive, data, h.pos)
--kernel.io.println("Wd: " .. h.pos .. "(+" .. #data .. ")/" .. component.invoke(drive, "getCapacity"))
h.pos = h.pos + #data
return not (h.pos >= component.invoke(drive, "getCapacity"))
--TODO: do this correctly
end,
read = function(h, len)
len = math.ceil(len)
kernel.io.println("Rd " .. tostring(len) .. ": " .. h.pos .. "/" .. component.invoke(drive, "getCapacity"))
if h.pos >= component.invoke(drive, "getCapacity") then
return
end
local data = readSectors(drive, h.pos, len)
h.pos = h.pos + len
return data
end,
seek = function(h, whence, offset)
offset = offset or 0
if whence == "end" then
h.pos = math.min(component.invoke(drive, "getCapacity"), math.max(1, component.invoke(drive, "getCapacity") - offset))
return h.pos - 1
elseif whence == "set" then
h.pos = math.min(component.invoke(drive, "getCapacity"), math.max(1, 1 + offset))
return h.pos - 1
else
h.pos = math.min(component.invoke(drive, "getCapacity"), math.max(1, h.pos + offset))
return h.pos - 1
end
return math.floor(h.pos)
end
}
end
end
local function onComponentAdded(_, address, componentType)
if componentType == "drive" then
drives[#drives + 1] = address
buildDevfs()
end
end
local function onComponentRemoved(_, address, componentType)
if componentType == "drive" then
local t
for i, drive in ipairs(drives) do
if drive == address then
t = i
break
end
end
table.remove(drives, t)
buildDevfs()
end
end
kernel.modules.keventd.listen("component_added", onComponentAdded)
kernel.modules.keventd.listen("component_removed", onComponentRemoved)

View File

@ -321,6 +321,7 @@ startNetwork = function()
end
sent = nil
else
--we've already requested this addr so if we get the route
--we'll respond
routeRequests[dest][#routeRequests[dest]+1] = {type = "R", host = origin}

View File

@ -15,20 +15,33 @@ local function buildDevfs()
end
component.invoke(tape, "seek", -math.huge)
hnd.tape = tape
hnd.pos = 0
end,
size = function()
return component.invoke(tape, "getSize")
end,
write = function(h, data)
component.invoke(tape, "write", data)
return not component.invoke(tape, "isEnd", data)
h.pos = h.pos + #data
return not (h.pos >= component.invoke(tape, "getSize"))
--TODO: do this correctly
end,
read = function(h, len)
if component.invoke(tape, "isEnd", data) then
if h.pos >= component.invoke(tape, "getSize") then
return
end
h.pos = h.pos + len
return component.invoke(tape, "read", len)
end,
seek = function(h, whence, offset)
if whence == "end" then
h.pos = h.pos + component.invoke(tape, "seek", component.invoke(tape, "getSize") - h.pos - (offset or 0))
elseif whence == "set" then
h.pos = h.pos + component.invoke(tape, "seek", (offset or 0) - h.pos)
else
h.pos = h.pos + component.invoke(tape, "seek", offset or 0)
end
return math.floor(h.pos)
end
}
end
@ -55,11 +68,11 @@ local function onComponentRemoved(_, address, componentType)
end
end
function start()
for tape, t in component.list("tape_drive") do
onComponentAdded(_, tape, t)
end
end
--function start()
-- for tape, t in component.list("tape_drive") do
-- onComponentAdded(_, tape, t)
-- end
--end
kernel.modules.keventd.listen("component_added", onComponentAdded)
kernel.modules.keventd.listen("component_removed", onComponentRemoved)

View File

@ -71,6 +71,8 @@ function spawn(exec, child, name, isthread, _, ...)
currentHandlerArg = nil,
eventQueue = {{"arg", ...}},
name = name or "unnamed",
maxPendingSignals = 32,
maxOpenFiles = 8,
uid = nextUid
}
@ -132,7 +134,7 @@ local function processSignals()
for _, thread in ipairs(threads) do
if thread.coro then
local nsig, oldest = countThreadSignals(thread, "signal")
if nsig > 32 then --TODO: make it a bit more intelligent
if nsig > thread.maxPendingSignals then --TODO: make it a bit more intelligent
table.remove(thread.eventQueue, oldest)
end
if thread.currentHandler == "yield" then

View File

@ -1,4 +1,5 @@
function joinThread(pid)
--coroutine.yield("yield", 0)
while true do
local dead = coroutine.yield("kill")
if pid == dead then
@ -30,7 +31,7 @@ function userKill(pid, signal, ...)
local args = {...}
local thread = kernel.modules.threading.threads[pid]
kernel.modules.manageg.protect(thread.sandbox)
--TODO: probably ser threading.currentThread here
--TODO: probably set threading.currentThread here
local res, reason = pcall(function()
thread.kill[signal](table.unpack(args))
end)
@ -41,7 +42,7 @@ function userKill(pid, signal, ...)
return true
end
function setKillHandler(signal, handler)
function setKillHandler(signal, handler) --WAT
if not kernel.modules.threading.threads[pid]
or not kernel.modules.threading.threads[pid].coro then
return nil, "Thread does not exists"

View File

@ -1,6 +1,8 @@
local term = {}
local function read(from, to)
term.escape = "\x1b"
local write = function(text) io.write(term.escape..text) end
local read = function(from, to)
local started, data
while true do
local char = io.read(1)
@ -19,6 +21,279 @@ local function read(from, to)
end
end
end
term.color={}
term.color.black=30
term.color.red=31
term.color.green=32
term.color.yellow=33
term.color.blue=34
term.color.magenta=35
term.color.cyan=36
term.color.white=37
term.attr={}
term.attr.resetAllAttr=0
term.attr.bright=1
term.attr.dim=2
term.attr.blink=5
term.attr.reverse=7
term.attr.hidden=8
------------------------------------------
--Set Display Attributes
------------------------------------------
--Set Attribute Mode *ESC*[{attr1};...;{attrn}m
function term.setAttr(attr)
write(attr.."m")
end
function term.setForeground(color)
write(color.."m")
end
function term.setBackground(color)
write((color+10).."m")
end
------------------------------------------
--Erasing Text
------------------------------------------
--Erase End of Line *ESC*[K
--Erases from the current cursor position to the end of the current line.
function term.eraseEndOfLine()
write("[K")
end
--Erase Start of Line *ESC*[1K
--Erases from the current cursor position to the start of the current line.
function term.eraseStartOfLine()
write("[1K")
end
--Erase Line *ESC*[2K
--Erases the entire current line.
function term.eraseLine()
write("[2K")
end
term.clearLine = term.eraseLine
--Erase Down *ESC*[J
--Erases the screen from the current line down to the bottom of the screen.
function term.eraseDown()
write("[J")
end
--Erase Up *ESC*[1J
--Erases the screen from the current line up to the top of the screen.
function term.eraseUp()
write("[1J")
end
--Erase Screen *ESC*[2J
--Erases the screen with the background colour and moves the cursor to home.
function term.clear()
write("[2J")
end
-------------------------------------------
--Tab Control
------------------------------------------
--Set Tab *ESC*H
--Sets a tab at the current position.
function term.tab()
write("[H")
end
--Clear Tab *ESC*[g
--Clears tab at the current position.
function term.clearTab()
write("[g")
end
--Clear All Tabs *ESC*[3g
--Clears all tabs.
function term.clearTabs()
write("[3g")
end
------------------------------------------
--Scrolling
------------------------------------------
--Scroll Screen *ESC*[r
--Enable scrolling for entire display.
function term.enableScroll()
write("[r")
end
--Scroll Screen *ESC*[{start};{end}r
--Enable scrolling from row {start} to row {end}.
function term.scrollScreen(from,to)
write(string.format("[%d;%dr",from,to))
end
--Scroll Down *ESC*D
--Scroll display down one line.
function term.scrollScreenDown()
write("D")
end
--Scroll Up *ESC*M
--Scroll display up one line.
function term.scrollScreenUp()
write("M")
end
------------------------------------------
--Cursor Control
------------------------------------------
--Cursor Home *ESC*[{ROW};{COLUMN}H
--Sets the cursor position where subsequent text will begin. If no row/column parameters are provided (ie. *ESC*[H), the cursor will move to the home position, at the upper left of the screen.
function term.setCursorPosition(row,col)
write(string.format("[%d;%dH", row, col))
end
function term.resetCursor()
write("[H")
end
--Cursor Up *ESC*[{COUNT}A
--Moves the cursor up by COUNT rows; the default count is 1.
function term.cursorUp(count)
write(string.format("[%dA",(count or 1)))
end
--Cursor Down *ESC*[{COUNT}B
--Moves the cursor down by COUNT rows; the default count is 1.
function term.cursorDown(count)
write(string.format("[%dB",(count or 1)))
end
--Cursor Forward *ESC*[{COUNT}C
--Moves the cursor forward by COUNT columns; the default count is 1.
function term.cursorForward(count)
write(string.format("[%dC",(count or 1)))
end
--Cursor Backward *ESC*[{COUNT}D
--Moves the cursor backward by COUNT columns; the default count is 1.
function term.cursorBackward(count)
write(string.format("[%dD",(count or 1)))
end
--Force Cursor Position *ESC*[{ROW};{COLUMN}f
--Identical to Cursor Home.
function term.forceCursorPosition(row, col)
write(string.format("[%d;%df", row, col))
end
--Save Cursor *ESC*[s
--Save current cursor position.
function term.saveCursor()
write("[s")
end
--Unsave Cursor *ESC*[u
--Restores cursor position after a Save Cursor.
function term.restoreCursor()
write("[u")
end
--Save Cursor & Attrs *ESC*7
--Save current cursor position.
function term.saveCursorAndAttr()
write("7")
end
--Restore Cursor & Attrs *ESC*8
--Restores cursor position after a Save Cursor.
function term.restoreCursorAndAttr()
write("8")
end
------------------------------------------
--Terminal Setup
------------------------------------------
--Reset Device *ESC*c
--Reset all terminal settings to default.
function term.reset()
write("c")
end
--Enable Line Wrap *ESC*[7h
--Text wraps to next line if longer than the length of the display area.
function term.enableLineWrap()
write("[7h")
end
--Disable Line Wrap *ESC*[7l
--Disables line wrapping.
function term.disableLineWrap()
write("[7l")
end
------------------------------------------
--Plan9k codes
------------------------------------------
-- \x1b9[H];[W]R - set resolution
function term.setResolution(height,width)
write(string.format("9%d;%dR", height, width))
end
-- \x1b9[Row];[Col];[Height];[Width]F -- fill
function term.fill(row, col, height, width)
write(string.format("9%d;%d;%d;%dF", row, col, height, width))
end
-- \x1b9[Row];[Col];[Height];[Width];[Dest Row];[Dest Col]c -- copy
function term.copy(row, col, height, width, destRow, destCol)
write(string.format("9%d;%d;%d;%d;%d;%dc", row, col, height, width, destRow, destCol ))
end
--get resolution
function term.getResolution()
local y, x = term.getCursorPosition()
term.setCursorPosition(999,999)
local h, w = term.getCursorPosition()
term.setCursorPosition(y,x)
return tonumber(h), tonumber(w)
end
function term.clear()
io.write("\x1b[2J")

View File

@ -0,0 +1,42 @@
local shell = require("shell")
local data = require("data")
local args, parms = shell.parse(...)
if parms.h or parms.help then
io.stderr:write("See: man base64" .. "\n")
os.exit(true)
end
local encodingfun = nil
local encode
if parms.d or parms.decode then
encodingfun = data.decode64
encode = false
else
encodingfun = data.encode64
encode = true
end
if #args == 0 then
repeat
local read = io.read(encode and 3 or 4)
if read then
io.write(encodingfun(read))
end
until not read
else
for i = 1, #args do
local file, reason = io.open(shell.resolve(args[i]))
if not file then
io.stderr:write(tostring(reason) .. "\n")
os.exit(false)
end
repeat
local line = file:read(encode and 3 or 4)
if line then
io.write(encodingfun(line))
end
until not line
file:close()
end
end

View File

@ -0,0 +1,25 @@
local shell = require("shell")
local data = require("data")
local args = shell.parse(...)
if #args == 0 then
local read = ""
repeat
local current = io.read("*a")
read = read .. current
until current ~= ""
io.write(data.deflate(read))
else
local read = ""
local file, reason = io.open(shell.resolve(args[1]))
if not file then
io.stderr:write(tostring(reason) .. "\n")
os.exit(false)
end
repeat
local current = file:read("*a")
read = read .. current
until current ~= ""
file:close()
io.write(data.deflate(read))
end

View File

@ -0,0 +1,244 @@
--[[
-- A program that allows user to perform all crypto operations provided by Tier II / Tier III data cards
-- Author: makkarpov
--]]
local shell = require("shell")
local data = require("data")
local term = require("term")
local filesystem = require("filesystem")
local serialization = require("serialization")
local args, options = shell.parse(...)
local function writeFile(path, data)
if filesystem.exists(path) then
io.stderr:write("gpg: failed to write file: " .. path .. "\n")
io.stderr:write("gpg: error was: file already exists\n")
return false
end
if type(data) == "table" then
data = serialization.serialize(data)
end
local h, err = io.open(path, "wb")
if not h then
io.stderr:write("gpg: failed to write file: " .. path .. "\n")
io.stderr:write("gpg: error was: " .. err .. "\n")
return false
end
h:write(data)
h:close()
return true
end
local function readFile(path, deserialize)
local h = io.open(path, "rb")
local r = h:read("*a")
h:close()
if deserialize then
r = serialization.unserialize(r)
end
return r
end
local function parseKey(path, isPublic)
local d = readFile(path, true)
local k, err = data.deserializeKey(d.d, d.t)
if not k then
io.stderr:write("gpg: failed to parse key: " .. err .. "\n")
return nil
end
if k.isPublic() ~= isPublic then
io.stderr:write("gpg: wrong key type\n")
return nil
end
return k
end
local function deriveName(base, encrypt)
if encrypt then
return base .. ".gpg"
else
local d = base:gsub(".gpg", "")
if d == base then
d = d .. ".dec"
io.write("gpg: decrypting to " .. d .. "\n")
end
return d
end
end
local function ensureMethods(...)
if not require("component").isAvailable("data") then
io.stderr:write("gpg: you must have data card in order to run this program\n")
error("data card is absent")
end
local names = table.pack(...)
for i = 1, names.n do
if names[i] and not data[names[i]] then
io.stderr:write("gpg: method " .. names[i] .. " required on data card to run this program\n")
error("data card tier insufficient")
end
end
end
if options['g'] and (#args == 2) then
ensureMethods("generateKeyPair")
local pub, priv = data.generateKeyPair(384)
priv = { t = priv.keyType(), d = priv.serialize() }
pub = { t = pub.keyType(), d = pub.serialize() }
if not writeFile(args[1], priv) then
io.stderr:write("gpg: failed to write private key, aborting\n")
return false
end
if not writeFile(args[2], pub) then
io.stderr:write("gpg: failed to write public key, aborting\n")
return false
end
return true
end
if options['c'] and (options['e'] or options['d']) and (#args == 1) then
ensureMethods("md5", "sha256", "encrypt", "decrypt", "random")
if options['d'] and options['e'] then
io.stderr:write("gpg: please specify either -d or -e\n")
return false
end
io.write("gpg: enter password: ")
local aesKey = data.md5(term.read(nil, nil, nil, "*"))
local checkValue = data.sha256(aesKey)
if options['e'] then
local iv = data.random(16)
local d = data.encrypt(readFile(args[1]), aesKey, iv)
return writeFile(deriveName(args[1], true), {
t = "pwd",
kdf = "md5",
iv = iv,
cv = checkValue,
d = d
})
else
local d = readFile(args[1], true)
if d.t ~= "pwd" then
io.stderr:write("gpg: file is not encrypted with a password\n")
return false
end
if checkValue ~= d.cv then
io.stderr:write("gpg: password incorrect\n")
return false
end
return writeFile(deriveName(args[1], false), data.decrypt(d.d, aesKey, d.iv))
end
end
if (options['d'] or options['e']) and (#args == 2) then
ensureMethods("md5", "sha256", "encrypt", "decrypt", "random", "generateKeyPair", "deserializeKey", "ecdh")
if options['d'] and options['e'] then
io.stderr:write("gpg: please specify either -d or -e\n")
return false
end
if options['e'] then
local userPub = parseKey(args[1], true)
local tmpPub, tmpPriv = data.generateKeyPair(384)
local aesKey = data.md5(data.ecdh(tmpPriv, userPub))
local checkValue = data.sha256(aesKey)
local iv = data.random(16)
local d = data.encrypt(readFile(args[2]), aesKey, iv)
return writeFile(deriveName(args[2], true), {
t = "ecdh",
kdf = "md5",
iv = iv,
cv = checkValue,
k = {
t = tmpPub.keyType(),
d = tmpPub.serialize()
},
d = d
})
else
local userPriv = parseKey(args[1], false)
local d = readFile(args[2], true)
if d.t ~= "ecdh" then
io.stderr:write("gpg: file is not encrypted with a key\n")
return false
end
local tmpPub = data.deserializeKey(d.k.d, d.k.t)
local aesKey = data.md5(data.ecdh(userPriv, tmpPub))
if d.cv ~= data.sha256(aesKey) then
io.stderr:write("gpg: invalid key\n")
return false
end
return writeFile(deriveName(args[2], false), data.decrypt(d.d, aesKey, d.iv))
end
end
if (options['s'] or options['v']) and (#args == 2) then
ensureMethods("deserializeKey", "ecdsa")
if options['s'] and options['v'] then
io.stderr:write("gpg: please specify either -s or -v\n")
return false
end
if options['s'] then
local userPriv = parseKey(args[1], false)
local sign = data.ecdsa(readFile(args[2]), userPriv)
return writeFile(args[2] .. ".sig", {
t = "ecdsa",
s = sign
})
else
local userPub = parseKey(args[1], true)
local sign = readFile(args[2] .. ".sig", true)
if sign.t ~= "ecdsa" then
io.stderr:write("gpg: unsupported signature type\n")
return false
end
if not data.ecdsa(readFile(args[2]), userPub, sign.s) then
io.stderr:write("gpg: signature verification failed\n")
return false
end
io.write("gpg: signature is valid\n")
return true
end
end
io.write("Usages:\n")
io.write("gpg -ce <file> -- encrypt file with password\n")
io.write("gpg -cd <file> -- decrypt file with password\n")
io.write("gpg -e <key> <file> -- encrypt file\n")
io.write("gpg -d <key> <file> -- decrypt file\n")
io.write("gpg -g <private key file> <public key file> -- generate keypair\n")
io.write("gpg -s <key> <file> -- sign file\n")
io.write("gpg -v <key> <file> -- verify file\n")
return false

View File

@ -0,0 +1,25 @@
local shell = require("shell")
local data = require("data")
local args = shell.parse(...)
if #args == 0 then
local read = ""
repeat
local current = io.read("*a")
read = read .. current
until current ~= ""
io.write(data.inflate(read))
else
local read = ""
local file, reason = io.open(shell.resolve(args[1]))
if not file then
io.stderr:write(tostring(reason) .. "\n")
os.exit(false)
end
repeat
local current = file:read("*a")
read = read .. current
until current ~= ""
file:close()
io.write(data.inflate(read))
end

View File

@ -0,0 +1,27 @@
local shell = require("shell")
local data = require("data")
local args = shell.parse(...)
if #args == 0 then
local read = ""
repeat
local current = io.read("*a")
read = read .. current
until current ~= ""
io.write(data.toHex(data.md5(read)))
else
for i = 1, #args do
local read = ""
local file, reason = io.open(args[i])
if not file then
io.stderr:write(tostring(reason) .. "\n")
os.exit(false)
end
repeat
local current = file:read("*a")
read = read .. current
until current ~= ""
file:close()
io.write(data.toHex(data.md5(read)) .. "\t".. args[i] .. "\n")
end
end

View File

@ -81,17 +81,25 @@ ocBackend = {
print(" Upgrade all packages that are out-of-date on the")
print(" local system. Only package versions are used to find outdated packages;")
print(" replacements are not checked here. This is a ?remove-then-add? process.")
print(" -f, --force")
print(" Force operation, in case of upgrade it redownloads all packages")
print(" --root='/some/dir'")
print(" Set alternative root directory")
print(" -v")
print(" More output")
print(" -y")
print(" Don't ask any questions, answer automatically")
print(" -r, --reboot")
print(" reboot after operation")
return
end
if options.v then loglevel = 0 end
if options.f or options.force then
core.data.force = true
end
if options.S or options.sync then
for _, pack in ipairs(args) do
core.install(pack)
@ -114,6 +122,8 @@ ocBackend = {
if options.y then
ocBackend.prompt = function()return true end
end
core.reboot = optionsr or options.reboot
core.doWork()
end,
@ -208,7 +218,8 @@ ocBackend = {
if p:sub(1,1):upper() ~= "Y" then
error("User stopped")
end
end
end,
reboot = function()computer.shutdown(true) end
}
local mptFrontend
@ -249,7 +260,7 @@ mptFrontend = {
local toCheck = {}
for pack, data in pairs(base.installed) do
if data.frontend == mptFrontend.name then
toCheck[pack] = base.installed[pack].data.checksum
toCheck[pack] = base.installed[pack].data.checksum .. (core.data.force and "WAT" or "")
end
end
local updateResp = backend.getText(config.frontend.mpt.api.."update", toCheck)
@ -368,6 +379,8 @@ core = {
upgrade = false,
remove = false,
force = false,
--User requested packages
userInstall = {},
@ -603,7 +616,8 @@ end
core.log(1, "Main", "> Saving settings")
core.finalize()
if core.reboot then
backend.reboot()
end

View File

@ -0,0 +1,27 @@
local shell = require("shell")
local data = require("data")
local args = shell.parse(...)
if #args == 0 then
local read = ""
repeat
local current = io.read("*a")
read = read .. current
until current ~= ""
io.write(data.toHex(data.sha256(read)))
else
for i = 1, #args do
local read = ""
local file, reason = io.open(shell.resolve(args[i]))
if not file then
io.stderr:write(tostring(reason) .. "\n")
os.exit(false)
end
repeat
local current = file:read("*a")
read = read .. current
until current ~= ""
file:close()
io.write(data.toHex(data.sha256(read)) .. "\t".. args[i] .. "\n")
end
end

View File

@ -0,0 +1,26 @@
local component = require("component")
local data = {}
-------------------------------------------------------------------------------
-- Converts binary data into hexadecimal string.
function data.toHex(data)
return (data:gsub('.', function (c)
return string.format('%02X', string.byte(c))
end))
end
-- Converts hexadecimal string into binary data.
function data.fromHex(hex)
return (hex:gsub('..', function (cc)
return string.char(tonumber(cc, 16))
end))
end
-- Forward everything else to the primary data card.
setmetatable(data, { __index = function(_, key) return component.data[key] end })
-------------------------------------------------------------------------------
return data

View File

@ -1 +1 @@
{cacheDir="/var/lib/mpt/cache/",database="/var/lib/mpt/base.db",frontend={mpt={api="http://mpt.magik6k.net/api/"}}}
{database="/var/lib/mpt/base.db",cacheDir="/var/lib/mpt/cache/",frontend={mpt={api="http://mpt.magik6k.net/api/"}}}

View File

@ -1 +1 @@
{installed={["plan9k-drivers"]={frontend="MPT",data={name="plan9k-drivers",repo="plan9k",checksum="-2327b14292d5c08f547d24e9b5122349",files={"/lib/modules/base/17_tape.lua","/lib/modules/base/17_eeprom.lua","/lib/modules/base/17_nfc.lua","/lib/modules/base/17_chatbox.lua"},dependencies={}},deps={}},["plan9k-shell"]={frontend="MPT",data={name="plan9k-shell",repo="plan9k",checksum="-4ebb18f6dedde575d4d61460494b3bbb",files={"/bin/sh.lua"},dependencies={}},deps={}},["plan9k-corelibs"]={frontend="MPT",data={name="plan9k-corelibs",repo="plan9k",checksum="1d01d437b10e8561a39cb9f108cc3d47",files={"/lib/serialization.lua","/lib/term.lua","/lib/text.lua","/lib/shell.lua","/lib/event.lua"},dependencies={}},deps={}},mpt={frontend="MPT",data={name="mpt",repo="mpt",checksum="f9d7744571e5c46c658f405043c656",files={"/usr/bin/mpt.lua"},dependencies={}},deps={}},["plan9k-fsutil"]={frontend="MPT",data={name="plan9k-fsutil",repo="plan9k",checksum="aded7c8083efcdcfe43908183370687",files={"/bin/cat.lua","/bin/ln.lua","/bin/ls.lua","/bin/mv.lua","/bin/rm.lua","/bin/tee.lua","/bin/df.lua","/bin/dd.lua","/bin/cp.lua","/bin/touch.lua","/bin/mount.lua","/bin/mount.cow.lua","/bin/mkdir.lua","/bin/pwd.lua"},dependencies={"plan9k-corelibs"}},deps={"plan9k-corelibs"}},["plan9k-network"]={frontend="MPT",data={name="plan9k-network",repo="plan9k",checksum="-29d10c88b7ed4116d5b4eacd019d5ad9",files={"/lib/internet.lua","/bin/pastebin.lua","/bin/wget.lua","/lib/modules/base/17_network.lua","/lib/modules/base/19_libnetwork.lua","/bin/arp.lua","/bin/ifconfig.lua","/bin/ping.lua","/bin/route.lua","/lib/modules/network/loopback.lua","/lib/modules/network/modem.lua","/usr/bin/nc.lua","/lib/modules/network/tunnel.lua"},dependencies={}},deps={}},pipes={frontend="MPT",data={name="pipes",repo="plan9k",checksum="6d088970fd4fb29b78279eef4d417646",files={"/boot/kernel/pipes","/lib/modules/base/05_vfs.lua","/lib/modules/base/20_threading.lua","/lib/modules/base/19_manageg.lua","/lib/modules/base/25_init.lua","/lib/modules/base/15_userspace.lua","/usr/man/pipes","/lib/modules/base/16_buffer.lua","/lib/modules/base/17_io.lua","/lib/modules/base/16_require.lua","/lib/modules/base/18_syscall.lua","/lib/modules/base/21_threadUtil.lua","/lib/modules/base/21_timer.lua","/lib/modules/base/16_component.lua","/lib/modules/base/15_keventd.lua","/lib/modules/base/10_procfs.lua","/lib/modules/base/01_util.lua","/lib/modules/base/10_devfs.lua","/lib/modules/base/18_pty.lua","/lib/modules/base/17_keyboard.lua","/lib/modules/base/06_cowfs.lua","/lib/modules/base/09_rootfs.lua","/lib/modules/base/01_gc.lua"},dependencies={"openloader-init"}},deps={"openloader-init"}},["plan9k-edit"]={frontend="MPT",data={name="plan9k-edit",repo="plan9k",checksum="fed5f4ee1212297b07247afa1cfe3a2",files={"/bin/edit.lua"},dependencies={}},deps={}},["plan9k-core"]={frontend="MPT",data={name="plan9k-core",repo="plan9k",checksum="-4f5e4f44875482035444a2b61e96243d",files={"/bin/init.lua","/bin/getty.lua","/bin/readkey.lua","/lib/rc.lua","/bin/rc.lua"},dependencies={"pipes","plan9k-coreutil","plan9k-shell"}},deps={"pipes","plan9k-coreutil","plan9k-shell"}},plan9k={frontend="MPT",data={name="plan9k",repo="plan9k",checksum="-c16ccdf21a1ff13be8f6258d1a17d89",files={},dependencies={"plan9k-core","plan9k-network","plan9k-drivers","plan9k-edit"}},deps={"plan9k-core","plan9k-network","plan9k-drivers","plan9k-edit"}},["plan9k-installer"]={frontend="MPT",data={name="plan9k-installer",repo="plan9k",checksum="52c8f82357c966ce3e19c97bf3942012",files={"/bin/install.lua"},dependencies={"plan9k","mpt"}},deps={"plan9k","mpt"}},["openloader-init"]={frontend="MPT",data={name="openloader-init",repo="disks",checksum="-45e6d7b1e41468c1d335952ee3b89e13",files={"/init.lua"},dependencies={}},deps={}},["plan9k-coreutil"]={frontend="MPT",data={name="plan9k-coreutil",repo="plan9k",checksum="-50d3cee571b07b6cb05f6fb01989997c",files={"/bin/echo.lua","/bin/wc.lua","/bin/ps.lua","/bin/lua.lua","/bin/kill.lua","/bin/reboot.lua","/bin/sleep.lua","/bin/clear.lua","/bin/components.lua","/bin/hostname.lua","/bin/dmesg.lua","/bin/shutdown.lua","/bin/label.lua","/bin/uptime.lua","/bin/resolution.lua"},dependencies={"plan9k-corelibs","plan9k-fsutil"}},deps={"plan9k-corelibs","plan9k-fsutil"}}}}
{installed={["plan9k-shell"]={deps={},frontend="MPT",data={checksum="517b9e0693e734a4ab516f12a6798f14",files={"/bin/sh.lua"},name="plan9k-shell",repo="plan9k",dependencies={}}},plan9k={deps={"plan9k-core","plan9k-network","plan9k-drivers","plan9k-edit","plan9k-data"},frontend="MPT",data={checksum="-2d8f4b84ea60b0c9d5846f57e9f1691c",files={},name="plan9k",repo="plan9k",dependencies={"plan9k-core","plan9k-network","plan9k-drivers","plan9k-edit","plan9k-data"}}},["plan9k-fsutil"]={deps={"plan9k-corelibs"},frontend="MPT",data={checksum="6a974a71f62315e6e2294eae132d1751",files={"/bin/cat.lua","/bin/ln.lua","/bin/ls.lua","/bin/mv.lua","/bin/rm.lua","/bin/tee.lua","/bin/df.lua","/bin/dd.lua","/bin/cp.lua","/bin/touch.lua","/bin/mount.lua","/bin/mount.cow.lua","/bin/mkdir.lua","/bin/pwd.lua","/bin/more.lua"},name="plan9k-fsutil",repo="plan9k",dependencies={"plan9k-corelibs"}}},["plan9k-edit"]={deps={},frontend="MPT",data={checksum="34b1046ac9b7a87a1cdd74f8c03f27ea",files={"/bin/edit.lua"},name="plan9k-edit",repo="plan9k",dependencies={}}},["plan9k-core"]={deps={"pipes","plan9k-coreutil","plan9k-shell"},frontend="MPT",data={checksum="-6f77a020200f96eefd1559dcd8af14a5",files={"/bin/init.lua","/bin/getty.lua","/bin/readkey.lua","/lib/rc.lua","/bin/rc.lua"},name="plan9k-core",repo="plan9k",dependencies={"pipes","plan9k-coreutil","plan9k-shell"}}},["plan9k-installer"]={deps={"plan9k","mpt"},frontend="MPT",data={checksum="52c8f82357c966ce3e19c97bf3942012",files={"/bin/install.lua"},name="plan9k-installer",repo="plan9k",dependencies={"plan9k","mpt"}}},["plan9k-drivers"]={deps={},frontend="MPT",data={checksum="-35f098652460458c13f83499b4633e2d",files={"/lib/modules/base/17_tape.lua","/lib/modules/base/17_eeprom.lua","/lib/modules/base/17_nfc.lua","/lib/modules/base/17_chatbox.lua","/lib/modules/base/17_data.lua","/lib/modules/base/17_drive.lua"},name="plan9k-drivers",repo="plan9k",dependencies={}}},["plan9k-coreutil"]={deps={"plan9k-corelibs","plan9k-fsutil"},frontend="MPT",data={checksum="5fa7e70e3aba17fef97ed65489efb0ca",files={"/bin/echo.lua","/bin/wc.lua","/bin/ps.lua","/bin/lua.lua","/bin/kill.lua","/bin/reboot.lua","/bin/sleep.lua","/bin/clear.lua","/bin/components.lua","/bin/hostname.lua","/bin/dmesg.lua","/bin/shutdown.lua","/bin/label.lua","/bin/uptime.lua","/bin/resolution.lua"},name="plan9k-coreutil",repo="plan9k",dependencies={"plan9k-corelibs","plan9k-fsutil"}}},["openloader-init"]={deps={},frontend="MPT",data={checksum="-45e6d7b1e41468c1d335952ee3b89e13",files={"/init.lua"},name="openloader-init",repo="disks",dependencies={}}},mpt={deps={},frontend="MPT",data={checksum="-3435ded79cf9de20e7185f403eee4a28",files={"/usr/bin/mpt.lua"},name="mpt",repo="mpt",dependencies={}}},pipes={deps={"openloader-init"},frontend="MPT",data={checksum="123b56992859cf05cd03af825437d734",files={"/boot/kernel/pipes","/lib/modules/base/05_vfs.lua","/lib/modules/base/20_threading.lua","/lib/modules/base/19_manageg.lua","/lib/modules/base/25_init.lua","/lib/modules/base/15_userspace.lua","/usr/man/pipes","/lib/modules/base/16_buffer.lua","/lib/modules/base/17_io.lua","/lib/modules/base/16_require.lua","/lib/modules/base/18_syscall.lua","/lib/modules/base/21_threadUtil.lua","/lib/modules/base/21_timer.lua","/lib/modules/base/16_component.lua","/lib/modules/base/15_keventd.lua","/lib/modules/base/10_procfs.lua","/lib/modules/base/01_util.lua","/lib/modules/base/10_devfs.lua","/lib/modules/base/18_pty.lua","/lib/modules/base/17_keyboard.lua","/lib/modules/base/06_cowfs.lua","/lib/modules/base/09_rootfs.lua","/lib/modules/base/01_gc.lua"},name="pipes",repo="plan9k",dependencies={"openloader-init"}}},["plan9k-corelibs"]={deps={},frontend="MPT",data={checksum="1cb7fa12e1a1a35fc168409b60cfe552",files={"/lib/serialization.lua","/lib/term.lua","/lib/text.lua","/lib/shell.lua","/lib/event.lua"},name="plan9k-corelibs",repo="plan9k",dependencies={}}},["plan9k-data"]={deps={},frontend="MPT",data={checksum="480a898a741b2bf424f9e0e86e5072ba",files={"/usr/bin/base64.lua","/usr/lib/data.lua","/usr/bin/deflate.lua","/usr/bin/inflate.lua","/usr/bin/md5sum.lua","/usr/bin/sha256sum.lua","/usr/bin/gpg.lua"},name="plan9k-data",repo="plan9k",dependencies={}}},["plan9k-network"]={deps={},frontend="MPT",data={checksum="6e06e6cf5028583fe54047ba9e19abc6",files={"/lib/internet.lua","/bin/pastebin.lua","/bin/wget.lua","/lib/modules/base/17_network.lua","/lib/modules/base/19_libnetwork.lua","/bin/arp.lua","/bin/ifconfig.lua","/bin/ping.lua","/bin/route.lua","/lib/modules/network/loopback.lua","/lib/modules/network/modem.lua","/usr/bin/nc.lua","/lib/modules/network/tunnel.lua"},name="plan9k-network",repo="plan9k",dependencies={}}}}}

View File

@ -1320,6 +1320,23 @@ local libcomputer = {
beep = function(...)
libcomponent.invoke(computer.address(), "beep", ...)
end,
getArchitectures = function(...)
return spcall(computer.getArchitectures, ...)
end,
getArchitecture = function(...)
return spcall(computer.getArchitecture, ...)
end,
setArchitecture = function(...)
local result, reason = spcall(computer.setArchitecture, ...)
if not result then
if reason then
return result, reason
end
else
coroutine.yield(true) -- reboot
end
end
}
sandbox.computer = libcomputer

View File

@ -0,0 +1,8 @@
{
"parent": "block/cube_bottom_top",
"textures": {
"top": "opencomputers:blocks/switch_top",
"bottom": "opencomputers:blocks/generic_top",
"side": "opencomputers:blocks/switch_side"
}
}

View File

@ -0,0 +1,221 @@
{
"textures": {
"bottom": "opencomputers:blocks/transposer_top",
"top": "opencomputers:blocks/transposer_top",
"side": "opencomputers:blocks/transposer_side",
"particle": "opencomputers:blocks/generic_top"
},
"elements": [
{ "from": [ 0, 0, 0 ],
"to": [ 7, 7, 7 ],
"faces": {
"up": { "uv": [ 0, 0, 7, 7 ], "texture": "#top" },
"down": { "uv": [ 0, 9, 7, 16 ], "texture": "#bottom" },
"north": { "uv": [ 9, 9, 16, 16 ], "texture": "#side" },
"south": { "uv": [ 0, 9, 7, 16 ], "texture": "#side" },
"west": { "uv": [ 0, 9, 7, 16 ], "texture": "#side" },
"east": { "uv": [ 9, 9, 16, 16 ], "texture": "#side" }
}
},
{ "from": [ 0, 0, 9 ],
"to": [ 7, 7, 16 ],
"faces": {
"up": { "uv": [ 0, 9, 7, 16 ], "texture": "#top" },
"down": { "uv": [ 0, 0, 7, 7 ], "texture": "#bottom" },
"north": { "uv": [ 9, 9, 16, 16 ], "texture": "#side" },
"south": { "uv": [ 0, 9, 7, 16 ], "texture": "#side" },
"west": { "uv": [ 9, 9, 16, 16 ], "texture": "#side" },
"east": { "uv": [ 0, 9, 7, 16 ], "texture": "#side" }
}
},
{ "from": [ 0, 9, 0 ],
"to": [ 7, 16, 7 ],
"faces": {
"up": { "uv": [ 0, 0, 7, 7 ], "texture": "#top" },
"down": { "uv": [ 0, 9, 7, 16 ], "texture": "#bottom" },
"north": { "uv": [ 9, 0, 16, 7 ], "texture": "#side" },
"south": { "uv": [ 0, 0, 7, 7 ], "texture": "#side" },
"west": { "uv": [ 0, 0, 7, 7 ], "texture": "#side" },
"east": { "uv": [ 9, 0, 16, 7 ], "texture": "#side" }
}
},
{ "from": [ 0, 9, 9 ],
"to": [ 7, 16, 16 ],
"faces": {
"up": { "uv": [ 0, 9, 7, 16 ], "texture": "#top" },
"down": { "uv": [ 0, 0, 7, 7 ], "texture": "#bottom" },
"north": { "uv": [ 9, 0, 16, 7 ], "texture": "#side" },
"south": { "uv": [ 0, 0, 7, 7 ], "texture": "#side" },
"west": { "uv": [ 9, 0, 16, 7 ], "texture": "#side" },
"east": { "uv": [ 0, 0, 7, 7 ], "texture": "#side" }
}
},
{ "from": [ 9, 0, 0 ],
"to": [ 16, 7, 7 ],
"faces": {
"up": { "uv": [ 9, 0, 16, 7 ], "texture": "#top" },
"down": { "uv": [ 9, 9, 16, 16 ], "texture": "#bottom" },
"north": { "uv": [ 0, 9, 7, 16 ], "texture": "#side" },
"south": { "uv": [ 9, 9, 16, 16 ], "texture": "#side" },
"west": { "uv": [ 0, 9, 7, 16 ], "texture": "#side" },
"east": { "uv": [ 9, 9, 16, 16 ], "texture": "#side" }
}
},
{ "from": [ 9, 0, 9 ],
"to": [ 16, 7, 16 ],
"faces": {
"up": { "uv": [ 9, 9, 16, 16 ], "texture": "#top" },
"down": { "uv": [ 9, 0, 16, 7 ], "texture": "#bottom" },
"north": { "uv": [ 0, 9, 7, 16 ], "texture": "#side" },
"south": { "uv": [ 9, 9, 16, 16 ], "texture": "#side" },
"west": { "uv": [ 9, 9, 16, 16 ], "texture": "#side" },
"east": { "uv": [ 0, 9, 7, 16 ], "texture": "#side" }
}
},
{ "from": [ 9, 9, 0 ],
"to": [ 16, 16, 7 ],
"faces": {
"up": { "uv": [ 9, 0, 16, 7 ], "texture": "#top" },
"down": { "uv": [ 9, 9, 16, 16 ], "texture": "#bottom" },
"north": { "uv": [ 0, 0, 7, 7 ], "texture": "#side" },
"south": { "uv": [ 9, 0, 16, 7 ], "texture": "#side" },
"west": { "uv": [ 0, 0, 7, 7 ], "texture": "#side" },
"east": { "uv": [ 9, 0, 16, 7 ], "texture": "#side" }
}
},
{ "from": [ 9, 9, 9 ],
"to": [ 16, 16, 16 ],
"faces": {
"up": { "uv": [ 9, 9, 16, 16 ], "texture": "#top" },
"down": { "uv": [ 9, 0, 16, 7 ], "texture": "#bottom" },
"north": { "uv": [ 0, 0, 7, 7 ], "texture": "#side" },
"south": { "uv": [ 9, 0, 16, 7 ], "texture": "#side" },
"west": { "uv": [ 9, 0, 16, 7 ], "texture": "#side" },
"east": { "uv": [ 0, 0, 7, 7 ], "texture": "#side" }
}
},
{ "from": [ 0, 0, 7 ],
"to": [ 5, 5, 9 ],
"faces": {
"up": { "uv": [ 0, 7, 5, 9 ], "texture": "#top" },
"down": { "uv": [ 0, 7, 5, 9 ], "texture": "#bottom" },
"west": { "uv": [ 7, 11, 9, 16 ], "texture": "#side" },
"east": { "uv": [ 7, 11, 9, 16 ], "texture": "#side" }
}
},
{ "from": [ 0, 11, 7 ],
"to": [ 5, 16, 9 ],
"faces": {
"up": { "uv": [ 0, 7, 5, 9 ], "texture": "#top" },
"down": { "uv": [ 0, 7, 5, 9 ], "texture": "#bottom" },
"west": { "uv": [ 7, 0, 9, 5 ], "texture": "#side" },
"east": { "uv": [ 7, 0, 9, 5 ], "texture": "#side" }
}
},
{ "from": [ 11, 0, 7 ],
"to": [ 16, 5, 9 ],
"faces": {
"up": { "uv": [ 11, 7, 16, 9 ], "texture": "#top" },
"down": { "uv": [ 11, 7, 16, 9 ], "texture": "#bottom" },
"west": { "uv": [ 7, 11, 9, 16 ], "texture": "#side" },
"east": { "uv": [ 7, 11, 9, 16 ], "texture": "#side" }
}
},
{ "from": [ 11, 11, 7 ],
"to": [ 16, 16, 9 ],
"faces": {
"up": { "uv": [ 11, 7, 16, 9 ], "texture": "#top" },
"down": { "uv": [ 11, 7, 16, 9 ], "texture": "#bottom" },
"west": { "uv": [ 7, 0, 9, 5 ], "texture": "#side" },
"east": { "uv": [ 7, 0, 9, 5 ], "texture": "#side" }
}
},
{ "from": [ 0, 7, 0 ],
"to": [ 5, 9, 5 ],
"faces": {
"north": { "uv": [ 11, 7, 16, 9 ], "texture": "#side" },
"south": { "uv": [ 0, 7, 5, 9 ], "texture": "#side" },
"west": { "uv": [ 0, 7, 5, 9 ], "texture": "#side" },
"east": { "uv": [ 11, 7, 16, 9 ], "texture": "#side" }
}
},
{ "from": [ 0, 7, 11 ],
"to": [ 5, 9, 16 ],
"faces": {
"north": { "uv": [ 11, 7, 16, 9 ], "texture": "#side" },
"south": { "uv": [ 0, 7, 5, 9 ], "texture": "#side" },
"west": { "uv": [ 11, 7, 16, 9 ], "texture": "#side" },
"east": { "uv": [ 0, 7, 5, 9 ], "texture": "#side" }
}
},
{ "from": [ 11, 7, 0 ],
"to": [ 16, 9, 5 ],
"faces": {
"north": { "uv": [ 0, 7, 5, 9 ], "texture": "#side" },
"south": { "uv": [ 11, 7, 16, 9 ], "texture": "#side" },
"west": { "uv": [ 0, 7, 5, 9 ], "texture": "#side" },
"east": { "uv": [ 11, 7, 16, 9 ], "texture": "#side" }
}
},
{ "from": [ 11, 7, 11 ],
"to": [ 16, 9, 16 ],
"faces": {
"north": { "uv": [ 0, 7, 5, 9 ], "texture": "#side" },
"south": { "uv": [ 11, 7, 16, 9 ], "texture": "#side" },
"west": { "uv": [ 11, 7, 16, 9 ], "texture": "#side" },
"east": { "uv": [ 0, 7, 5, 9 ], "texture": "#side" }
}
},
{ "from": [ 7, 0, 0 ],
"to": [ 9, 5, 5 ],
"faces": {
"up": { "uv": [ 7, 0, 9, 5 ], "texture": "#top" },
"down": { "uv": [ 7, 11, 9, 16 ], "texture": "#bottom" },
"north": { "uv": [ 7, 11, 9, 16 ], "texture": "#side" },
"south": { "uv": [ 7, 11, 9, 16 ], "texture": "#side" }
}
},
{ "from": [ 7, 0, 11 ],
"to": [ 9, 5, 16 ],
"faces": {
"up": { "uv": [ 7, 11, 9, 16 ], "texture": "#top" },
"down": { "uv": [ 7, 0, 9, 5 ], "texture": "#bottom" },
"north": { "uv": [ 7, 11, 9, 16 ], "texture": "#side" },
"south": { "uv": [ 7, 11, 9, 16 ], "texture": "#side" }
}
},
{ "from": [ 7, 11, 0 ],
"to": [ 9, 16, 5 ],
"faces": {
"up": { "uv": [ 7, 0, 9, 5 ], "texture": "#top" },
"down": { "uv": [ 7, 11, 9, 16 ], "texture": "#bottom" },
"north": { "uv": [ 7, 0, 9, 5 ], "texture": "#side" },
"south": { "uv": [ 7, 0, 9, 5 ], "texture": "#side" }
}
},
{ "from": [ 7, 11, 11 ],
"to": [ 9, 16, 16 ],
"faces": {
"up": { "uv": [ 7, 11, 9, 16 ], "texture": "#top" },
"down": { "uv": [ 7, 0, 9, 5 ], "texture": "#bottom" },
"north": { "uv": [ 7, 0, 9, 5 ], "texture": "#side" },
"south": { "uv": [ 7, 0, 9, 5 ], "texture": "#side" }
}
},
{ "from": [ 1, 1, 1 ],
"to": [ 15, 15, 15 ],
"faces": {
"up": { "uv": [ 1, 1, 15, 15 ], "texture": "#top" },
"down": { "uv": [ 1, 1, 15, 15 ], "texture": "#bottom" },
"north": { "uv": [ 1, 1, 15, 15 ], "texture": "#side" },
"south": { "uv": [ 1, 1, 15, 15 ], "texture": "#side" },
"west": { "uv": [ 1, 1, 15, 15 ], "texture": "#side" },
"east": { "uv": [ 1, 1, 15, 15 ], "texture": "#side" }
}
}
]
}

View File

@ -0,0 +1,10 @@
{
"parent": "opencomputers:block/relay",
"display": {
"thirdperson": {
"rotation": [ 10, -45, 170 ],
"translation": [ 0, 1.5, -2.75 ],
"scale": [ 0.375, 0.375, 0.375 ]
}
}
}

View File

@ -0,0 +1,10 @@
{
"parent": "opencomputers:block/transposer",
"display": {
"thirdperson": {
"rotation": [ 10, -45, 170 ],
"translation": [ 0, 1.5, -2.75 ],
"scale": [ 0.375, 0.375, 0.375 ]
}
}
}

View File

@ -504,11 +504,6 @@ interweb {
[string, string, string]]
}
accessPoint {
input: [[ingotIron, "oc:wlanCard", ingotIron]
["oc:cable", "oc:lanCard", "oc:cable"]
[ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
}
adapter {
input: [[ingotIron, "oc:cable", ingotIron]
["oc:cable", "oc:circuitChip1", "oc:cable"]
@ -607,7 +602,7 @@ powerDistributor {
serverRack {
input: [["oc:circuitChip2", "oc:wlanCard", "oc:circuitChip2"]
[fenceIron, chest, fenceIron]
["oc:switch", "oc:materialCircuitBoardPrinted", "oc:powerDistributor"]]
["oc:relay", "oc:materialCircuitBoardPrinted", "oc:powerDistributor"]]
}
raid {
input: [[nuggetIron, "oc:cpu3", nuggetIron]
@ -619,7 +614,7 @@ redstone {
[blockRedstone, "oc:redstoneCard1", blockRedstone]
[ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
}
switch {
relay {
input: [[ingotIron, "oc:cable", ingotIron]
["oc:cable", "oc:lanCard", "oc:cable"]
[ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
@ -639,6 +634,12 @@ screen3 {
[yellowDust, "oc:circuitChip3", glass]
[obsidian, yellowDust, obsidian]]
}
transposer {
input: [[ingotIron, "oc:inventoryControllerUpgrade", ingotIron]
[hopper, bucket, hopper]
[ingotIron, "oc:tankControllerUpgrade", ingotIron]]
output: 4
}
waypoint {
input: [[ingotIron, "oc:circuitChip1", ingotIron]
["oc:materialTransistor", "oc:materialInterweb", "oc:materialTransistor"],

View File

@ -318,7 +318,7 @@ powerDistributor {
serverRack {
input: [[craftingToolScrewdriver, "oc:wlanCard", craftingToolWrench]
["ic2.reactorVentDiamond", chest, "ic2.reactorVentDiamond"]
["oc:switch", "oc:materialCircuitBoardPrinted","oc:powerDistributor"]]
["oc:relay", "oc:materialCircuitBoardPrinted","oc:powerDistributor"]]
}
redstone {
# 32731 = Activity Detector
@ -326,7 +326,7 @@ redstone {
[{item="gt.metaitem.01", subID=32731}, {block="gt.blockcasings", subID=2}, "oc:redstoneCard1"]
["oc:circuitChip2", "oc:materialCircuitBoardPrinted", "oc:circuitChip2"]]
}
switch {
relay {
input: [["", "oc:lanCard", ""]
["oc:cable", {block="gt.blockcasings", subID=2}, "oc:cable"]
["oc:materialCircuitBoardPrinted", craftingToolWrench, "oc:materialCircuitBoardPrinted"]]

View File

@ -363,14 +363,14 @@ powerDistributor {
serverRack {
input: [["oc:circuitChip3", "oc:wlanCard", "oc:circuitChip3"]
[fenceIron, chest, fenceIron]
["oc:switch", "oc:materialCircuitBoardPrinted","oc:powerDistributor"]]
["oc:relay", "oc:materialCircuitBoardPrinted","oc:powerDistributor"]]
}
redstone {
input: [[ingotIron, "oc:circuitChip3", ingotIron]
[blockRedstone, "oc:redstoneCard1", blockRedstone]
[ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
}
switch {
relay {
input: [[ingotIron, "oc:cable", ingotIron]
["oc:cable", "oc:lanCard", "oc:cable"]
[ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

View File

@ -25,12 +25,14 @@ object Constants {
final val Keyboard = "keyboard"
final val Microcontroller = "microcontroller"
final val MotionSensor = "motionSensor"
final val NetSplitter = "netSplitter"
final val PowerConverter = "powerConverter"
final val PowerDistributor = "powerDistributor"
final val Print = "print"
final val Printer = "printer"
final val Raid = "raid"
final val Redstone = "redstone"
final val Relay = "relay"
final val Robot = "robot"
final val RobotAfterimage = "robotAfterimage"
final val ScreenTier1 = "screen1"
@ -38,7 +40,7 @@ object Constants {
final val ScreenTier3 = "screen3"
final val ServerRack = "serverRack"
final val Switch = "switch"
final val NetSplitter = "netSplitter"
final val Transposer = "transposer"
final val Waypoint = "waypoint"
def Case(tier: Int) = ItemUtils.caseNameWithTierSuffix("case", tier)

View File

@ -201,6 +201,7 @@ class Settings(val config: Config) {
val dataCardComplex = config.getDouble("power.cost.dataCardComplex") max 0
val dataCardComplexByte = config.getDouble("power.cost.dataCardComplexByte") max 0
val dataCardAsymmetric = config.getDouble("power.cost.dataCardAsymmetric") max 0
val transposerCost = config.getDouble("power.cost.transposer") max 0
// power.rate
val accessPointRate = config.getDouble("power.rate.accessPoint") max 0
@ -336,6 +337,7 @@ class Settings(val config: Config) {
val dataCardHardLimit = config.getInt("misc.dataCardHardLimit") max 0
val dataCardTimeout = config.getDouble("misc.dataCardTimeout") max 0
val serverRackSwitchTier = (config.getInt("misc.serverRackSwitchTier") - 1) max Tier.None min Tier.Three
val redstoneDelay = config.getDouble("misc.redstoneDelay") max 0
// ----------------------------------------------------------------------- //
// printer

View File

@ -36,12 +36,14 @@ object GuiHandler extends CommonGuiHandler {
new gui.DiskDrive(player.inventory, t)
case t: tileentity.Printer if id == GuiType.Printer.id =>
new gui.Printer(player.inventory, t)
case t: tileentity.Raid if id == GuiType.Raid.id =>
new gui.Raid(player.inventory, t)
case t: tileentity.RobotProxy if id == GuiType.Robot.id =>
new gui.Robot(player.inventory, t.robot)
case t: tileentity.ServerRack if id == GuiType.Rack.id =>
new gui.ServerRack(player.inventory, t)
case t: tileentity.Raid if id == GuiType.Raid.id =>
new gui.Raid(player.inventory, t)
case t: tileentity.Relay if id == GuiType.Relay.id =>
new gui.Relay(player.inventory, t)
case t: tileentity.RobotProxy if id == GuiType.Robot.id =>
new gui.Robot(player.inventory, t.robot)
case t: tileentity.Screen if id == GuiType.Screen.id =>
new gui.Screen(t.origin.buffer, t.tier > 0, () => t.origin.hasKeyboard, () => t.origin.buffer.isRenderingEnabled)
case t: tileentity.Switch if id == GuiType.Switch.id =>

View File

@ -81,6 +81,7 @@ object PacketHandler extends CommonPacketHandler {
case PacketType.ServerPresence => onServerPresence(p)
case PacketType.Sound => onSound(p)
case PacketType.SoundPattern => onSoundPattern(p)
case PacketType.TransposerActivity => onTransposerActivity(p)
case PacketType.WaypointLabel => onWaypointLabel(p)
case _ => // Invalid packet.
}
@ -260,6 +261,15 @@ object PacketHandler extends CommonPacketHandler {
}
}
def onNetSplitterState(p: PacketParser) =
p.readTileEntity[NetSplitter]() match {
case Some(t) =>
t.isInverted = p.readBoolean()
t.openSides = t.uncompressSides(p.readByte())
t.world.markBlockForUpdate(t.getPos)
case _ => // Invalid packet.
}
def onParticleEffect(p: PacketParser) = {
val dimension = p.readInt()
world(p.player, dimension) match {
@ -420,7 +430,7 @@ object PacketHandler extends CommonPacketHandler {
}
def onSwitchActivity(p: PacketParser) =
p.readTileEntity[Switch]() match {
p.readTileEntity[traits.SwitchLike]() match {
case Some(t) => t.lastMessage = System.currentTimeMillis()
case _ => // Invalid packet.
}
@ -589,15 +599,6 @@ object PacketHandler extends CommonPacketHandler {
buffer.rawSetForeground(col, row, color)
}
def onNetSplitterState(p: PacketParser) =
p.readTileEntity[NetSplitter]() match {
case Some(t) =>
t.isInverted = p.readBoolean()
t.openSides = t.uncompressSides(p.readByte())
t.world.markBlockForUpdate(t.getPos)
case _ => // Invalid packet.
}
def onScreenTouchMode(p: PacketParser) =
p.readTileEntity[Screen]() match {
case Some(t) => t.invertTouchMode = p.readBoolean()
@ -638,6 +639,12 @@ object PacketHandler extends CommonPacketHandler {
}
}
def onTransposerActivity(p: PacketParser) =
p.readTileEntity[Transposer]() match {
case Some(transposer) => transposer.lastOperation = System.currentTimeMillis()
case _ => // Invalid packet.
}
def onWaypointLabel(p: PacketParser) =
p.readTileEntity[Waypoint]() match {
case Some(waypoint) => waypoint.label = p.readUTF()

View File

@ -63,15 +63,17 @@ private[oc] class Proxy extends CommonProxy {
else
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Hologram], HologramRendererFallback)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Microcontroller], MicrocontrollerRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.NetSplitter], NetSplitterRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.PowerDistributor], PowerDistributorRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Printer], PrinterRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Raid], RaidRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.ServerRack], ServerRackRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Switch], SwitchRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.AccessPoint], SwitchRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Relay], SwitchRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.RobotProxy], RobotRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Screen], ScreenRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.NetSplitter], NetSplitterRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Transposer], TransposerRenderer)
ClientRegistry.registerKeyBinding(KeyBindings.materialCosts)
ClientRegistry.registerKeyBinding(KeyBindings.clipboardPaste)

View File

@ -59,6 +59,7 @@ object Textures {
val RobotSelection = L("robot_selection")
val Server = L("server")
val Slot = L("slot")
val UpgradeTab = L("upgrade_tab")
val Waypoint = L("waypoint")
override protected def basePath = "textures/gui/%s.png"
@ -142,6 +143,7 @@ object Textures {
val RaidFrontError = L("overlay/raid_front_error")
val ScreenUpIndicator = L("overlay/screen_up_indicator")
val SwitchSideOn = L("overlay/switch_side_on")
val TransposerOn = L("overlay/transposer_on")
val Cable = L("cable")
val CableCap = L("cableCap")

View File

@ -0,0 +1,123 @@
package li.cil.oc.client.gui
import java.lang.Iterable
import java.text.DecimalFormat
import java.util
import codechicken.nei.VisiblityData
import codechicken.nei.api.INEIGuiHandler
import codechicken.nei.api.TaggedInventoryArea
import li.cil.oc.Localization
import li.cil.oc.client.Textures
import li.cil.oc.common.container
import li.cil.oc.common.tileentity
import li.cil.oc.integration.Mods
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.inventory.GuiContainer
import net.minecraft.client.renderer.Tessellator
import net.minecraft.entity.player.InventoryPlayer
import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.Optional
import org.lwjgl.opengl.GL11
import org.lwjgl.util.Rectangle
@Optional.Interface(iface = "codechicken.nei.api.INEIGuiHandler", modid = Mods.IDs.NotEnoughItems)
class Relay(playerInventory: InventoryPlayer, val relay: tileentity.Relay) extends DynamicGuiContainer(new container.Relay(playerInventory, relay)) with INEIGuiHandler {
private val format = new DecimalFormat("#.##hz")
private val tabPosition = new Rectangle(xSize, 10, 23, 26)
override protected def drawSecondaryBackgroundLayer(): Unit = {
super.drawSecondaryBackgroundLayer()
// Tab background.
GL11.glColor4f(1, 1, 1, 1)
Minecraft.getMinecraft.getTextureManager.bindTexture(Textures.GUI.UpgradeTab)
val x = windowX + tabPosition.getX
val y = windowY + tabPosition.getY
val w = tabPosition.getWidth
val h = tabPosition.getHeight
val t = Tessellator.getInstance
val r = t.getWorldRenderer
r.startDrawingQuads()
r.addVertexWithUV(x, y + h, zLevel, 0, 1)
r.addVertexWithUV(x + w, y + h, zLevel, 1, 1)
r.addVertexWithUV(x + w, y, zLevel, 1, 0)
r.addVertexWithUV(x, y, zLevel, 0, 0)
t.draw()
}
override def mouseClicked(mouseX: Int, mouseY: Int, button: Int): Unit = {
// So MC doesn't throw away the item in the upgrade slot when we're trying to pick it up...
val originalWidth = xSize
try {
xSize += tabPosition.getWidth
super.mouseClicked(mouseX, mouseY, button)
}
finally {
xSize = originalWidth
}
}
override def mouseReleased(mouseX: Int, mouseY: Int, button: Int): Unit = {
// So MC doesn't throw away the item in the upgrade slot when we're trying to pick it up...
val originalWidth = xSize
try {
xSize += tabPosition.getWidth
super.mouseReleased(mouseX, mouseY, button)
}
finally {
xSize = originalWidth
}
}
override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
super.drawSecondaryForegroundLayer(mouseX, mouseY)
fontRendererObj.drawString(
Localization.localizeImmediately(relay.getName),
8, 6, 0x404040)
fontRendererObj.drawString(
Localization.Switch.TransferRate,
14, 20, 0x404040)
fontRendererObj.drawString(
Localization.Switch.PacketsPerCycle,
14, 39, 0x404040)
fontRendererObj.drawString(
Localization.Switch.QueueSize,
14, 58, 0x404040)
fontRendererObj.drawString(
format.format(20f / inventoryContainer.relayDelay),
108, 20, 0x404040)
fontRendererObj.drawString(
inventoryContainer.packetsPerCycleAvg + " / " + inventoryContainer.relayAmount,
108, 39, thresholdBasedColor(inventoryContainer.packetsPerCycleAvg, math.ceil(inventoryContainer.relayAmount / 2f).toInt, inventoryContainer.relayAmount))
fontRendererObj.drawString(
inventoryContainer.queueSize + " / " + inventoryContainer.maxQueueSize,
108, 58, thresholdBasedColor(inventoryContainer.queueSize, inventoryContainer.maxQueueSize / 2, inventoryContainer.maxQueueSize))
}
private def thresholdBasedColor(value: Int, yellow: Int, red: Int) = {
if (value < yellow) 0x009900
else if (value < red) 0x999900
else 0x990000
}
@Optional.Method(modid = Mods.IDs.NotEnoughItems)
override def modifyVisiblity(gui: GuiContainer, currentVisibility: VisiblityData): VisiblityData = null
@Optional.Method(modid = Mods.IDs.NotEnoughItems)
override def getItemSpawnSlots(gui: GuiContainer, stack: ItemStack): Iterable[Integer] = null
@Optional.Method(modid = Mods.IDs.NotEnoughItems)
override def getInventoryAreas(gui: GuiContainer): util.List[TaggedInventoryArea] = null
@Optional.Method(modid = Mods.IDs.NotEnoughItems)
override def handleDragNDrop(gui: GuiContainer, mouseX: Int, mouseY: Int, stack: ItemStack, button: Int): Boolean = false
@Optional.Method(modid = Mods.IDs.NotEnoughItems)
override def hideItemPanelSlot(gui: GuiContainer, x: Int, y: Int, w: Int, h: Int): Boolean = {
new Rectangle(x - windowX, y - windowY, w, h).intersects(tabPosition)
}
}

View File

@ -7,6 +7,7 @@ import li.cil.oc.common.container
import li.cil.oc.common.tileentity
import net.minecraft.entity.player.InventoryPlayer
// TODO Remove in 1.7
class Switch(playerInventory: InventoryPlayer, val switch: tileentity.Switch) extends DynamicGuiContainer(new container.Switch(playerInventory, switch)) {
private val format = new DecimalFormat("#.##hz")

View File

@ -12,7 +12,7 @@ object SwitchRenderer extends TileEntitySpecialRenderer {
override def renderTileEntityAt(tileEntity: TileEntity, x: Double, y: Double, z: Double, f: Float, damage: Int) {
RenderState.checkError(getClass.getName + ".renderTileEntityAt: entering (aka: wasntme)")
val switch = tileEntity.asInstanceOf[tileentity.Switch]
val switch = tileEntity.asInstanceOf[tileentity.traits.SwitchLike]
val activity = math.max(0, 1 - (System.currentTimeMillis() - switch.lastMessage) / 1000.0)
if (activity > 0) {
RenderState.pushAttrib()

View File

@ -0,0 +1,78 @@
package li.cil.oc.client.renderer.tileentity
import li.cil.oc.client.Textures
import li.cil.oc.common.tileentity
import li.cil.oc.util.RenderState
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.texture.TextureMap
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
import net.minecraft.tileentity.TileEntity
import org.lwjgl.opengl.GL11
object TransposerRenderer extends TileEntitySpecialRenderer {
override def renderTileEntityAt(tileEntity: TileEntity, x: Double, y: Double, z: Double, f: Float, damage: Int) {
RenderState.checkError(getClass.getName + ".renderTileEntityAt: entering (aka: wasntme)")
val transposer = tileEntity.asInstanceOf[tileentity.Transposer]
val activity = math.max(0, 1 - (System.currentTimeMillis() - transposer.lastOperation) / 1000.0)
if (activity > 0) {
RenderState.pushAttrib()
RenderState.disableEntityLighting()
RenderState.makeItBlend()
RenderState.setBlendAlpha(activity.toFloat)
RenderState.pushMatrix()
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
GL11.glScaled(1.0025, -1.0025, 1.0025)
GL11.glTranslatef(-0.5f, -0.5f, -0.5f)
val t = Tessellator.getInstance
val r = t.getWorldRenderer
Textures.Block.bind()
r.startDrawingQuads()
val icon = Textures.getSprite(Textures.Block.TransposerOn)
r.addVertexWithUV(0, 1, 0, icon.getMaxU, icon.getMinV)
r.addVertexWithUV(1, 1, 0, icon.getMinU, icon.getMinV)
r.addVertexWithUV(1, 1, 1, icon.getMinU, icon.getMaxV)
r.addVertexWithUV(0, 1, 1, icon.getMaxU, icon.getMaxV)
r.addVertexWithUV(0, 0, 0, icon.getMaxU, icon.getMaxV)
r.addVertexWithUV(0, 0, 1, icon.getMaxU, icon.getMinV)
r.addVertexWithUV(1, 0, 1, icon.getMinU, icon.getMinV)
r.addVertexWithUV(1, 0, 0, icon.getMinU, icon.getMaxV)
r.addVertexWithUV(1, 1, 0, icon.getMinU, icon.getMaxV)
r.addVertexWithUV(0, 1, 0, icon.getMaxU, icon.getMaxV)
r.addVertexWithUV(0, 0, 0, icon.getMaxU, icon.getMinV)
r.addVertexWithUV(1, 0, 0, icon.getMinU, icon.getMinV)
r.addVertexWithUV(0, 1, 1, icon.getMinU, icon.getMaxV)
r.addVertexWithUV(1, 1, 1, icon.getMaxU, icon.getMaxV)
r.addVertexWithUV(1, 0, 1, icon.getMaxU, icon.getMinV)
r.addVertexWithUV(0, 0, 1, icon.getMinU, icon.getMinV)
r.addVertexWithUV(0, 1, 0, icon.getMinU, icon.getMaxV)
r.addVertexWithUV(0, 1, 1, icon.getMaxU, icon.getMaxV)
r.addVertexWithUV(0, 0, 1, icon.getMaxU, icon.getMinV)
r.addVertexWithUV(0, 0, 0, icon.getMinU, icon.getMinV)
r.addVertexWithUV(1, 1, 1, icon.getMinU, icon.getMaxV)
r.addVertexWithUV(1, 1, 0, icon.getMaxU, icon.getMaxV)
r.addVertexWithUV(1, 0, 0, icon.getMaxU, icon.getMinV)
r.addVertexWithUV(1, 0, 1, icon.getMinU, icon.getMinV)
t.draw()
RenderState.enableEntityLighting()
RenderState.popMatrix()
RenderState.popAttrib()
}
RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving")
}
}

View File

@ -30,6 +30,8 @@ abstract class GuiHandler extends IGuiHandler {
new container.Printer(player.inventory, t)
case t: tileentity.Raid if id == GuiType.Raid.id =>
new container.Raid(player.inventory, t)
case t: tileentity.Relay if id == GuiType.Relay.id =>
new container.Relay(player.inventory, t)
case t: tileentity.RobotProxy if id == GuiType.Robot.id =>
new container.Robot(player.inventory, t.robot)
case t: tileentity.ServerRack if id == GuiType.Rack.id =>

View File

@ -28,6 +28,7 @@ object GuiType extends ScalaEnum {
val Printer = new EnumVal { def name = "Printer"; def subType = GuiType.Category.Block }
val Rack = new EnumVal { def name = "Rack"; def subType = GuiType.Category.Block }
val Raid = new EnumVal { def name = "Raid"; def subType = GuiType.Category.Block }
val Relay = new EnumVal { def name = "Relay"; def subType = GuiType.Category.Block }
val Robot = new EnumVal { def name = "Robot"; def subType = GuiType.Category.Block }
val Screen = new EnumVal { def name = "Screen"; def subType = GuiType.Category.Block }
val Server = new EnumVal { def name = "Server"; def subType = GuiType.Category.Item }

View File

@ -120,6 +120,13 @@ object InventorySlots {
)
)
val relay = Array(
InventorySlot(Slot.CPU, Tier.Three),
InventorySlot(Slot.Memory, Tier.Three),
InventorySlot(Slot.HDD, Tier.Three),
InventorySlot(Slot.Card, Tier.Three)
)
val switch = Array(
InventorySlot(Slot.CPU, Tier.Three),
InventorySlot(Slot.Memory, Tier.Three),

View File

@ -20,6 +20,7 @@ object PacketType extends Enumeration {
HologramTranslation,
HologramValues,
LootDisk,
NetSplitterState,
ParticleEffect,
PetVisibility, // Goes both ways.
PowerState,
@ -49,11 +50,11 @@ object PacketType extends Enumeration {
TextBufferMultiRawSetBackground,
TextBufferMultiRawSetForeground,
TextBufferPowerChange,
NetSplitterState,
ScreenTouchMode,
ServerPresence,
Sound,
SoundPattern,
TransposerActivity,
WaypointLabel, // Goes both ways.
// Client -> Server

View File

@ -4,6 +4,7 @@ import li.cil.oc.Settings
import li.cil.oc.common.tileentity
import net.minecraft.world.World
// TODO Remove in 1.7
class AccessPoint extends Switch with traits.PowerAcceptor {
override def energyThroughput = Settings.get.accessPointRate

View File

@ -0,0 +1,17 @@
package li.cil.oc.common.block
import li.cil.oc.Settings
import li.cil.oc.common.GuiType
import li.cil.oc.common.tileentity
import net.minecraft.block.state.IBlockState
import net.minecraft.world.World
class Relay extends SimpleBlock with traits.GUI with traits.PowerAcceptor {
override def guiType = GuiType.Relay
override def energyThroughput = Settings.get.accessPointRate
override def hasTileEntity(state: IBlockState) = true
override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Relay()
}

View File

@ -5,6 +5,7 @@ import li.cil.oc.common.tileentity
import net.minecraft.block.state.IBlockState
import net.minecraft.world.World
// TODO Remove in 1.7
class Switch extends SimpleBlock with traits.GUI {
override def guiType = GuiType.Switch

View File

@ -0,0 +1,18 @@
package li.cil.oc.common.block
import li.cil.oc.common.tileentity
import net.minecraft.block.state.IBlockState
import net.minecraft.util.BlockPos
import net.minecraft.util.EnumFacing
import net.minecraft.world.IBlockAccess
import net.minecraft.world.World
class Transposer extends SimpleBlock {
override def isSideSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing): Boolean = false
// ----------------------------------------------------------------------- //
override def hasTileEntity(state: IBlockState): Boolean = true
override def createNewTileEntity(world: World, meta: Int) = new tileentity.Transposer()
}

View File

@ -0,0 +1,33 @@
package li.cil.oc.common.container
import li.cil.oc.common.Slot
import li.cil.oc.common.tileentity
import net.minecraft.entity.player.InventoryPlayer
import net.minecraft.nbt.NBTTagCompound
class Relay(playerInventory: InventoryPlayer, relay: tileentity.Relay) extends Player(playerInventory, relay) {
addSlotToContainer(151, 15, Slot.CPU)
addSlotToContainer(151, 34, Slot.Memory)
addSlotToContainer(151, 53, Slot.HDD)
addSlotToContainer(178, 15, Slot.Card)
addPlayerInventorySlots(8, 84)
def relayDelay = synchronizedData.getInteger("relayDelay")
def relayAmount = synchronizedData.getInteger("relayAmount")
def maxQueueSize = synchronizedData.getInteger("maxQueueSize")
def packetsPerCycleAvg = synchronizedData.getInteger("packetsPerCycleAvg")
def queueSize = synchronizedData.getInteger("queueSize")
override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = {
synchronizedData.setInteger("relayDelay", relay.relayDelay)
synchronizedData.setInteger("relayAmount", relay.relayAmount)
synchronizedData.setInteger("maxQueueSize", relay.maxQueueSize)
synchronizedData.setInteger("packetsPerCycleAvg", relay.packetsPerCycleAvg())
synchronizedData.setInteger("queueSize", relay.queue.size)
super.detectCustomDataChanges(nbt)
}
}

View File

@ -5,6 +5,7 @@ import li.cil.oc.common.tileentity
import net.minecraft.entity.player.InventoryPlayer
import net.minecraft.nbt.NBTTagCompound
// TODO Remove in 1.7
class Switch(playerInventory: InventoryPlayer, switch: tileentity.Switch) extends Player(playerInventory, switch) {
addSlotToContainer(151, 15, Slot.CPU)
addSlotToContainer(151, 34, Slot.Memory)

View File

@ -24,20 +24,22 @@ object Blocks {
GameRegistry.registerTileEntity(classOf[tileentity.Geolyzer], Settings.namespace + "geolyzer")
GameRegistry.registerTileEntity(classOf[tileentity.Microcontroller], Settings.namespace + "microcontroller")
GameRegistry.registerTileEntity(classOf[tileentity.MotionSensor], Settings.namespace + "motionSensor")
GameRegistry.registerTileEntity(classOf[tileentity.NetSplitter], Settings.namespace + "netSplitter")
GameRegistry.registerTileEntity(classOf[tileentity.PowerConverter], Settings.namespace + "powerConverter")
GameRegistry.registerTileEntity(classOf[tileentity.PowerDistributor], Settings.namespace + "powerDistributor")
GameRegistry.registerTileEntity(classOf[tileentity.Print], Settings.namespace + "print")
GameRegistry.registerTileEntity(classOf[tileentity.Printer], Settings.namespace + "printer")
GameRegistry.registerTileEntity(classOf[tileentity.Raid], Settings.namespace + "raid")
GameRegistry.registerTileEntity(classOf[tileentity.Redstone], Settings.namespace + "redstone")
GameRegistry.registerTileEntity(classOf[tileentity.Relay], Settings.namespace + "relay")
GameRegistry.registerTileEntity(classOf[tileentity.RobotProxy], Settings.namespace + "robot")
GameRegistry.registerTileEntity(classOf[tileentity.Switch], Settings.namespace + "switch")
GameRegistry.registerTileEntity(classOf[tileentity.Screen], Settings.namespace + "screen")
GameRegistry.registerTileEntity(classOf[tileentity.ServerRack], Settings.namespace + "serverRack")
GameRegistry.registerTileEntity(classOf[tileentity.NetSplitter], Settings.namespace + "netSplitter")
GameRegistry.registerTileEntity(classOf[tileentity.Transposer], Settings.namespace + "transposer")
GameRegistry.registerTileEntity(classOf[tileentity.Waypoint], Settings.namespace + "waypoint")
Recipes.addBlock(new AccessPoint(), Constants.BlockName.AccessPoint, "oc:accessPoint")
Items.registerBlock(new AccessPoint(), Constants.BlockName.AccessPoint)
Recipes.addBlock(new Adapter(), Constants.BlockName.Adapter, "oc:adapter")
Recipes.addBlock(new Assembler(), Constants.BlockName.Assembler, "oc:assembler")
Recipes.addBlock(new Cable(), Constants.BlockName.Cable, "oc:cable")
@ -59,11 +61,12 @@ object Blocks {
Recipes.addBlock(new Printer(), Constants.BlockName.Printer, "oc:printer")
Recipes.addBlock(new Raid(), Constants.BlockName.Raid, "oc:raid")
Recipes.addBlock(new Redstone(), Constants.BlockName.Redstone, "oc:redstone")
Recipes.addBlock(new Relay(), Constants.BlockName.Relay, "oc:relay")
Recipes.addBlock(new Screen(Tier.One), Constants.BlockName.ScreenTier1, "oc:screen1")
Recipes.addBlock(new Screen(Tier.Three), Constants.BlockName.ScreenTier3, "oc:screen3")
Recipes.addBlock(new Screen(Tier.Two), Constants.BlockName.ScreenTier2, "oc:screen2")
Recipes.addBlock(new ServerRack(), Constants.BlockName.ServerRack, "oc:serverRack")
Recipes.addBlock(new Switch(), Constants.BlockName.Switch, "oc:switch")
Items.registerBlock(new Switch(), Constants.BlockName.Switch)
Recipes.addBlock(new Waypoint(), Constants.BlockName.Waypoint, "oc:waypoint")
Items.registerBlock(new Case(Tier.Four), Constants.BlockName.CaseCreative)
@ -77,5 +80,8 @@ object Blocks {
// v1.5.14
Recipes.addBlock(new NetSplitter(), Constants.BlockName.NetSplitter, "oc:netSplitter")
// v1.5.16
Recipes.addBlock(new Transposer(), Constants.BlockName.Transposer, "oc:transposer")
}
}

View File

@ -241,9 +241,11 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
override def facing = RotationHelper.fromYaw(player.rotationYaw)
override def toLocal(value: EnumFacing) = value // -T-O-D-O- do we care? no we don't
override def toLocal(value: EnumFacing) =
RotationHelper.toLocal(EnumFacing.NORTH, facing, value)
override def toGlobal(value: EnumFacing) = value // -T-O-D-O- do we care? no we don't
override def toGlobal(value: EnumFacing) =
RotationHelper.toGlobal(EnumFacing.NORTH, facing, value)
def readFromNBT() {
if (stack.hasTagCompound) {

View File

@ -3,12 +3,10 @@ package li.cil.oc.common.item.traits
import java.util
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.machine.Architecture
import li.cil.oc.integration.opencomputers.DriverCPU
import li.cil.oc.util.Tooltip
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.ChatComponentTranslation
import net.minecraft.world.World
@ -21,37 +19,19 @@ trait CPULike extends Delegate {
override protected def tooltipData: Seq[Any] = Seq(Settings.get.cpuComponentSupport(cpuTier))
override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]) {
(if (stack.hasTagCompound) {
Option(stack.getTagCompound.getString(Settings.namespace + "archName"))
}
else {
val architectures = allArchitectures
architectures.headOption.map(_._2)
}) match {
case Some(archName) if !archName.isEmpty => tooltip.addAll(Tooltip.get("CPU.Architecture", archName))
case _ => allArchitectures.headOption.collect {
case ((_, name)) => tooltip.addAll(Tooltip.get("CPU.Architecture", name))
}
}
tooltip.addAll(Tooltip.get("CPU.Architecture", DriverCPU.getArchitectureName(DriverCPU.architecture(stack))))
}
override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer) = {
if (player.isSneaking) {
if (!world.isRemote) {
val architectures = allArchitectures
if (architectures.length > 0) {
val currentIndex = if (stack.hasTagCompound) {
val currentArch = stack.getTagCompound.getString(Settings.namespace + "archClass")
architectures.indexWhere(_._1.getName == currentArch)
}
else {
stack.setTagCompound(new NBTTagCompound())
-1
}
val index = (currentIndex + 1) % architectures.length
val (archClass, archName) = architectures(index)
stack.getTagCompound.setString(Settings.namespace + "archClass", archClass.getName)
stack.getTagCompound.setString(Settings.namespace + "archName", archName)
val architectures = DriverCPU.allArchitectures.toList
if (architectures.nonEmpty) {
val currentIndex = architectures.indexOf(DriverCPU.architecture(stack))
val newIndex = (currentIndex + 1) % architectures.length
val archClass = architectures(newIndex)
val archName = DriverCPU.getArchitectureName(archClass)
DriverCPU.setArchitecture(stack, archClass)
player.addChatMessage(new ChatComponentTranslation(Settings.namespace + "tooltip.CPU.Architecture", archName))
}
player.swingItem()
@ -59,11 +39,4 @@ trait CPULike extends Delegate {
}
stack
}
private def allArchitectures = api.Machine.architectures.map { arch =>
arch.getAnnotation(classOf[Architecture.Name]) match {
case annotation: Architecture.Name => (arch, annotation.value)
case _ => (arch, arch.getSimpleName)
}
}.toArray
}

View File

@ -326,6 +326,12 @@ object Recipes {
GameRegistry.addRecipe(new ExtendedShapelessOreRecipe(
lightPrint,
print.createItemStack(1), new ItemStack(net.minecraft.init.Blocks.glowstone)))
// Switch/AccessPoint -> Relay conversion
GameRegistry.addShapelessRecipe(api.Items.get(Constants.BlockName.Relay).createItemStack(1),
api.Items.get(Constants.BlockName.AccessPoint).createItemStack(1))
GameRegistry.addShapelessRecipe(api.Items.get(Constants.BlockName.Relay).createItemStack(1),
api.Items.get(Constants.BlockName.Switch).createItemStack(1))
}
catch {
case e: Throwable => OpenComputers.log.error("Error parsing recipes, you may not be able to craft any items from this mod!", e)

View File

@ -15,6 +15,7 @@ import net.minecraftforge.common.util.Constants.NBT
import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly
// TODO Remove in 1.7
class AccessPoint extends Switch with WirelessEndpoint with traits.PowerAcceptor {
var strength = Settings.get.maxWirelessRange
@ -24,6 +25,8 @@ class AccessPoint extends Switch with WirelessEndpoint with traits.PowerAcceptor
withComponent("access_point").
create())
override def isWirelessEnabled = true
// ----------------------------------------------------------------------- //
@SideOnly(Side.CLIENT)
@ -71,7 +74,7 @@ class AccessPoint extends Switch with WirelessEndpoint with traits.PowerAcceptor
override protected def relayPacket(sourceSide: Option[EnumFacing], packet: Packet) {
super.relayPacket(sourceSide, packet)
if (strength > 0 && (sourceSide != None || isRepeater)) {
if (strength > 0 && (sourceSide.isDefined || isRepeater)) {
val cost = Settings.get.wirelessCostPerRange
val tryChangeBuffer = sourceSide match {
case Some(side) =>

View File

@ -0,0 +1,282 @@
package li.cil.oc.common.tileentity
import li.cil.oc.Constants
import li.cil.oc.Localization
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.Driver
import li.cil.oc.api.machine.Arguments
import li.cil.oc.api.machine.Callback
import li.cil.oc.api.machine.Context
import li.cil.oc.api.network.Analyzable
import li.cil.oc.api.network.Connector
import li.cil.oc.api.network.Node
import li.cil.oc.api.network.Packet
import li.cil.oc.api.network.Visibility
import li.cil.oc.api.network.WirelessEndpoint
import li.cil.oc.common.InventorySlots
import li.cil.oc.common.Slot
import li.cil.oc.common.item
import li.cil.oc.common.item.Delegator
import li.cil.oc.integration.Mods
import li.cil.oc.integration.opencomputers.DriverLinkedCard
import li.cil.oc.server.network.QuantumNetwork
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.EnumFacing
import net.minecraftforge.common.util.Constants.NBT
import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly
class Relay extends traits.SwitchLike with traits.ComponentInventory with traits.PowerAcceptor with Analyzable with WirelessEndpoint with QuantumNetwork.QuantumNode {
lazy final val WirelessNetworkCard = api.Items.get(Constants.ItemName.WirelessNetworkCard)
lazy final val LinkedCard = api.Items.get(Constants.ItemName.LinkedCard)
var strength = Settings.get.maxWirelessRange
var isRepeater = true
var isWirelessEnabled = false
var isLinkedEnabled = false
var tunnel = "creative"
val componentNodes = Array.fill(6)(api.Network.newNode(this, Visibility.Network).
withComponent("relay").
create())
override def canUpdate = isServer
// ----------------------------------------------------------------------- //
@SideOnly(Side.CLIENT)
override protected def hasConnector(side: EnumFacing) = true
override protected def connector(side: EnumFacing) = sidedNode(side) match {
case connector: Connector => Option(connector)
case _ => None
}
override def energyThroughput = Settings.get.accessPointRate
// ----------------------------------------------------------------------- //
override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Array[Node] = {
if (isWirelessEnabled) {
player.addChatMessage(Localization.Analyzer.WirelessStrength(strength))
Array(componentNodes(side.getIndex))
}
else null
}
// ----------------------------------------------------------------------- //
@Callback(direct = true, doc = """function():number -- Get the signal strength (range) used when relaying messages.""")
def getStrength(context: Context, args: Arguments): Array[AnyRef] = synchronized(result(strength))
@Callback(doc = """function(strength:number):number -- Set the signal strength (range) used when relaying messages.""")
def setStrength(context: Context, args: Arguments): Array[AnyRef] = synchronized {
strength = math.max(args.checkDouble(0), math.min(0, Settings.get.maxWirelessRange))
result(strength)
}
@Callback(direct = true, doc = """function():boolean -- Get whether the access point currently acts as a repeater (resend received wireless packets wirelessly).""")
def isRepeater(context: Context, args: Arguments): Array[AnyRef] = synchronized(result(isRepeater))
@Callback(doc = """function(enabled:boolean):boolean -- Set whether the access point should act as a repeater.""")
def setRepeater(context: Context, args: Arguments): Array[AnyRef] = synchronized {
isRepeater = args.checkBoolean(0)
result(isRepeater)
}
// ----------------------------------------------------------------------- //
protected def queueMessage(source: String, destination: String, port: Int, answerPort: Int, args: Array[AnyRef]) {
/* TODO ComputerCraft
for (computer <- computers.map(_.asInstanceOf[IComputerAccess])) {
val address = s"cc${computer.getID}_${computer.getAttachmentName}"
if (source != address && Option(destination).forall(_ == address) && openPorts(computer).contains(port))
computer.queueEvent("modem_message", Array(Seq(computer.getAttachmentName, Int.box(port), Int.box(answerPort)) ++ args.map {
case x: Array[Byte] => new String(x, Charsets.UTF_8)
case x => x
}: _*))
}
*/
}
// ----------------------------------------------------------------------- //
override def receivePacket(packet: Packet, source: WirelessEndpoint): Unit = {
if (isWirelessEnabled) {
tryEnqueuePacket(None, packet)
}
}
override def receivePacket(packet: Packet): Unit = {
if (isLinkedEnabled) {
tryEnqueuePacket(None, packet)
}
}
override def tryEnqueuePacket(sourceSide: Option[EnumFacing], packet: Packet): Boolean = {
if (Mods.ComputerCraft.isAvailable) {
packet.data.headOption match {
case Some(answerPort: java.lang.Double) => queueMessage(packet.source, packet.destination, packet.port, answerPort.toInt, packet.data.drop(1))
case _ => queueMessage(packet.source, packet.destination, packet.port, -1, packet.data)
}
}
super.tryEnqueuePacket(sourceSide, packet)
}
override protected def relayPacket(sourceSide: Option[EnumFacing], packet: Packet): Unit = {
super.relayPacket(sourceSide, packet)
val tryChangeBuffer = sourceSide match {
case Some(side) =>
(amount: Double) => plugs(side.ordinal).node.asInstanceOf[Connector].tryChangeBuffer(amount)
case _ =>
(amount: Double) => plugs.exists(_.node.asInstanceOf[Connector].tryChangeBuffer(amount))
}
if (isWirelessEnabled && strength > 0 && (sourceSide.isDefined || isRepeater)) {
val cost = Settings.get.wirelessCostPerRange
if (tryChangeBuffer(-strength * cost)) {
api.Network.sendWirelessPacket(this, strength, packet)
}
}
if (isLinkedEnabled && sourceSide.isDefined) {
val cost = packet.size / 32.0 + Settings.get.wirelessCostPerRange * Settings.get.maxWirelessRange * 5
if (tryChangeBuffer(-cost)) {
val endpoints = QuantumNetwork.getEndpoints(tunnel).filter(_ != this)
for (endpoint <- endpoints) {
endpoint.receivePacket(packet)
}
}
}
onSwitchActivity()
}
// ----------------------------------------------------------------------- //
override protected def createNode(plug: Plug) = api.Network.newNode(plug, Visibility.Network).
withConnector(math.round(Settings.get.bufferAccessPoint)).
create()
override protected def onPlugConnect(plug: Plug, node: Node) {
super.onPlugConnect(plug, node)
if (node == plug.node) {
api.Network.joinWirelessNetwork(this)
}
if (plug.isPrimary)
plug.node.connect(componentNodes(plug.side.ordinal()))
else
componentNodes(plug.side.ordinal).remove()
}
override protected def onPlugDisconnect(plug: Plug, node: Node) {
super.onPlugDisconnect(plug, node)
if (node == plug.node) {
api.Network.leaveWirelessNetwork(this)
}
if (plug.isPrimary && node != plug.node)
plug.node.connect(componentNodes(plug.side.ordinal()))
else
componentNodes(plug.side.ordinal).remove()
}
// ----------------------------------------------------------------------- //
override protected def onItemAdded(slot: Int, stack: ItemStack) {
super.onItemAdded(slot, stack)
updateLimits(slot, stack)
}
private def updateLimits(slot: Int, stack: ItemStack) {
Option(Driver.driverFor(stack, getClass)) match {
case Some(driver) if driver.slot(stack) == Slot.CPU =>
relayDelay = math.max(1, relayBaseDelay - ((driver.tier(stack) + 1) * relayDelayPerUpgrade))
case Some(driver) if driver.slot(stack) == Slot.Memory =>
relayAmount = math.max(1, relayBaseAmount + (Delegator.subItem(stack) match {
case Some(ram: item.Memory) => (ram.tier + 1) * relayAmountPerUpgrade
case _ => (driver.tier(stack) + 1) * (relayAmountPerUpgrade * 2)
}))
case Some(driver) if driver.slot(stack) == Slot.HDD =>
maxQueueSize = math.max(1, queueBaseSize + (driver.tier(stack) + 1) * queueSizePerUpgrade)
case Some(driver) if driver.slot(stack) == Slot.Card =>
val descriptor = api.Items.get(stack)
if (descriptor == WirelessNetworkCard) {
isWirelessEnabled = true
}
if (descriptor == LinkedCard) {
val data = DriverLinkedCard.dataTag(stack)
if (data.hasKey(Settings.namespace + "tunnel")) {
tunnel = data.getString(Settings.namespace + "tunnel")
isLinkedEnabled = true
QuantumNetwork.add(this)
}
}
case _ => // Dafuq u doin.
}
}
override protected def onItemRemoved(slot: Int, stack: ItemStack) {
super.onItemRemoved(slot, stack)
Driver.driverFor(stack, getClass) match {
case driver if driver.slot(stack) == Slot.CPU => relayDelay = relayBaseDelay
case driver if driver.slot(stack) == Slot.Memory => relayAmount = relayBaseAmount
case driver if driver.slot(stack) == Slot.HDD => maxQueueSize = queueBaseSize
case driver if driver.slot(stack) == Slot.Card =>
isWirelessEnabled = false
isLinkedEnabled = false
QuantumNetwork.remove(this)
}
}
override def getSizeInventory = InventorySlots.relay.length
override def isItemValidForSlot(slot: Int, stack: ItemStack) =
Option(Driver.driverFor(stack, getClass)).fold(false)(driver => {
val provided = InventorySlots.relay(slot)
val tierSatisfied = driver.slot(stack) == provided.slot && driver.tier(stack) <= provided.tier
val cardTypeSatisfied = if (provided.slot == Slot.Card) api.Items.get(stack) == WirelessNetworkCard || api.Items.get(stack) == LinkedCard else true
tierSatisfied && cardTypeSatisfied
})
// ----------------------------------------------------------------------- //
override def readFromNBTForServer(nbt: NBTTagCompound) {
super.readFromNBTForServer(nbt)
for (slot <- items.indices) items(slot) collect {
case stack => updateLimits(slot, stack)
}
if (nbt.hasKey(Settings.namespace + "strength")) {
strength = nbt.getDouble(Settings.namespace + "strength") max 0 min Settings.get.maxWirelessRange
}
if (nbt.hasKey(Settings.namespace + "isRepeater")) {
isRepeater = nbt.getBoolean(Settings.namespace + "isRepeater")
}
nbt.getTagList(Settings.namespace + "componentNodes", NBT.TAG_COMPOUND).toArray[NBTTagCompound].
zipWithIndex.foreach {
case (tag, index) => componentNodes(index).load(tag)
}
}
override def writeToNBTForServer(nbt: NBTTagCompound) = {
super.writeToNBTForServer(nbt)
nbt.setDouble(Settings.namespace + "strength", strength)
nbt.setBoolean(Settings.namespace + "isRepeater", isRepeater)
nbt.setNewTagList(Settings.namespace + "componentNodes", componentNodes.map {
case node: Node =>
val tag = new NBTTagCompound()
node.save(tag)
tag
case _ => new NBTTagCompound()
})
}
}

View File

@ -6,25 +6,49 @@ import li.cil.oc.common.InventorySlots
import li.cil.oc.common.Slot
import li.cil.oc.common.item
import li.cil.oc.common.item.Delegator
import li.cil.oc.server.PacketSender
import li.cil.oc.integration.Mods
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.EnumFacing
class Switch extends traits.Hub with traits.NotAnalyzable with traits.ComponentInventory {
var lastMessage = 0L
// TODO Remove in 1.7
class Switch extends traits.SwitchLike with traits.NotAnalyzable with traits.ComponentInventory {
override def isWirelessEnabled = false
override def isLinkedEnabled = false
override def canUpdate = isServer
// ----------------------------------------------------------------------- //
protected def queueMessage(source: String, destination: String, port: Int, answerPort: Int, args: Array[AnyRef]) {
/* TODO ComputerCraft
for (computer <- computers.map(_.asInstanceOf[IComputerAccess])) {
val address = s"cc${computer.getID}_${computer.getAttachmentName}"
if (source != address && Option(destination).forall(_ == address) && openPorts(computer).contains(port))
computer.queueEvent("modem_message", Array(Seq(computer.getAttachmentName, Int.box(port), Int.box(answerPort)) ++ args.map {
case x: Array[Byte] => new String(x, Charsets.UTF_8)
case x => x
}: _*))
}
*/
}
// ----------------------------------------------------------------------- //
override def tryEnqueuePacket(sourceSide: Option[EnumFacing], packet: Packet): Boolean = {
if (Mods.ComputerCraft.isAvailable) {
packet.data.headOption match {
case Some(answerPort: java.lang.Double) => queueMessage(packet.source, packet.destination, packet.port, answerPort.toInt, packet.data.drop(1))
case _ => queueMessage(packet.source, packet.destination, packet.port, -1, packet.data)
}
}
super.tryEnqueuePacket(sourceSide, packet)
}
override protected def relayPacket(sourceSide: Option[EnumFacing], packet: Packet) {
super.relayPacket(sourceSide, packet)
val now = System.currentTimeMillis()
if (now - lastMessage >= (relayDelay - 1) * 50) {
lastMessage = now
PacketSender.sendSwitchActivity(this)
}
onSwitchActivity()
}
// ----------------------------------------------------------------------- //

View File

@ -0,0 +1,25 @@
package li.cil.oc.common.tileentity
import li.cil.oc.server.component
import net.minecraft.nbt.NBTTagCompound
class Transposer extends traits.Environment {
val transposer = new component.Transposer(this)
def node = transposer.node
// Used on client side to check whether to render activity indicators.
var lastOperation = 0L
override def canUpdate = false
override def readFromNBTForServer(nbt: NBTTagCompound) {
super.readFromNBTForServer(nbt)
transposer.load(nbt)
}
override def writeToNBTForServer(nbt: NBTTagCompound) {
super.writeToNBTForServer(nbt)
transposer.save(nbt)
}
}

Some files were not shown because too many files have changed in this diff Show More