mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-15 10:21:45 -04:00
Merge branch 'master-MC1.7.10' of github.com:MightyPirates/OpenComputers into master-MC1.8
Conflicts: src/main/scala/li/cil/oc/common/item/Acid.scala src/main/scala/li/cil/oc/common/item/Nanomachines.scala
This commit is contained in:
commit
a76bdb4552
@ -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.6.0";
|
||||
public static final String VERSION = "5.6.1";
|
||||
|
||||
public static DriverAPI driver = null;
|
||||
public static FileSystemAPI fileSystem = null;
|
||||
|
@ -44,15 +44,24 @@ public interface Controller {
|
||||
int getTotalInputCount();
|
||||
|
||||
/**
|
||||
* Get the total number of inputs that may be active at the same time
|
||||
* Get the number of inputs that may be active at the same time
|
||||
* before negative effects are applied to the player.
|
||||
* <p/>
|
||||
* The number of active inputs may exceed this value, but this will
|
||||
* have negative effects on the player.
|
||||
*
|
||||
* @return the number of inputs that may safely be active at a time.
|
||||
*/
|
||||
int getSafeActiveInputs();
|
||||
|
||||
/**
|
||||
* Get the total number of inputs that may be active at the same time.
|
||||
* <p/>
|
||||
* The number of active inputs cannot exceed this value.
|
||||
*
|
||||
* @return the number of inputs that may be active at a time.
|
||||
*/
|
||||
int getSafeInputCount();
|
||||
int getMaxActiveInputs();
|
||||
|
||||
/**
|
||||
* Get whether the input with the specified index is active.
|
||||
@ -65,12 +74,16 @@ public interface Controller {
|
||||
|
||||
/**
|
||||
* Set the state of the input with the specified index.
|
||||
* <p/>
|
||||
* This will fail if too many inputs are active already. It will also
|
||||
* always fail when called on the client.
|
||||
*
|
||||
* @param index the input index.
|
||||
* @param value whether the input should be active.
|
||||
* @return whether the input was changed successfully.
|
||||
* @throws IndexOutOfBoundsException if <code>index < 0</code> or <code>index >= getInputCount</code>.
|
||||
*/
|
||||
void setInput(int index, boolean value);
|
||||
boolean setInput(int index, boolean value);
|
||||
|
||||
/**
|
||||
* Get the list of currently active behaviors, based on the current input states.
|
||||
|
@ -1011,11 +1011,21 @@ opencomputers {
|
||||
|
||||
# How many input nodes may be active at the same time before negative
|
||||
# effects are applied to the player.
|
||||
safeInputCount: 2
|
||||
safeInputsActive: 2
|
||||
|
||||
# The time in seconds it takes to reconfigure the nanomachines. This is
|
||||
# to avoid spamming reconfigurations.
|
||||
reconfigureCooldown: 5
|
||||
# Hard maximum number of active inputs. This is mainly to avoid people
|
||||
# bumping other nanomachines' inputs to max, killing them in a matter
|
||||
# of (milli)seconds.
|
||||
maxInputsActive: 4
|
||||
|
||||
# Time in seconds it takes for the nanomachines to process a command
|
||||
# and send a response.
|
||||
commandDelay: 1
|
||||
|
||||
# The distance in blocks that nanomachines can communicate within. If
|
||||
# a message comes from further away, it'll be ignored. When responding,
|
||||
# the response will only be sent this far.
|
||||
commandRange: 2
|
||||
|
||||
# Range of the item magnet behavior added for each active input.
|
||||
magnetRange: 8
|
||||
|
@ -4,4 +4,6 @@
|
||||
|
||||
This tasty [citation needed] concoction can be consumed if you ever feel the need for some... fun. Or ruining your digestive tract. Or both. It can also serve as ingredient in other, more useful items.
|
||||
|
||||
One of the main uses, however, is to remove [nanomachines](nanomachines.md) from your system, if you no longer want them in you. Drinking this is the only way of getting rid of them!
|
||||
|
||||
When using hard-mode recipes, it is used to etch [circuit boards](circuitBoard.md) before crafting [printed circuit boards](printedCircuitBoard.md).
|
||||
|
@ -8,22 +8,26 @@ Once injected, a new power indicator in your HUD will indicate how much energy y
|
||||
|
||||
Nanomachines provide a certain number of "inputs" that can be triggered, causing many different effects on the player, ranging from visual effects such as particles spawning near the player, to select potion effects and some more rare and special behaviors!
|
||||
|
||||
Which input triggers what effect depends on the current configuration of the nanomachines, the actual "connections" being random per configuration. This means you'll have to try enabling different inputs to see what they do. If you're unhappy with a configuration, you can always reconfigure your nanomachines. Beware that enabling too many inputs at a time has severe negative effects on you!
|
||||
Which input triggers what effect depends on the current configuration of the nanomachines, the actual "connections" being random per configuration. This means you'll have to try enabling different inputs to see what they do. If you're unhappy with a configuration, you can always reconfigure your nanomachines by injecting a new batch (just eat some more). To completely get rid of the nanomachines in you, consider drinking some [grog](acid.md). Beware that enabling too many inputs at a time has severe negative effects on you!
|
||||
|
||||
By default, the nanomachines will be on standby. You'll need to control them using wireless messages, so carrying a [tablet](tablet.md) with a [wireless network card](wlanCard.md) is strongly recommended. Nanomachines will only react to wireless signals emitted by devices no further than two meters away, but they will react to messages on any port, and from any device!
|
||||
|
||||
Nanomachines react to a simple, proprietary protocol: each packet must consist of multiple parts, the first of which is the "header" and must equal the string `nanomachines`. The second part must be the command name. Additional parts are parameters for the command. The following commands are available, formatted as `commandName(arg1, ...)`:
|
||||
|
||||
- `setResponsePort(port:number)` - Set the port nanomachines should send response messages to, for commands that have a response.
|
||||
- `dispose()` - Destroy all nanomachines currently in the player.
|
||||
- `reconfigure()` - Cause the nanomachines to enter a new configuration.
|
||||
- `getTotalInputCount()` - Request a message with the total number of available inputs.
|
||||
- `getSafeInputCount()` - Request a message with the number of *safe* inputs.
|
||||
- `getInput(index:number)` - Request a message with the current state of the input with the specified index.
|
||||
- `getPowerState()` - Request the currently stored and maximum stored energy of the nanomachines.
|
||||
- `getHealth()` - Request the player's health state.
|
||||
- `getHunger()` - Request the player's hunger state.
|
||||
- `getAge()` - Request the player's age in seconds.
|
||||
- `getName()` - Request the player's display name.
|
||||
- `getExperience()` - Request the player's experience level.
|
||||
- `getTotalInputCount()` - Request the total number of available inputs.
|
||||
- `getSafeActiveInputs()` - Request the number of *safe* active inputs.
|
||||
- `getMaxActiveInputs()` - Request the number of *maximum* active inputs.
|
||||
- `getInput(index:number)` - Request the current state of the input with the specified index.
|
||||
- `setInput(index:number, value:boolean)` - Set the state of the input with the specified index to the specified value.
|
||||
- `getActiveEffects()` - Request a list of active effects. Note that some effects may not show up in this list.
|
||||
- `getPowerState()` - Request a message with the currently stored and maximum stored energy of the nanomachines.
|
||||
|
||||
For example, in OpenOS:
|
||||
- `component.modem.broadcast(1, "nanomachines", "setInput", 1, true)` will enable the first input.
|
||||
- `component.modem.broadcast(1, "nanomachines", "reconfigure")` will reconfigure the nanomachines.
|
||||
- `component.modem.broadcast(1, "nanomachines", "getHealth")` will get the player's health info.
|
||||
|
@ -356,8 +356,10 @@ class Settings(val config: Config) {
|
||||
val nanomachineConnectorQuota = config.getDouble("nanomachines.connectorQuota") max 0
|
||||
val nanomachineMaxInputs = config.getInt("nanomachines.maxInputs") max 1
|
||||
val nanomachineMaxOutputs = config.getInt("nanomachines.maxOutputs") max 1
|
||||
val nanomachinesSafeInputCount = config.getInt("nanomachines.safeInputCount") max 0
|
||||
val nanomachineReconfigureTimeout = config.getDouble("nanomachines.reconfigureCooldown") max 0
|
||||
val nanomachinesSafeInputsActive = config.getInt("nanomachines.safeInputsActive") max 0
|
||||
val nanomachinesMaxInputsActive = config.getInt("nanomachines.maxInputsActive") max 0
|
||||
val nanomachinesCommandDelay = config.getDouble("nanomachines.commandDelay") max 0
|
||||
val nanomachinesCommandRange = config.getDouble("nanomachines.commandRange") max 0
|
||||
val nanomachineMagnetRange = config.getDouble("nanomachines.magnetRange") max 0
|
||||
val nanomachineDisintegrationRange = config.getInt("nanomachines.disintegrationRange") max 0
|
||||
val nanomachinePotionWhitelist = config.getAnyRefList("nanomachines.potionWhitelist")
|
||||
|
@ -1,5 +1,6 @@
|
||||
package li.cil.oc.common.item
|
||||
|
||||
import li.cil.oc.api
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.EnumAction
|
||||
import net.minecraft.item.ItemStack
|
||||
@ -23,11 +24,12 @@ class Acid(val parent: Delegator) extends traits.Delegate {
|
||||
player.addPotionEffect(new PotionEffect(Potion.poison.id, 100))
|
||||
player.addPotionEffect(new PotionEffect(Potion.moveSlowdown.id, 600))
|
||||
player.addPotionEffect(new PotionEffect(Potion.confusion.id, 1200))
|
||||
player.addPotionEffect(new PotionEffect(Potion.fireResistance.id, 6000))
|
||||
player.addPotionEffect(new PotionEffect(Potion.saturation.id, 2000))
|
||||
|
||||
stack.stackSize -= 1
|
||||
// Remove nanomachines if installed.
|
||||
api.Nanomachines.uninstallController(player)
|
||||
}
|
||||
stack.stackSize -= 1
|
||||
if (stack.stackSize > 0) stack
|
||||
else null
|
||||
}
|
||||
|
@ -11,9 +11,7 @@ class Nanomachines(val parent: Delegator) extends traits.Delegate {
|
||||
override def rarity(stack: ItemStack): EnumRarity = EnumRarity.UNCOMMON
|
||||
|
||||
override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ItemStack = {
|
||||
if (!api.Nanomachines.hasController(player)) {
|
||||
player.setItemInUse(stack, getMaxItemUseDuration(stack))
|
||||
}
|
||||
player.setItemInUse(stack, getMaxItemUseDuration(stack))
|
||||
stack
|
||||
}
|
||||
|
||||
@ -22,11 +20,11 @@ class Nanomachines(val parent: Delegator) extends traits.Delegate {
|
||||
override def getMaxItemUseDuration(stack: ItemStack): Int = 32
|
||||
|
||||
override def onItemUseFinish(stack: ItemStack, world: World, player: EntityPlayer): ItemStack = {
|
||||
if (!world.isRemote && !api.Nanomachines.hasController(player)) {
|
||||
if (!world.isRemote) {
|
||||
// Reconfigure if already installed.
|
||||
api.Nanomachines.installController(player).reconfigure()
|
||||
|
||||
stack.stackSize -= 1
|
||||
}
|
||||
stack.stackSize -= 1
|
||||
if (stack.stackSize > 0) stack
|
||||
else null
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import scala.collection.mutable
|
||||
class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessEndpoint {
|
||||
if (isServer) api.Network.joinWirelessNetwork(this)
|
||||
|
||||
final val MaxSenderDistance = 2f
|
||||
lazy val CommandRange = Settings.get.nanomachinesCommandRange * Settings.get.nanomachinesCommandRange
|
||||
final val FullSyncInterval = 20 * 60
|
||||
|
||||
final val OverloadDamage = new DamageSourceWithRandomCause("oc.nanomachinesOverload", 3).
|
||||
@ -41,12 +41,13 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
|
||||
|
||||
var uuid = UUID.randomUUID.toString
|
||||
var responsePort = 0
|
||||
var commandDelay = 0
|
||||
var queuedCommand: Option[() => Unit] = None
|
||||
var storedEnergy = Settings.get.bufferNanomachines * 0.25
|
||||
var hadPower = true
|
||||
val configuration = new NeuralNetwork(this)
|
||||
val activeBehaviors = mutable.Set.empty[Behavior]
|
||||
var activeBehaviorsDirty = true
|
||||
var configCooldown = 0
|
||||
var hasSentConfiguration = false
|
||||
|
||||
override def world: World = player.getEntityWorld
|
||||
@ -58,10 +59,10 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
|
||||
override def z: Int = BlockPosition(player).z
|
||||
|
||||
override def receivePacket(packet: Packet, sender: WirelessEndpoint): Unit = {
|
||||
if (getLocalBuffer > 0 && !player.isDead) {
|
||||
if (getLocalBuffer > 0 && commandDelay < 1 && !player.isDead) {
|
||||
val (dx, dy, dz) = ((sender.x + 0.5) - player.posX, (sender.y + 0.5) - player.posY, (sender.z + 0.5) - player.posZ)
|
||||
val dSquared = dx * dx + dy * dy + dz * dz
|
||||
if (dSquared < MaxSenderDistance * MaxSenderDistance) packet.data.headOption match {
|
||||
if (dSquared <= CommandRange) packet.data.headOption match {
|
||||
case Some(header: Array[Byte]) if new String(header, Charsets.UTF_8) == "nanomachines" =>
|
||||
val command = packet.data.drop(1).map {
|
||||
case value: Array[Byte] => new String(value, Charsets.UTF_8)
|
||||
@ -70,17 +71,27 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
|
||||
command match {
|
||||
case Array("setResponsePort", port: java.lang.Number) =>
|
||||
responsePort = port.intValue max 0 min 0xFFFF
|
||||
respond(sender, "responsePort", responsePort)
|
||||
case Array("dispose") =>
|
||||
api.Nanomachines.uninstallController(player)
|
||||
respond(sender, "disposed")
|
||||
case Array("reconfigure") =>
|
||||
reconfigure()
|
||||
respond(sender, "reconfigured")
|
||||
respond(sender, "port", responsePort)
|
||||
case Array("getPowerState") =>
|
||||
respond(sender, "power", getLocalBuffer, getLocalBufferSize)
|
||||
|
||||
case Array("getHealth") =>
|
||||
respond(sender, "health", player.getHealth, player.getMaxHealth)
|
||||
case Array("getHunger") =>
|
||||
respond(sender, "hunger", player.getFoodStats.getFoodLevel, player.getFoodStats.getSaturationLevel)
|
||||
case Array("getAge") =>
|
||||
respond(sender, "age", (player.getAge / 20f).toInt)
|
||||
case Array("getName") =>
|
||||
respond(sender, "name", player.getDisplayName)
|
||||
case Array("getExperience") =>
|
||||
respond(sender, "experience", player.experienceLevel)
|
||||
|
||||
case Array("getTotalInputCount") =>
|
||||
respond(sender, "totalInputCount", getTotalInputCount)
|
||||
case Array("getSafeInputCount") =>
|
||||
respond(sender, "safeInputCount", getSafeInputCount)
|
||||
case Array("getSafeActiveInputs") =>
|
||||
respond(sender, "safeActiveInputs", getSafeActiveInputs)
|
||||
case Array("getMaxActiveInputs") =>
|
||||
respond(sender, "maxActiveInputs", getMaxActiveInputs)
|
||||
case Array("getInput", index: java.lang.Number) =>
|
||||
try {
|
||||
val trigger = getInput(index.intValue - 1)
|
||||
@ -92,8 +103,12 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
|
||||
}
|
||||
case Array("setInput", index: java.lang.Number, value: java.lang.Boolean) =>
|
||||
try {
|
||||
setInput(index.intValue - 1, value.booleanValue)
|
||||
respond(sender, "input", index.intValue, getInput(index.intValue - 1))
|
||||
if (setInput(index.intValue - 1, value.booleanValue)) {
|
||||
respond(sender, "input", index.intValue, getInput(index.intValue - 1))
|
||||
}
|
||||
else {
|
||||
respond(sender, "input", "too many active inputs")
|
||||
}
|
||||
}
|
||||
catch {
|
||||
case _: Throwable =>
|
||||
@ -103,10 +118,8 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
|
||||
configuration.synchronized {
|
||||
val names = getActiveBehaviors.map(_.getNameHint).filterNot(Strings.isNullOrEmpty)
|
||||
val joined = "{" + names.map(_.replace(',', '_').replace('"', '_')).mkString(",") + "}"
|
||||
respond(sender, "active", joined)
|
||||
respond(sender, "effects", joined)
|
||||
}
|
||||
case Array("getPowerState") =>
|
||||
respond(sender, "power", getLocalBuffer, getLocalBufferSize)
|
||||
case _ => // Ignore.
|
||||
}
|
||||
case _ => // Not for us.
|
||||
@ -115,23 +128,25 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
|
||||
}
|
||||
|
||||
def respond(endpoint: WirelessEndpoint, data: Any*): Unit = {
|
||||
if (responsePort > 0) {
|
||||
val cost = Settings.get.wirelessCostPerRange * 10
|
||||
val epsilon = 0.1
|
||||
if (changeBuffer(-cost) > -epsilon) {
|
||||
val packet = api.Network.newPacket(uuid, null, responsePort, (Iterable("nanomachines") ++ data.map(_.asInstanceOf[AnyRef])).toArray)
|
||||
api.Network.sendWirelessPacket(this, 10, packet)
|
||||
queuedCommand = Option(() => {
|
||||
if (responsePort > 0) {
|
||||
val cost = Settings.get.wirelessCostPerRange * CommandRange
|
||||
val epsilon = 0.1
|
||||
if (changeBuffer(-cost) > -epsilon) {
|
||||
val packet = api.Network.newPacket(uuid, null, responsePort, (Iterable("nanomachines") ++ data.map(_.asInstanceOf[AnyRef])).toArray)
|
||||
api.Network.sendWirelessPacket(this, CommandRange, packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
commandDelay = (Settings.get.nanomachinesCommandDelay * 20).toInt
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def reconfigure() = {
|
||||
if (isServer && configCooldown < 1) configuration.synchronized {
|
||||
if (isServer) configuration.synchronized {
|
||||
configuration.reconfigure()
|
||||
activeBehaviorsDirty = true
|
||||
configCooldown = (Settings.get.nanomachineReconfigureTimeout * 20).toInt
|
||||
|
||||
player match {
|
||||
case playerMP: EntityPlayerMP if playerMP.playerNetServerHandler != null =>
|
||||
@ -149,14 +164,19 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
|
||||
|
||||
override def getTotalInputCount: Int = configuration.synchronized(configuration.triggers.length)
|
||||
|
||||
override def getSafeInputCount: Int = Settings.get.nanomachinesSafeInputCount
|
||||
override def getSafeActiveInputs: Int = Settings.get.nanomachinesSafeInputsActive
|
||||
|
||||
override def getMaxActiveInputs: Int = Settings.get.nanomachinesMaxInputsActive
|
||||
|
||||
override def getInput(index: Int): Boolean = configuration.synchronized(configuration.triggers(index).isActive)
|
||||
|
||||
override def setInput(index: Int, value: Boolean): Unit = {
|
||||
if (isServer && configCooldown < 1) configuration.synchronized {
|
||||
configuration.triggers(index).isActive = value
|
||||
activeBehaviorsDirty = true
|
||||
override def setInput(index: Int, value: Boolean): Boolean = {
|
||||
isServer && configuration.synchronized {
|
||||
(!value || configuration.triggers.count(_.isActive) < Settings.get.nanomachinesMaxInputsActive) && {
|
||||
configuration.triggers(index).isActive = value
|
||||
activeBehaviorsDirty = true
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,14 +211,16 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
|
||||
}
|
||||
|
||||
if (isServer) {
|
||||
if (commandDelay > 0) {
|
||||
commandDelay -= 1
|
||||
if (commandDelay == 0) {
|
||||
queuedCommand.foreach(_())
|
||||
queuedCommand = None
|
||||
}
|
||||
}
|
||||
api.Network.updateWirelessNetwork(this)
|
||||
}
|
||||
|
||||
if (configCooldown > 0) {
|
||||
configCooldown -= 1
|
||||
return
|
||||
}
|
||||
|
||||
var hasPower = getLocalBuffer > 0 || Settings.get.ignorePower
|
||||
lazy val active = getActiveBehaviors.toIterable // Wrap once.
|
||||
lazy val activeInputs = configuration.triggers.count(_.isActive)
|
||||
@ -220,7 +242,7 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
|
||||
PacketSender.sendNanomachinePower(player)
|
||||
}
|
||||
|
||||
val overload = activeInputs - getSafeInputCount
|
||||
val overload = activeInputs - getSafeActiveInputs
|
||||
if (!player.capabilities.isCreativeMode && overload > 0 && player.getEntityWorld.getTotalWorldTime % 20 == 0) {
|
||||
player.attackEntityFrom(OverloadDamage, overload)
|
||||
}
|
||||
|
@ -698,7 +698,10 @@ object Network extends api.detail.NetworkAPI {
|
||||
acc + (arg match {
|
||||
case null | Unit | None => 4
|
||||
case _: java.lang.Boolean => 4
|
||||
case _: java.lang.Byte => 4
|
||||
case _: java.lang.Short => 4
|
||||
case _: java.lang.Integer => 4
|
||||
case _: java.lang.Float => 8
|
||||
case _: java.lang.Double => 8
|
||||
case value: java.lang.String => value.length max 1
|
||||
case value: Array[Byte] => value.length max 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user