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

Conflicts:
	build.properties
This commit is contained in:
Florian Nücke 2015-03-13 19:42:49 +01:00
commit 86811be881
18 changed files with 91 additions and 87 deletions

View File

@ -1,7 +1,7 @@
minecraft.version=1.7.10
forge.version=10.13.2.1236
oc.version=1.5.2
oc.version=1.5.3
oc.subversion=
ae2.version=rv1-stable-1

View File

@ -146,6 +146,7 @@ object Sound {
sources.synchronized(try sources.foreach(_._2.stop()) catch {
case _: Throwable => // Ignore.
})
sources.clear()
}
private abstract class Command(val when: Long, val tileEntity: TileEntity) extends Ordered[Command] {

View File

@ -21,6 +21,7 @@ import li.cil.oc.common.tileentity.Robot
import li.cil.oc.common.tileentity.traits.power
import li.cil.oc.integration.Mods
import li.cil.oc.integration.util
import li.cil.oc.server.component.Keyboard
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util._
import net.minecraft.client.Minecraft
@ -34,6 +35,7 @@ import net.minecraftforge.common.util.ForgeDirection
import net.minecraftforge.event.world.BlockEvent
import net.minecraftforge.event.world.WorldEvent
import scala.collection.convert.WrapAsScala._
import scala.collection.mutable
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
@ -45,10 +47,14 @@ object EventHandler {
private val runningRobots = mutable.Set.empty[Robot]
private val keyboards = java.util.Collections.newSetFromMap[Keyboard](new java.util.WeakHashMap[Keyboard, java.lang.Boolean])
def onRobotStart(robot: Robot): Unit = runningRobots += robot
def onRobotStopped(robot: Robot): Unit = runningRobots -= robot
def addKeyboard(keyboard: Keyboard): Unit = keyboards += keyboard
def schedule(tileEntity: TileEntity) {
if (SideTracker.isServer) pending.synchronized {
pending += (() => Network.joinOrCreateNetwork(tileEntity))
@ -186,6 +192,21 @@ object EventHandler {
}
}
@SubscribeEvent
def onPlayerRespawn(e: PlayerRespawnEvent) {
keyboards.foreach(_.releasePressedKeys(e.player))
}
@SubscribeEvent
def onPlayerChangedDimension(e: PlayerChangedDimensionEvent) {
keyboards.foreach(_.releasePressedKeys(e.player))
}
@SubscribeEvent
def onPlayerLogout(e: PlayerLoggedOutEvent) {
keyboards.foreach(_.releasePressedKeys(e.player))
}
lazy val drone = api.Items.get("drone")
lazy val eeprom = api.Items.get("eeprom")
lazy val mcu = api.Items.get("microcontroller")

View File

@ -168,7 +168,7 @@ object SaveHandler {
val chunk = e.getChunk.getChunkCoordIntPair
val dimPath = new io.File(path, dimension.toString)
val chunkPath = new io.File(dimPath, s"${chunk.chunkXPos}.${chunk.chunkZPos}")
if (chunkPath.exists && chunkPath.isDirectory) {
if (chunkPath.exists && chunkPath.isDirectory && chunkPath.list() != null) {
for (file <- chunkPath.listFiles() if System.currentTimeMillis() - file.lastModified() > TimeToHoldOntoOldSaves) file.delete()
}
saveData.get(dimension) match {
@ -207,7 +207,7 @@ object SaveHandler {
// But that's really not something I'm bothered by, it's a fallback.
def recurse(file: File) {
file.setLastModified(System.currentTimeMillis())
if (file.isDirectory) file.listFiles().foreach(recurse)
if (file.exists() && file.isDirectory && file.list() != null) file.listFiles().foreach(recurse)
}
recurse(statePath)
}

View File

@ -11,10 +11,10 @@ object AngelUpgradeHandler {
@SubscribeEvent
def onPlaceInAir(e: RobotPlaceInAirEvent) {
val machineNode = e.agent.machine.node
machineNode.reachableNodes.exists {
e.setAllowed(machineNode.reachableNodes.exists {
case component: Component if component.canBeSeenFrom(machineNode) =>
component.host.isInstanceOf[UpgradeAngel]
case _ => false
}
})
}
}

View File

@ -7,6 +7,7 @@ import li.cil.oc.api.network.Analyzable
import li.cil.oc.api.network._
import li.cil.oc.common.component.TextBuffer
import li.cil.oc.util.Color
import li.cil.oc.util.ExtendedWorld._
import net.minecraft.client.Minecraft
import net.minecraft.entity.Entity
import net.minecraft.entity.player.EntityPlayer
@ -61,7 +62,7 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
override def canConnect(side: ForgeDirection) = toLocal(side) != ForgeDirection.SOUTH
// Allow connections from front for keyboards, and keyboards only...
override def sidedNode(side: ForgeDirection) = if (toLocal(side) != ForgeDirection.SOUTH || world.getTileEntity(x + side.offsetX, y + side.offsetY, z + side.offsetZ).isInstanceOf[Keyboard]) node else null
override def sidedNode(side: ForgeDirection) = if (toLocal(side) != ForgeDirection.SOUTH || (world.blockExists(position.offset(side)) && world.getTileEntity(position.offset(side)).isInstanceOf[Keyboard])) node else null
// ----------------------------------------------------------------------- //

View File

@ -45,6 +45,9 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledEmitter with IBund
super.isOutputEnabled_=(value)
}
def bundledInput(side: ForgeDirection) =
(_bundledInput(side.ordinal()), _rednetInput(side.ordinal())).zipped.map(math.max)
def bundledInput(side: ForgeDirection, color: Int) =
math.max(_bundledInput(side.ordinal())(color), _rednetInput(side.ordinal())(color))

View File

@ -1,5 +1,6 @@
package li.cil.oc.integration.vanilla;
import cpw.mods.fml.common.eventhandler.Event;
import li.cil.oc.Settings;
import li.cil.oc.api.machine.Arguments;
import li.cil.oc.api.machine.Callback;
@ -7,14 +8,16 @@ import li.cil.oc.api.machine.Context;
import li.cil.oc.api.network.ManagedEnvironment;
import li.cil.oc.api.prefab.DriverTileEntity;
import li.cil.oc.integration.ManagedTileEntityEnvironment;
import li.cil.oc.util.BlockPosition;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.util.FakePlayerFactory;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
public final class DriverInventory extends DriverTileEntity {
@Override
@ -29,12 +32,12 @@ public final class DriverInventory extends DriverTileEntity {
public static final class Environment extends ManagedTileEntityEnvironment<IInventory> {
private final EntityPlayer fakePlayer;
private final Vec3 position;
private final BlockPosition position;
public Environment(final TileEntity tileEntity, final World world) {
super((IInventory) tileEntity, "inventory");
fakePlayer = FakePlayerFactory.get((WorldServer) world, Settings.get().fakePlayerProfile());
position = Vec3.createVectorHelper(tileEntity.xCoord + 0.5, tileEntity.yCoord + 0.5, tileEntity.zCoord + 0.5);
position = BlockPosition.apply(tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord, world);
}
@Callback(doc = "function():string -- Get the name of this inventory.")
@ -172,8 +175,9 @@ public final class DriverInventory extends DriverTileEntity {
private boolean notPermitted() {
synchronized (fakePlayer) {
fakePlayer.setPosition(position.xCoord, position.yCoord, position.zCoord);
return !tileEntity.isUseableByPlayer(fakePlayer);
fakePlayer.setPosition(position.toVec3().xCoord, position.toVec3().yCoord, position.toVec3().zCoord);
final PlayerInteractEvent event = ForgeEventFactory.onPlayerInteract(fakePlayer, PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK, position.x(), position.y(), position.z(), 0, fakePlayer.getEntityWorld());
return !event.isCanceled() && event.useBlock != Event.Result.DENY && !tileEntity.isUseableByPlayer(fakePlayer);
}
}
}

View File

@ -1,21 +1,14 @@
package li.cil.oc.server.component
import cpw.mods.fml.common.FMLCommonHandler
import cpw.mods.fml.common.eventhandler.SubscribeEvent
import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerChangedDimensionEvent
import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerLoggedOutEvent
import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerRespawnEvent
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.Network
import li.cil.oc.api.component.Keyboard.UsabilityChecker
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.network.Message
import li.cil.oc.api.network.Node
import li.cil.oc.api.network.Visibility
import li.cil.oc.api.prefab
import net.minecraft.entity.player.EntityPlayer
import net.minecraftforge.event.world.WorldEvent
import scala.collection.mutable
@ -35,21 +28,6 @@ class Keyboard(val host: EnvironmentHost) extends prefab.ManagedEnvironment with
// ----------------------------------------------------------------------- //
@SubscribeEvent
def onPlayerRespawn(e: PlayerRespawnEvent) {
releasePressedKeys(e.player)
}
@SubscribeEvent
def onPlayerChangedDimension(e: PlayerChangedDimensionEvent) {
releasePressedKeys(e.player)
}
@SubscribeEvent
def onPlayerLogout(e: PlayerLoggedOutEvent) {
releasePressedKeys(e.player)
}
def releasePressedKeys(player: EntityPlayer) {
pressedKeys.get(player) match {
case Some(keys) => for ((code, char) <- keys) {
@ -65,29 +43,8 @@ class Keyboard(val host: EnvironmentHost) extends prefab.ManagedEnvironment with
pressedKeys.remove(player)
}
@SubscribeEvent
def onWorldUnload(e: WorldEvent.Unload) {
try FMLCommonHandler.instance.bus.unregister(this) catch {
case ignore: Throwable =>
}
}
// ----------------------------------------------------------------------- //
override def onConnect(node: Node) {
if (node == this.node) {
FMLCommonHandler.instance.bus.register(this)
}
}
override def onDisconnect(node: Node) {
if (node == this.node) {
try FMLCommonHandler.instance.bus.unregister(this) catch {
case ignore: Throwable =>
}
}
}
override def onMessage(message: Message) = {
message.data match {
case Array(p: EntityPlayer, char: Character, code: Integer) if message.name == "keyboard.keyDown" =>

View File

@ -9,18 +9,22 @@ import li.cil.oc.common.tileentity.traits.BundledRedstoneAware
trait RedstoneBundled extends RedstoneVanilla {
override def redstone: EnvironmentHost with BundledRedstoneAware
@Callback(direct = true, doc = """function(side:number, color:number):number -- Get the bundled redstone input on the specified side and with the specified color.""")
@Callback(direct = true, doc = """function(side:number[, color:number]):number or table -- Get the bundled redstone input on the specified side and with the specified color.""")
def getBundledInput(context: Context, args: Arguments): Array[AnyRef] = {
val side = checkSide(args, 0)
val color = checkColor(args, 1)
result(redstone.bundledInput(side, color))
if (args.optAny(1, null) == null)
result(redstone.bundledInput(side).zipWithIndex.map(_.swap).toMap)
else
result(redstone.bundledInput(side, checkColor(args, 1)))
}
@Callback(direct = true, doc = """function(side:number, color:number):number -- Get the bundled redstone output on the specified side and with the specified color.""")
@Callback(direct = true, doc = """function(side:number[, color:number]):number or table -- Get the bundled redstone output on the specified side and with the specified color.""")
def getBundledOutput(context: Context, args: Arguments): Array[AnyRef] = {
val side = checkSide(args, 0)
val color = checkColor(args, 1)
result(redstone.bundledOutput(side, color))
if (args.optAny(1, null) == null)
result(redstone.bundledOutput(side).zipWithIndex.map(_.swap).toMap)
else
result(redstone.bundledOutput(side, checkColor(args, 1)))
}
@Callback(doc = """function(side:number, color:number, value:number):number -- Set the bundled redstone output on the specified side and with the specified color.""")

View File

@ -36,8 +36,9 @@ trait InventoryWorldControl extends InventoryAware with WorldAware with SideRest
val count = args.optionalItemCount(1)
val stack = inventory.getStackInSlot(selectedSlot)
if (stack != null && stack.stackSize > 0) {
InventoryUtils.inventoryAt(position.offset(facing)) match {
case Some(inv) if inv.isUseableByPlayer(fakePlayer) =>
val blockPos = position.offset(facing)
InventoryUtils.inventoryAt(blockPos) match {
case Some(inv) if inv.isUseableByPlayer(fakePlayer) && mayInteract(blockPos, facing.getOpposite) =>
if (!InventoryUtils.insertIntoInventory(stack, inv, Option(facing.getOpposite), count)) {
// Cannot drop into that inventory.
return result(false, "inventory full")
@ -70,8 +71,9 @@ trait InventoryWorldControl extends InventoryAware with WorldAware with SideRest
val facing = checkSideForAction(args, 0)
val count = args.optionalItemCount(1)
if (InventoryUtils.inventoryAt(position.offset(facing)).exists(inventory => {
inventory.isUseableByPlayer(fakePlayer) && InventoryUtils.extractFromInventory(InventoryUtils.insertIntoInventory(_, this.inventory, slots = Option(insertionSlots)), inventory, facing.getOpposite, count)
val blockPos = position.offset(facing)
if (InventoryUtils.inventoryAt(blockPos).exists(inventory => {
inventory.isUseableByPlayer(fakePlayer) && mayInteract(blockPos, facing.getOpposite) && InventoryUtils.extractFromInventory(InventoryUtils.insertIntoInventory(_, this.inventory, slots = Option(insertionSlots)), inventory, facing.getOpposite, count)
})) {
context.pause(Settings.get.suckDelay)
result(true)

View File

@ -56,7 +56,7 @@ trait InventoryWorldControlMk2 extends InventoryAware with WorldAware with SideR
private def withInventory(side: ForgeDirection, f: IInventory => Array[AnyRef]) =
InventoryUtils.inventoryAt(position.offset(side)) match {
case Some(inventory) if inventory.isUseableByPlayer(fakePlayer) => f(inventory)
case Some(inventory) if inventory.isUseableByPlayer(fakePlayer) && mayInteract(position.offset(side), side.getOpposite) => f(inventory)
case _ => result(Unit, "no inventory")
}
}

View File

@ -1,5 +1,6 @@
package li.cil.oc.server.component.traits
import cpw.mods.fml.common.eventhandler.Event.Result
import li.cil.oc.Settings
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedBlock._
@ -13,6 +14,8 @@ import net.minecraft.world.WorldServer
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.util.FakePlayerFactory
import net.minecraftforge.common.util.ForgeDirection
import net.minecraftforge.event.ForgeEventFactory
import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action
import net.minecraftforge.event.world.BlockEvent
import net.minecraftforge.fluids.FluidRegistry
@ -33,6 +36,11 @@ trait WorldAware {
player
}
def mayInteract(blockPos: BlockPosition, face: ForgeDirection): Boolean = {
val event = ForgeEventFactory.onPlayerInteract(fakePlayer, Action.RIGHT_CLICK_BLOCK, blockPos.x, blockPos.y, blockPos.z, face.ordinal(), world)
!event.isCanceled && event.useBlock != Result.DENY
}
def entitiesInBounds[Type <: Entity : ClassTag](bounds: AxisAlignedBB) = {
world.getEntitiesWithinAABB(classTag[Type].runtimeClass, bounds).map(_.asInstanceOf[Type])
}

View File

@ -66,7 +66,7 @@ trait WorldInventoryAnalytics extends WorldAware with SideRestricted with Networ
private def withInventory(side: ForgeDirection, f: IInventory => Array[AnyRef]) =
InventoryUtils.inventoryAt(position.offset(side)) match {
case Some(inventory) if inventory.isUseableByPlayer(fakePlayer) => f(inventory)
case Some(inventory) if inventory.isUseableByPlayer(fakePlayer) && mayInteract(position.offset(side), side.getOpposite) => f(inventory)
case _ => result(null, "no inventory")
}
}

View File

@ -42,7 +42,7 @@ trait Buffered extends OutputStreamFileSystem {
for (child <- directory.listFiles() if isValidFilename(child.getName)) {
val childPath = path + child.getName
val childFile = new io.File(directory, child.getName)
if (child.isDirectory) {
if (child.exists() && child.isDirectory && child.list() != null) {
recurse(childPath + "/", childFile)
}
else if (!exists(childPath) || !isDirectory(childPath)) {

View File

@ -3,7 +3,7 @@ package li.cil.oc.server.fs
import java.io
trait FileInputStreamFileSystem extends InputStreamFileSystem {
protected val root: io.File
protected def root: io.File
// ----------------------------------------------------------------------- //
@ -36,7 +36,7 @@ trait FileInputStreamFileSystem extends InputStreamFileSystem {
override def list(path: String) = new io.File(root, path) match {
case file if file.exists() && file.isFile => Array(file.getName)
case directory if directory.exists() && directory.isDirectory =>
case directory if directory.exists() && directory.isDirectory && directory.list() != null =>
directory.listFiles().map(file => if (file.isDirectory) file.getName + "/" else file.getName)
case _ => throw new io.FileNotFoundException("no such file or directory")
}

View File

@ -102,13 +102,13 @@ class LuaJLuaArchitecture(val machine: api.machine.Machine) extends Architecture
memory > 0
}
private def memoryInBytes(components: java.lang.Iterable[ItemStack]) = components.foldLeft(0)((acc, stack) => Option(api.Driver.driverFor(stack)) match {
private def memoryInBytes(components: java.lang.Iterable[ItemStack]) = components.foldLeft(0)((acc, stack) => acc + (Option(api.Driver.driverFor(stack)) match {
case Some(driver: Memory) =>
val sizes = Settings.get.ramSizes
val tier = math.round(driver.amount(stack)).toInt - 1
sizes(tier max 0 min (sizes.length - 1)) * 1024
case _ => 0
})
}))
// ----------------------------------------------------------------------- //

View File

@ -100,24 +100,27 @@ object ItemCosts {
}
else {
val recipes = CraftingManager.getInstance.getRecipeList.map(_.asInstanceOf[IRecipe])
val recipe = recipes.find(recipe => recipe.getRecipeOutput != null && fuzzyEquals(stack, recipe.getRecipeOutput))
val (ingredients, output) = recipe match {
case Some(recipe: ShapedRecipes) => (recipe.recipeItems.flatMap(accumulate(_, path :+ stack)).toIterable, recipe.getRecipeOutput.stackSize)
case Some(recipe: ShapelessRecipes) => (recipe.recipeItems.flatMap(accumulate(_, path :+ stack)).toIterable, recipe.getRecipeOutput.stackSize)
case Some(recipe: ShapedOreRecipe) => (recipe.getInput.flatMap(accumulate(_, path :+ stack)).toIterable, recipe.getRecipeOutput.stackSize)
case Some(recipe: ShapelessOreRecipe) => (recipe.getInput.flatMap(accumulate(_, path :+ stack)).toIterable, recipe.getRecipeOutput.stackSize)
case _ => FurnaceRecipes.smelting.getSmeltingList.asInstanceOf[util.Map[ItemStack, ItemStack]].find {
case (_, value) => fuzzyEquals(stack, value)
} match {
case Some((rein, raus)) => (accumulate(rein, path :+ stack), raus.stackSize)
case _ => (Iterable((stack, 1.0)), 1)
if (recipes == null) Iterable((stack, 1.0))
else {
val recipe = recipes.filter(_ != null).find(recipe => recipe.getRecipeOutput != null && fuzzyEquals(stack, recipe.getRecipeOutput))
val (ingredients, output) = recipe match {
case Some(recipe: ShapedRecipes) => (recipe.recipeItems.flatMap(accumulate(_, path :+ stack)).toIterable, recipe.getRecipeOutput.stackSize)
case Some(recipe: ShapelessRecipes) => (recipe.recipeItems.flatMap(accumulate(_, path :+ stack)).toIterable, recipe.getRecipeOutput.stackSize)
case Some(recipe: ShapedOreRecipe) => (recipe.getInput.flatMap(accumulate(_, path :+ stack)).toIterable, recipe.getRecipeOutput.stackSize)
case Some(recipe: ShapelessOreRecipe) => (recipe.getInput.flatMap(accumulate(_, path :+ stack)).toIterable, recipe.getRecipeOutput.stackSize)
case _ => FurnaceRecipes.smelting.getSmeltingList.asInstanceOf[util.Map[ItemStack, ItemStack]].find {
case (_, value) => fuzzyEquals(stack, value)
} match {
case Some((rein, raus)) => (accumulate(rein, path :+ stack), raus.stackSize)
case _ => (Iterable((stack, 1.0)), 1)
}
}
val scaled = deflate(ingredients.map {
case (ingredient, count) => (ingredient.copy(), count / output)
}).toArray.sortBy(_._1.getUnlocalizedName)
cache += new ItemStackWrapper(stack.copy()) -> scaled
scaled
}
val scaled = deflate(ingredients.map {
case (ingredient, count) => (ingredient.copy(), count / output)
}).toArray.sortBy(_._1.getUnlocalizedName)
cache += new ItemStackWrapper(stack.copy()) -> scaled
scaled
}
}
case list: util.ArrayList[ItemStack]@unchecked if !list.isEmpty =>