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

Conflicts:
	src/main/scala/li/cil/oc/common/event/NanomachinesHandler.scala
	src/main/scala/li/cil/oc/common/nanomachines/provider/DisintegrationProvider.scala
	src/main/scala/li/cil/oc/common/nanomachines/provider/MagnetProvider.scala
	src/main/scala/li/cil/oc/common/nanomachines/provider/ParticleProvider.scala
This commit is contained in:
Florian Nücke 2015-09-18 14:52:25 +02:00
commit 2d56a45b7d
24 changed files with 352 additions and 118 deletions

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.5";
public static final String VERSION = "5.6.0";
public static DriverAPI driver = null;
public static FileSystemAPI fileSystem = null;

View File

@ -40,8 +40,10 @@ public interface Behavior {
* Called when this behavior becomes inactive.
* <p/>
* Use this to remove permanent effects.
*
* @param reason the reason the behavior is being disabled.
*/
void onDisable();
void onDisable(DisableReason reason);
/**
* Called each tick while this behavior is active.

View File

@ -0,0 +1,23 @@
package li.cil.oc.api.nanomachines;
/**
* Enum with reasons why a nanomachine behavior was disabled.
* <p/>
* This allows some more context specific behavior in a more stable fashion.
*/
public enum DisableReason {
/**
* This covers things like players logging off or the controller being reset.
*/
Default,
/**
* Input state changed, leading to a behavior being disabled.
*/
InputChanged,
/**
* System has run out of energy and is powering down.
*/
OutOfEnergy
}

View File

@ -0,0 +1,52 @@
package li.cil.oc.api.prefab;
import li.cil.oc.api.nanomachines.Behavior;
import li.cil.oc.api.nanomachines.DisableReason;
import net.minecraft.entity.player.EntityPlayer;
/**
* Base class for behaviors, mostly useful to have less cluttered classes when
* you only need one or two of the methods in the interface.
* <p/>
* This implementation will also store the player the behavior was created for.
*/
public abstract class AbstractBehavior implements Behavior {
/**
* The player this behavior was created for.
*/
public final EntityPlayer player;
/**
* Pass along the player the behavior was created for here to have it stored
* for later use.
*
* @param player the player the behavior was created for.
*/
protected AbstractBehavior(EntityPlayer player) {
this.player = player;
}
/**
* Use this if you do not need the player reference in your implementation.
*/
protected AbstractBehavior() {
this(null);
}
@Override
public String getNameHint() {
return null;
}
@Override
public void onEnable() {
}
@Override
public void onDisable(DisableReason reason) {
}
@Override
public void update() {
}
}

View File

@ -0,0 +1,74 @@
package li.cil.oc.api.prefab;
import li.cil.oc.api.nanomachines.Behavior;
import li.cil.oc.api.nanomachines.BehaviorProvider;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
/**
* Example base implementation of nanomachine behavior provider.
* <p/>
* This class takes care of handling the unique identifier used to tell
* if a behavior is its own when loading from NBT.
*/
public abstract class AbstractProvider implements BehaviorProvider {
/**
* Unique identifier used to tell if a behavior is ours when asked to load it.
*/
protected final String id;
/**
* For the ID passed in here, it is suggested to use a one-time generated
* UUID that is hard-coded into your provider implementation. Take care to
* use a different one for each provider you create!
*
* @param id the unique identifier for this provider.
*/
protected AbstractProvider(String id) {
if (id == null) throw new NullPointerException("id must not be null");
this.id = id;
}
/**
* Called when saving a behavior created using this behavior to NBT.
* <p/>
* The ID will already have been written, don't overwrite it. Store
* any additional data you need to restore the behavior here, if any.
*
* @param behavior the behavior to persist.
* @param nbt the NBT tag to persist it to.
*/
protected void writeBehaviorToNBT(Behavior behavior, NBTTagCompound nbt) {
}
/**
* Called when loading a behavior from NBT.
* <p/>
* Use the data written in {@link #writeBehaviorToNBT} to restore the behavior
* to its previous state, then return it.
*
* @param player the player to restore the behavior for.
* @param nbt the NBT tag to load restore the behavior from.
* @return the restored behavior.
*/
protected abstract Behavior readBehaviorFromNBT(EntityPlayer player, NBTTagCompound nbt);
// ----------------------------------------------------------------------- //
@Override
public NBTTagCompound writeToNBT(Behavior behavior) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setString("provider", id);
writeBehaviorToNBT(behavior, nbt);
return nbt;
}
@Override
public Behavior readFromNBT(EntityPlayer player, NBTTagCompound nbt) {
if (id.equals(nbt.getString("provider"))) {
return readBehaviorFromNBT(player, nbt);
} else {
return null;
}
}
}

View File

@ -1023,16 +1023,40 @@ opencomputers {
# Radius in blocks of the disintegration behavior for each active input.
disintegrationRange: 1
# Blacklisted potions, i.e. potions that won't be used for the potion
# Whitelisted potions, i.e. potions that will be used for the potion
# behaviors nanomachines may trigger. This can contain strings or numbers.
# In the case of strings, it has to be the internal name of the potion,
# in case of a number it has to be the potion ID.
potionBlacklist: [
"potion.heal",
"potion.regeneration",
"potion.invisibility",
"potion.saturation"
# in case of a number it has to be the potion ID. Add any potion effects
# to make use of here, since they will all be disabled by default.
potionWhitelist: [
"potion.moveSpeed",
"potion.digSpeed",
"potion.damageBoost",
"potion.jump",
"potion.resistance",
"potion.fireResistance",
"potion.waterBreathing",
"potion.nightVision",
"potion.absorption",
"potion.blindness",
"potion.confusion",
"potion.digSlowDown",
"potion.harm",
"potion.hunger",
"potion.moveSlowdown",
"potion.poison",
"potion.weakness",
"potion.wither"
]
# How much damage the hungry behavior should deal to the player when the
# nanomachine controller runs out of energy.
hungryDamage: 5
# How much energy the hungry behavior should restore when damaging the
# player.
hungryEnergyRestored: 50
}
# 3D printer related stuff.

View File

@ -451,6 +451,15 @@ achievement.oc.transistor.desc=Create a Transistor to get started. Then listen t
achievement.oc.wirelessNetworkCard=Signals
achievement.oc.wirelessNetworkCard.desc=Time to go where no packet has gone before.
# Death messages. Note that the number of entries here must match the number
# set in the actual damage source in code.
death.attack.oc.nanomachinesOverload.1=%s got too greedy.
death.attack.oc.nanomachinesOverload.2=%s had a nervous breakdown.
death.attack.oc.nanomachinesOverload.3=%s's nanomachines went out of control.
death.attack.oc.nanomachinesHungry.1=%s was eaten by nanomachines.
death.attack.oc.nanomachinesHungry.2=%s didn't keep their nanomachines fed.
death.attack.oc.nanomachinesHungry.3=%s has been digested.
# NEI Integration
nei.options.inventory.oredict=Show OreDictionary names
nei.options.inventory.oredict.true=True

View File

@ -361,6 +361,9 @@ class Settings(val config: Config) {
val nanomachineMagnetRange = config.getDouble("nanomachines.magnetRange") max 0
val nanomachineDisintegrationRange = config.getInt("nanomachines.disintegrationRange") max 0
val nanomachinePotionBlacklist = config.getAnyRefList("nanomachines.potionBlacklist")
val nanomachinePotionWhitelist = config.getAnyRefList("nanomachines.potionWhitelist")
val nanomachinesHungryDamage = config.getDouble("nanomachines.hungryDamage").toFloat max 0
val nanomachinesHungryEnergyRestored = config.getDouble("nanomachines.hungryEnergyRestored") max 0
// ----------------------------------------------------------------------- //
// printer

View File

@ -13,7 +13,7 @@ import li.cil.oc.client.renderer.entity.DroneRenderer
import li.cil.oc.client.renderer.tileentity._
import li.cil.oc.common.component.TextBuffer
import li.cil.oc.common.entity.Drone
import li.cil.oc.common.event.NanomachinesEventHandler
import li.cil.oc.common.event.NanomachinesHandler
import li.cil.oc.common.init.Items
import li.cil.oc.common.item.traits.Delegate
import li.cil.oc.common.tileentity
@ -81,7 +81,7 @@ private[oc] class Proxy extends CommonProxy {
ClientRegistry.registerKeyBinding(KeyBindings.clipboardPaste)
MinecraftForge.EVENT_BUS.register(HighlightRenderer)
MinecraftForge.EVENT_BUS.register(NanomachinesEventHandler.Client)
MinecraftForge.EVENT_BUS.register(NanomachinesHandler.Client)
MinecraftForge.EVENT_BUS.register(PetRenderer)
MinecraftForge.EVENT_BUS.register(ServerRack)
MinecraftForge.EVENT_BUS.register(Sound)

View File

@ -8,6 +8,7 @@ import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.nanomachines.Controller
import li.cil.oc.client.Textures
import li.cil.oc.common.EventHandler
import li.cil.oc.common.nanomachines.ControllerImpl
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.ScaledResolution
@ -19,8 +20,9 @@ import net.minecraftforge.client.event.RenderGameOverlayEvent
import net.minecraftforge.event.entity.living.LivingEvent
import net.minecraftforge.event.entity.player.PlayerEvent
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedOutEvent
object NanomachinesEventHandler {
object NanomachinesHandler {
object Client {
@SubscribeEvent
@ -141,6 +143,16 @@ object NanomachinesEventHandler {
}
}
}
@SubscribeEvent
def onPlayerDisconnect(e: PlayerLoggedOutEvent): Unit = {
api.Nanomachines.getController(e.player) match {
case controller: ControllerImpl =>
// Wait a tick because saving is done after this event.
EventHandler.schedule(() => api.Nanomachines.uninstallController(e.player))
case _ => // Not a player with nanomachines.
}
}
}
}

View File

@ -3,10 +3,13 @@ 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.EnumRarity
import net.minecraft.item.ItemStack
import net.minecraft.world.World
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))

View File

@ -9,8 +9,10 @@ import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.nanomachines.Behavior
import li.cil.oc.api.nanomachines.Controller
import li.cil.oc.api.nanomachines.DisableReason
import li.cil.oc.api.network.Packet
import li.cil.oc.api.network.WirelessEndpoint
import li.cil.oc.integration.util.DamageSourceWithRandomCause
import li.cil.oc.server.PacketSender
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedNBT._
@ -33,6 +35,10 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
final val MaxSenderDistance = 2f
final val FullSyncInterval = 20 * 60
final val OverloadDamage = new DamageSourceWithRandomCause("oc.nanomachinesOverload", 3).
setDamageBypassesArmor().
setDamageIsAbsolute()
var uuid = UUID.randomUUID.toString
var responsePort = 0
var storedEnergy = Settings.get.bufferNanomachines * 0.25
@ -52,7 +58,7 @@ 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) {
if (getLocalBuffer > 0 && !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 {
@ -155,7 +161,7 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
}
override def getActiveBehaviors: lang.Iterable[Behavior] = configuration.synchronized {
cleanActiveBehaviors()
cleanActiveBehaviors(DisableReason.InputChanged)
activeBehaviors
}
@ -180,6 +186,10 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
// ----------------------------------------------------------------------- //
def update(): Unit = {
if (player.isDead) {
return
}
if (isServer) {
api.Network.updateWirelessNetwork(this)
}
@ -189,12 +199,15 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
return
}
val hasPower = getLocalBuffer > 0 || Settings.get.ignorePower
var hasPower = getLocalBuffer > 0 || Settings.get.ignorePower
lazy val active = getActiveBehaviors.toIterable // Wrap once.
lazy val activeInputs = configuration.triggers.count(_.isActive)
if (hasPower != hadPower) {
if (!hasPower) active.foreach(_.onDisable())
if (!hasPower) {
active.foreach(_.onDisable(DisableReason.OutOfEnergy)) // This may change our energy buffer.
hasPower = getLocalBuffer > 0 || Settings.get.ignorePower
}
else active.foreach(_.onEnable())
}
@ -209,8 +222,7 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
val overload = activeInputs - getSafeInputCount
if (!player.capabilities.isCreativeMode && overload > 0 && player.getEntityWorld.getTotalWorldTime % 20 == 0) {
player.setHealth(player.getHealth - overload)
player.performHurtAnimation()
player.attackEntityFrom(OverloadDamage, overload)
}
}
@ -246,6 +258,7 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
configuration.triggers(index).isActive = false
activeBehaviorsDirty = true
}
cleanActiveBehaviors(DisableReason.Default)
}
}
@ -253,7 +266,6 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
reset()
if (isServer) {
api.Network.leaveWirelessNetwork(this)
PacketSender.sendNanomachineConfiguration(player)
}
}
@ -280,7 +292,7 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
private def isServer = !isClient
private def cleanActiveBehaviors(): Unit = {
private def cleanActiveBehaviors(reason: DisableReason): Unit = {
if (activeBehaviorsDirty) {
configuration.synchronized(if (activeBehaviorsDirty) {
val newBehaviors = configuration.behaviors.filter(_.isActive).map(_.behavior)
@ -290,7 +302,7 @@ class ControllerImpl(val player: EntityPlayer) extends Controller with WirelessE
activeBehaviors ++= newBehaviors
activeBehaviorsDirty = false
addedBehaviors.foreach(_.onEnable())
removedBehaviors.foreach(_.onDisable())
removedBehaviors.foreach(_.onDisable(reason))
if (isServer) {
PacketSender.sendNanomachineInputs(player)

View File

@ -4,6 +4,7 @@ import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.nanomachines.BehaviorProvider
import li.cil.oc.api.nanomachines.Controller
import li.cil.oc.server.PacketSender
import li.cil.oc.util.PlayerUtils
import net.minecraft.entity.player.EntityPlayer
@ -41,9 +42,12 @@ object Nanomachines extends api.detail.NanomachinesAPI {
override def uninstallController(player: EntityPlayer): Unit = {
getController(player) match {
case controller: ControllerImpl =>
PlayerUtils.persistedData(player).removeTag(Settings.namespace + "hasNanomachines")
controllers(player) -= player
controller.dispose()
controllers(player) -= player
PlayerUtils.persistedData(player).removeTag(Settings.namespace + "hasNanomachines")
if (!player.getEntityWorld.isRemote) {
PacketSender.sendNanomachineConfiguration(player)
}
case _ => // Doesn't have one anyway.
}
}

View File

@ -55,8 +55,8 @@ class NeuralNetwork(controller: ControllerImpl) extends Persistable {
val rng = new Random(controller.player.getEntityWorld.rand.nextInt())
def connect[Sink <: ConnectorNeuron, Source <: Neuron](sinks: Iterable[Sink], sources: mutable.ArrayBuffer[Source]): Unit = {
val sinkPool = sinks.toBuffer
rng.shuffle(sinkPool)
// Shuffle sink list to give each entry the same chance.
val sinkPool = rng.shuffle(sinks.toBuffer)
for (sink <- sinkPool if sources.nonEmpty) {
for (n <- 0 to rng.nextInt(Settings.get.nanomachineMaxInputs) if sources.nonEmpty) {
val sourceIndex = rng.nextInt(sources.length)
@ -65,10 +65,6 @@ class NeuralNetwork(controller: ControllerImpl) extends Persistable {
}
}
// Shuffle behavior and connector list to give each entry the same chance.
rng.shuffle(connectors)
rng.shuffle(behaviors)
// Connect connectors to triggers, then behaviors to connectors and/or remaining triggers.
val sourcePool = mutable.ArrayBuffer.fill(Settings.get.nanomachineMaxOutputs)(triggers.map(_.asInstanceOf[Neuron])).flatten
connect(connectors, sourcePool)

View File

@ -1,7 +1,10 @@
package li.cil.oc.common.nanomachines.provider
import li.cil.oc.Settings
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.nanomachines.DisableReason
import li.cil.oc.api.prefab.AbstractBehavior
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
import net.minecraft.block.Block
@ -17,20 +20,18 @@ import net.minecraftforge.fml.common.eventhandler.Event
import scala.collection.mutable
object DisintegrationProvider extends SimpleProvider {
final val Id = "c4e7e3c2-8069-4fbb-b08e-74b1bddcdfe7"
object DisintegrationProvider extends ScalaProvider("c4e7e3c2-8069-4fbb-b08e-74b1bddcdfe7") {
override def createScalaBehaviors(player: EntityPlayer) = Iterable(new DisintegrationBehavior(player))
override def doCreateBehaviors(player: EntityPlayer) = Iterable(new DisintegrationBehavior(player))
override def readBehaviorFromNBT(player: EntityPlayer, nbt: NBTTagCompound) = new DisintegrationBehavior(player)
override def doReadFromNBT(player: EntityPlayer, nbt: NBTTagCompound) = new DisintegrationBehavior(player)
class DisintegrationBehavior(player: EntityPlayer) extends SimpleBehavior(player) {
class DisintegrationBehavior(player: EntityPlayer) extends AbstractBehavior(player) {
var breakingMap = mutable.Map.empty[BlockPosition, SlowBreakInfo]
var breakingMapNew = mutable.Map.empty[BlockPosition, SlowBreakInfo]
// Note: intentionally not overriding getNameHint. Gotta find this one manually!
override def onDisable(): Unit = {
override def onDisable(reason: DisableReason): Unit = {
val world = player.getEntityWorld
for (pos <- breakingMap.keys) {
world.destroyBlockInWorldPartially(pos.hashCode(), pos, -1)

View File

@ -0,0 +1,32 @@
package li.cil.oc.common.nanomachines.provider
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.nanomachines.Behavior
import li.cil.oc.api.nanomachines.DisableReason
import li.cil.oc.api.prefab.AbstractBehavior
import li.cil.oc.integration.util.DamageSourceWithRandomCause
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
object HungryProvider extends ScalaProvider("") {
final val FillCount = 10 // Create a bunch of these to have a higher chance of one being picked / available.
final val HungryDamage = new DamageSourceWithRandomCause("oc.nanomachinesHungry", 3).
setDamageBypassesArmor().
setDamageIsAbsolute()
override def createScalaBehaviors(player: EntityPlayer): Iterable[Behavior] = Iterable.fill(FillCount)(new HungryBehavior(player))
override protected def readBehaviorFromNBT(player: EntityPlayer, nbt: NBTTagCompound): Behavior = new HungryBehavior(player)
class HungryBehavior(player: EntityPlayer) extends AbstractBehavior(player) {
override def onDisable(reason: DisableReason): Unit = {
if (reason == DisableReason.OutOfEnergy) {
player.attackEntityFrom(HungryDamage, Settings.get.nanomachinesHungryDamage)
api.Nanomachines.getController(player).changeBuffer(Settings.get.nanomachinesHungryEnergyRestored)
}
}
}
}

View File

@ -2,6 +2,7 @@ package li.cil.oc.common.nanomachines.provider
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.prefab.AbstractBehavior
import net.minecraft.entity.item.EntityItem
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
@ -9,15 +10,12 @@ import net.minecraft.util.Vec3
import scala.collection.convert.WrapAsScala._
object MagnetProvider extends SimpleProvider {
// One-time generated UUID to identify our behaviors.
final val Id = "9324d5ec-71f1-41c2-b51c-406e527668fc"
object MagnetProvider extends ScalaProvider("9324d5ec-71f1-41c2-b51c-406e527668fc") {
override def createScalaBehaviors(player: EntityPlayer) = Iterable(new MagnetBehavior(player))
override def doCreateBehaviors(player: EntityPlayer) = Iterable(new MagnetBehavior(player))
override def readBehaviorFromNBT(player: EntityPlayer, nbt: NBTTagCompound) = new MagnetBehavior(player)
override def doReadFromNBT(player: EntityPlayer, nbt: NBTTagCompound) = new MagnetBehavior(player)
class MagnetBehavior(player: EntityPlayer) extends SimpleBehavior(player) {
class MagnetBehavior(player: EntityPlayer) extends AbstractBehavior(player) {
override def getNameHint = "magnet"
override def update(): Unit = {

View File

@ -2,14 +2,13 @@ package li.cil.oc.common.nanomachines.provider
import li.cil.oc.api
import li.cil.oc.api.nanomachines.Behavior
import li.cil.oc.api.prefab.AbstractBehavior
import li.cil.oc.util.PlayerUtils
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.EnumParticleTypes
object ParticleProvider extends SimpleProvider {
final val Id = "b48c4bbd-51bb-4915-9367-16cff3220e4b"
object ParticleProvider extends ScalaProvider("b48c4bbd-51bb-4915-9367-16cff3220e4b") {
final val ParticleTypes = Array(
EnumParticleTypes.FIREWORKS_SPARK,
EnumParticleTypes.TOWN_AURA,
@ -26,9 +25,9 @@ object ParticleProvider extends SimpleProvider {
EnumParticleTypes.VILLAGER_HAPPY
)
override def doCreateBehaviors(player: EntityPlayer): Iterable[Behavior] = ParticleTypes.map(new ParticleBehavior(_, player))
override def createScalaBehaviors(player: EntityPlayer): Iterable[Behavior] = ParticleTypes.map(new ParticleBehavior(_, player))
override def doWriteToNBT(behavior: Behavior, nbt: NBTTagCompound): Unit = {
override def writeBehaviorToNBT(behavior: Behavior, nbt: NBTTagCompound): Unit = {
behavior match {
case particles: ParticleBehavior =>
nbt.setInteger("effectName", particles.effectType.getParticleID)
@ -36,12 +35,12 @@ object ParticleProvider extends SimpleProvider {
}
}
override def doReadFromNBT(player: EntityPlayer, nbt: NBTTagCompound): Behavior = {
override def readBehaviorFromNBT(player: EntityPlayer, nbt: NBTTagCompound): Behavior = {
val effectType = EnumParticleTypes.getParticleFromId(nbt.getInteger("effectName"))
new ParticleBehavior(effectType, player)
}
class ParticleBehavior(var effectType: EnumParticleTypes, player: EntityPlayer) extends SimpleBehavior(player) {
class ParticleBehavior(var effectType: EnumParticleTypes, player: EntityPlayer) extends AbstractBehavior(player) {
override def getNameHint = "particles"
override def update(): Unit = {

View File

@ -3,6 +3,8 @@ package li.cil.oc.common.nanomachines.provider
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.nanomachines.Behavior
import li.cil.oc.api.nanomachines.DisableReason
import li.cil.oc.api.prefab.AbstractBehavior
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.potion.Potion
@ -10,23 +12,27 @@ import net.minecraft.potion.PotionEffect
import scala.collection.convert.WrapAsScala._
object PotionProvider extends SimpleProvider {
final val Id = "c29e4eec-5a46-479a-9b3d-ad0f06da784a"
object PotionProvider extends ScalaProvider("c29e4eec-5a46-479a-9b3d-ad0f06da784a") {
// Lazy to give other mods a chance to register their potions.
lazy val PotionBlacklist = Settings.get.nanomachinePotionBlacklist.map {
case name: String => Potion.potionTypes.find(p => p != null && p.getName == name)
case id: java.lang.Number if id.intValue() >= 0 && id.intValue() < Potion.potionTypes.length => Option(Potion.potionTypes(id.intValue()))
case _ => None
}.collect {
case Some(potion) => potion
}.toSet
lazy val PotionWhitelist = filterPotions(Settings.get.nanomachinePotionWhitelist)
override def doCreateBehaviors(player: EntityPlayer) = {
Potion.potionTypes.filter(_ != null).filterNot(PotionBlacklist.contains).map(new PotionBehavior(_, player))
def filterPotions[T](list: Iterable[T]) = {
list.map {
case name: String => Potion.potionTypes.find(p => p != null && p.getName == name)
case id: java.lang.Number if id.intValue() >= 0 && id.intValue() < Potion.potionTypes.length => Option(Potion.potionTypes(id.intValue()))
case _ => None
}.collect {
case Some(potion) => potion
}.toSet
}
override def doWriteToNBT(behavior: Behavior, nbt: NBTTagCompound): Unit = {
def isPotionEligible(potion: Potion) = potion != null && PotionWhitelist.contains(potion)
override def createScalaBehaviors(player: EntityPlayer) = {
Potion.potionTypes.filter(isPotionEligible).map(new PotionBehavior(_, player))
}
override def writeBehaviorToNBT(behavior: Behavior, nbt: NBTTagCompound): Unit = {
behavior match {
case potionBehavior: PotionBehavior =>
nbt.setInteger("potionId", potionBehavior.potion.id)
@ -34,21 +40,19 @@ object PotionProvider extends SimpleProvider {
}
}
override def doReadFromNBT(player: EntityPlayer, nbt: NBTTagCompound) = {
override def readBehaviorFromNBT(player: EntityPlayer, nbt: NBTTagCompound) = {
val potionId = nbt.getInteger("potionId")
new PotionBehavior(Potion.potionTypes(potionId), player)
}
class PotionBehavior(val potion: Potion, player: EntityPlayer) extends SimpleBehavior(player) {
class PotionBehavior(val potion: Potion, player: EntityPlayer) extends AbstractBehavior(player) {
final val Duration = 600
def amplifier(player: EntityPlayer) = api.Nanomachines.getController(player).getInputCount(this) - 1
override def getNameHint: String = potion.getName.stripPrefix("potion.")
override def onEnable(): Unit = {}
override def onDisable(): Unit = {
override def onDisable(reason: DisableReason): Unit = {
player.removePotionEffect(potion.id)
}

View File

@ -0,0 +1,13 @@
package li.cil.oc.common.nanomachines.provider
import li.cil.oc.api.nanomachines.Behavior
import li.cil.oc.api.prefab.AbstractProvider
import net.minecraft.entity.player.EntityPlayer
import scala.collection.convert.WrapAsJava._
abstract class ScalaProvider(id: String) extends AbstractProvider(id) {
def createScalaBehaviors(player: EntityPlayer): Iterable[Behavior]
override def createBehaviors(player: EntityPlayer): java.lang.Iterable[Behavior] = asJavaIterable(createScalaBehaviors(player))
}

View File

@ -1,14 +0,0 @@
package li.cil.oc.common.nanomachines.provider
import li.cil.oc.api.nanomachines.Behavior
import net.minecraft.entity.player.EntityPlayer
class SimpleBehavior(val player: EntityPlayer) extends Behavior {
override def getNameHint: String = null
override def onEnable(): Unit = {}
override def onDisable(): Unit = {}
override def update(): Unit = {}
}

View File

@ -1,35 +0,0 @@
package li.cil.oc.common.nanomachines.provider
import li.cil.oc.api.nanomachines.Behavior
import li.cil.oc.api.nanomachines.BehaviorProvider
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
import scala.collection.convert.WrapAsJava._
abstract class SimpleProvider extends BehaviorProvider {
// One-time generated UUID to identify our behaviors.
def Id: String
def doCreateBehaviors(player: EntityPlayer): Iterable[Behavior]
def doWriteToNBT(behavior: Behavior, nbt: NBTTagCompound): Unit = {}
def doReadFromNBT(player: EntityPlayer, nbt: NBTTagCompound): Behavior
override def createBehaviors(player: EntityPlayer): java.lang.Iterable[Behavior] = asJavaIterable(doCreateBehaviors(player))
override def writeToNBT(behavior: Behavior): NBTTagCompound = {
val nbt = new NBTTagCompound()
nbt.setString("provider", Id)
doWriteToNBT(behavior: Behavior, nbt: NBTTagCompound)
nbt
}
override def readFromNBT(player: EntityPlayer, nbt: NBTTagCompound): Behavior = {
if (nbt.getString("provider") == Id) {
doReadFromNBT(player, nbt)
}
else null
}
}

View File

@ -28,6 +28,7 @@ import li.cil.oc.common.item.Delegator
import li.cil.oc.common.item.RedstoneCard
import li.cil.oc.common.item.Tablet
import li.cil.oc.common.nanomachines.provider.DisintegrationProvider
import li.cil.oc.common.nanomachines.provider.HungryProvider
import li.cil.oc.common.nanomachines.provider.MagnetProvider
import li.cil.oc.common.nanomachines.provider.ParticleProvider
import li.cil.oc.common.nanomachines.provider.PotionProvider
@ -72,6 +73,7 @@ object ModOpenComputers extends ModProxy {
ForgeChunkManager.setForcedChunkLoadingCallback(OpenComputers, ChunkloaderUpgradeHandler)
FMLCommonHandler.instance.bus.register(EventHandler)
FMLCommonHandler.instance.bus.register(NanomachinesHandler.Common)
FMLCommonHandler.instance.bus.register(SimpleComponentTickHandler.Instance)
FMLCommonHandler.instance.bus.register(Tablet)
@ -84,7 +86,7 @@ object ModOpenComputers extends ModProxy {
MinecraftForge.EVENT_BUS.register(GeolyzerHandler)
MinecraftForge.EVENT_BUS.register(HoverBootsHandler)
MinecraftForge.EVENT_BUS.register(Loot)
MinecraftForge.EVENT_BUS.register(NanomachinesEventHandler.Common)
MinecraftForge.EVENT_BUS.register(NanomachinesHandler.Common)
MinecraftForge.EVENT_BUS.register(RobotCommonHandler)
MinecraftForge.EVENT_BUS.register(SaveHandler)
MinecraftForge.EVENT_BUS.register(Tablet)
@ -253,6 +255,7 @@ object ModOpenComputers extends ModProxy {
api.Manual.addTab(new ItemStackTabIconRenderer(api.Items.get("cpu1").createItemStack(1)), "oc:gui.Manual.Items", "%LANGUAGE%/item/index.md")
api.Nanomachines.addProvider(DisintegrationProvider)
api.Nanomachines.addProvider(HungryProvider)
api.Nanomachines.addProvider(ParticleProvider)
api.Nanomachines.addProvider(PotionProvider)
api.Nanomachines.addProvider(MagnetProvider)

View File

@ -0,0 +1,19 @@
package li.cil.oc.integration.util
import net.minecraft.entity.EntityLivingBase
import net.minecraft.util.ChatComponentTranslation
import net.minecraft.util.DamageSource
import net.minecraft.util.IChatComponent
import net.minecraft.util.StatCollector
class DamageSourceWithRandomCause(name: String, numCauses: Int) extends DamageSource(name) {
override def getDeathMessage(damagee: EntityLivingBase): IChatComponent = {
val damager = damagee.func_94060_bK
val format = "death.attack." + damageType + "." + (damagee.worldObj.rand.nextInt(numCauses) + 1)
val withCauseFormat = format + ".player"
if (damager != null && StatCollector.canTranslate(withCauseFormat))
new ChatComponentTranslation(withCauseFormat, damagee.getDisplayName, damager.getDisplayName)
else
new ChatComponentTranslation(format, damagee.getDisplayName)
}
}