Skip to content

Commit

Permalink
Merge branch 'master-MC1.7.10' into master-MC1.12
Browse files Browse the repository at this point in the history
  • Loading branch information
asiekierka committed Aug 27, 2022
2 parents b823414 + 352e756 commit 0b5de85
Show file tree
Hide file tree
Showing 13 changed files with 99 additions and 42 deletions.
9 changes: 9 additions & 0 deletions src/main/java/li/cil/oc/api/machine/MachineHost.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,13 @@ public interface MachineHost extends EnvironmentHost {
* @param node the node that was disconnected from the network.
*/
void onMachineDisconnect(Node node);

/** Helper method for printing the machine position in error messages and debug statements. */
default String machinePosition()
{
if (world() != null && world().provider != null)
return String.format("(%g, %g, %g, %d)", xPosition(), yPosition(), zPosition(), world().provider.getDimension());
else
return String.format("(%g, %g, %g)", xPosition(), yPosition(), zPosition());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,5 @@ if #args == 0 then
end
else
-- execute command.
return sh.execute(...)
return sh.execute(_ENV, ...)
end
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ function shell.execute(command, env, ...)
if not sh then
return false, reason
end
local proc = process.load(sh, nil, nil, command)
local result = table.pack(process.internal.continue(proc, env, command, ...))
local proc = process.load(sh, env, nil, command)
local result = table.pack(process.internal.continue(proc, command, ...))
if result.n == 0 then return true end
return table.unpack(result, 1, result.n)
end
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/assets/opencomputers/robot.names
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Claptrap # Borderlands
Codsworth # Fallout 4
Continuity # Mona Lisa Overdrive
Cortana # Halo
Crow # Mystery Science Theater 3000
Crypto # Kodos
Curiosity # Mars Rover
Daedalus # Deus Ex
Expand All @@ -60,6 +61,7 @@ Ghost # I, Robot quote "There have always been ghosts in the machin
GLaDOS # Portal
Gipsy Danger # Pacific Rim
G.U.N.T.E.R. # Lost in Space
Gypsy # Mystery Science Theater 3000
HAL 9000 # Space Odyssey
Harbinger # Mass Effect
Harkness # Fallout 3
Expand Down Expand Up @@ -117,6 +119,7 @@ T-1000 # Terminator
Tachikoma # Ghost in the Shell
TARA UH # Perry Rhodan
Terminator # Terminator
Tom Servo # Mystery Science Theater 3000
Rinzler # Tron
Twiki # Buck Rodgers
Uniblab # The Jetsons
Expand All @@ -132,3 +135,4 @@ Wheatley # Portal
Wintermute # Neuromancer
Wobbo # Contributor
Yui-MHCP001 # AKA Yui (Mental Health Counseling Program 001) - Sword Art Online
Zone of Endless # Ace Combat series
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ trait NetworkControl[AETile >: Null <: TileEntity with IActionHost with IGridHos
case (key, value) => hash += key -> value
}
hash.update("isCraftable", Boolean.box(aeItem.isCraftable))
hash.update("size", Int.box(aeItem.getStackSize.toInt))
hash.update("size", Long.box(aeItem.getStackSize))
hash
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ class DiskDriveMountable(val rack: api.internal.Rack, val slot: Int) extends Abs
else result(false)
}

@Callback(doc = "function(): string -- Return the internal floppy disk address")
def media(context: Context, args: Arguments): Array[AnyRef] = {
if (filesystemNode.isEmpty)
result(Unit, "drive is empty")
else
result(filesystemNode.head.address)
}

// ----------------------------------------------------------------------- //
// Analyzable

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ trait InventoryWorldControl extends InventoryAware with WorldAware with SideRest
val stack = inventory.getStackInSlot(selectedSlot)
if (!stack.isEmpty && stack.getCount > 0) {
val blockPos = position.offset(facing)
InventoryUtils.inventoryAt(blockPos, facing.getOpposite) match {
case Some(inv) if mayInteract(blockPos, facing.getOpposite, inv) =>
if (!InventoryUtils.insertIntoInventory(stack, inv, count)) {
InventoryUtils.inventorySourceAt(blockPos, facing.getOpposite) match {
case Some(inv) if mayInteract(inv) =>
if (!InventoryUtils.insertIntoInventory(stack, inv.inventory, count)) {
// Cannot drop into that inventory.
return result(false, "inventory full")
}
Expand Down Expand Up @@ -103,9 +103,9 @@ trait InventoryWorldControl extends InventoryAware with WorldAware with SideRest
val count = args.optItemCount(1)

val blockPos = position.offset(facing)
var extracted: Int = InventoryUtils.inventoryAt(blockPos, facing.getOpposite) match {
case Some(inventory) => mayInteract(blockPos, facing.getOpposite)
InventoryUtils.extractAnyFromInventory((is, sim) => InventoryUtils.insertIntoInventory(is, InventoryUtils.asItemHandler(this.inventory), slots = Option(insertionSlots), simulate = sim), inventory, count)
var extracted: Int = InventoryUtils.inventorySourceAt(blockPos, facing.getOpposite) match {
case Some(inventory) => mayInteract(inventory)
InventoryUtils.extractAnyFromInventory((is, sim) => InventoryUtils.insertIntoInventory(is, InventoryUtils.asItemHandler(this.inventory), slots = Option(insertionSlots), simulate = sim), inventory.inventory, count)
case _ => 0
}
if (extracted <= 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ trait InventoryWorldControlMk2 extends InventoryAware with WorldAware with SideR
}

private def withInventory(blockPos: BlockPosition, fromSide: EnumFacing, f: IItemHandler => Array[AnyRef]) =
InventoryUtils.inventoryAt(blockPos, fromSide) match {
case Some(inventory) if mayInteract(blockPos, fromSide) => f(inventory)
InventoryUtils.inventorySourceAt(blockPos, fromSide) match {
case Some(inventory) if mayInteract(inventory) => f(inventory.inventory)
case _ => result(Unit, "no inventory")
}
}
25 changes: 20 additions & 5 deletions src/main/scala/li/cil/oc/server/component/traits/WorldAware.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ package li.cil.oc.server.component.traits

import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.{BlockInventorySource, BlockPosition, EntityInventorySource, InventorySource}
import li.cil.oc.util.ExtendedBlock._
import li.cil.oc.util.ExtendedWorld._
import net.minecraft.entity.Entity
import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.item.EntityMinecart
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.util.EnumFacing
import net.minecraft.util.EnumHand
import net.minecraft.util.{EnumActionResult, EnumFacing, EnumHand}
import net.minecraft.util.math.AxisAlignedBB
import net.minecraft.world.WorldServer
import net.minecraftforge.common.MinecraftForge
Expand All @@ -35,7 +34,7 @@ trait WorldAware {
player
}

def mayInteract(blockPos: BlockPosition, face: EnumFacing): Boolean = {
private def mayInteract(blockPos: BlockPosition, face: EnumFacing): Boolean = {
try {
val event = new PlayerInteractEvent.RightClickBlock(fakePlayer, EnumHand.MAIN_HAND, blockPos.toBlockPos, face, null)
MinecraftForge.EVENT_BUS.post(event)
Expand All @@ -47,9 +46,25 @@ trait WorldAware {
}
}

def mayInteract(blockPos: BlockPosition, side: EnumFacing, inventory: IItemHandler): Boolean = mayInteract(blockPos, side) && (inventory match {
private def mayInteract(entity: Entity): Boolean = {
try {
val event = new PlayerInteractEvent.EntityInteract(fakePlayer, EnumHand.MAIN_HAND, entity)
MinecraftForge.EVENT_BUS.post(event)
!event.isCanceled
} catch {
case t: Throwable =>
OpenComputers.log.warn("Some event handler threw up while checking for permission to access an entity.", t)
true
}
}

def mayInteract(inv: InventorySource): Boolean = (inv.inventory match {
case inv: InvWrapper if inv.getInv != null => inv.getInv.isUsableByPlayer(fakePlayer)
case _ => true
}) && (inv match {
case inv: BlockInventorySource => mayInteract(inv.position, inv.side)
case inv: EntityInventorySource => mayInteract(inv.entity)
case _ => true
})

def entitiesInBounds[Type <: Entity](clazz: Class[Type], bounds: AxisAlignedBB) = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import li.cil.oc.api.machine.Callback
import li.cil.oc.api.machine.Context
import li.cil.oc.api.prefab.ItemStackArrayValue
import li.cil.oc.server.component.result
import li.cil.oc.util.{BlockPosition, DatabaseAccess, InventoryUtils}
import li.cil.oc.util.{BlockInventorySource, BlockPosition, DatabaseAccess, EntityInventorySource, InventorySource, InventoryUtils, StackOption}
import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.ExtendedArguments._
import net.minecraft.block.Block
import li.cil.oc.util.StackOption
import net.minecraft.item.ItemStack
import net.minecraft.util.EnumFacing
import net.minecraftforge.fml.common.registry.EntityRegistry
import net.minecraftforge.items.IItemHandler
import net.minecraftforge.oredict.OreDictionary

Expand Down Expand Up @@ -102,8 +102,12 @@ trait WorldInventoryAnalytics extends WorldAware with SideRestricted with Networ
}
case _ => None
}
withInventory(facing, inventory => blockAt(position.offset(facing)) match {
case Some(block) => result(block.getRegistryName)
withInventorySource(facing, {
case BlockInventorySource(position, _, _) => blockAt(position) match {
case Some(block) => result(block.getRegistryName)
case _ => result(Unit, "Unknown")
}
case EntityInventorySource(entity, _, _) => result(EntityRegistry.getEntry(entity.getClass).getRegistryName)
case _ => result(Unit, "Unknown")
})
}
Expand All @@ -122,9 +126,12 @@ trait WorldInventoryAnalytics extends WorldAware with SideRestricted with Networ
withInventory(facing, inventory => store(inventory.getStackInSlot(args.checkSlot(inventory, 1))))
}

private def withInventory(side: EnumFacing, f: IItemHandler => Array[AnyRef]) =
InventoryUtils.inventoryAt(position.offset(side), side.getOpposite) match {
case Some(inventory) if mayInteract(position.offset(side), side.getOpposite, inventory) => f(inventory)
private def withInventorySource(side: EnumFacing, f: InventorySource => Array[AnyRef]) =
InventoryUtils.inventorySourceAt(position.offset(side), side.getOpposite) match {
case Some(inventory) if mayInteract(inventory) => f(inventory)
case _ => result(Unit, "no inventory")
}

private def withInventory(side: EnumFacing, f: IItemHandler => Array[AnyRef]) =
withInventorySource(side, is => f(is.inventory))
}
4 changes: 2 additions & 2 deletions src/main/scala/li/cil/oc/server/machine/Machine.scala
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ class Machine(val host: MachineHost) extends AbstractManagedEnvironment with mac
catch {
case t: Throwable =>
OpenComputers.log.error(
s"""Unexpected error loading a state of computer at (${host.xPosition}, ${host.yPosition}, ${host.zPosition}). """ +
s"""Unexpected error loading a state of computer at ${host.machinePosition()}. """ +
s"""State: ${state.headOption.fold("no state")(_.toString)}. Unless you're upgrading/downgrading across a major version, please report this! Thank you.""", t)
close()
}
Expand Down Expand Up @@ -882,7 +882,7 @@ class Machine(val host: MachineHost) extends AbstractManagedEnvironment with mac
catch {
case t: Throwable =>
OpenComputers.log.error(
s"""Unexpected error saving a state of computer at (${host.xPosition}, ${host.yPosition}, ${host.zPosition}). """ +
s"""Unexpected error saving a state of computer at ${host.machinePosition()}. """ +
s"""State: ${state.headOption.fold("no state")(_.toString)}. Unless you're upgrading/downgrading across a major version, please report this! Thank you.""", t)
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ abstract class NativeLuaArchitecture(val machine: api.machine.Machine) extends A

try lua.gc(LuaState.GcAction.COLLECT, 0) catch {
case t: Throwable =>
OpenComputers.log.warn(s"Error cleaning up loaded computer @ (${machine.host.xPosition}, ${machine.host.yPosition}, ${machine.host.zPosition}). This either means the server is badly overloaded or a user created an evil __gc method, accidentally or not.")
OpenComputers.log.warn(s"Error cleaning up loaded computer @ ${machine.host().machinePosition()}. This either means the server is badly overloaded or a user created an evil __gc method, accidentally or not.")
machine.crash("error in garbage collector, most likely __gc method timed out")
}
} catch {
Expand Down Expand Up @@ -414,15 +414,15 @@ abstract class NativeLuaArchitecture(val machine: api.machine.Machine) extends A

try lua.gc(LuaState.GcAction.COLLECT, 0) catch {
case t: Throwable =>
OpenComputers.log.warn(s"Error cleaning up loaded computer @ (${machine.host.xPosition}, ${machine.host.yPosition}, ${machine.host.zPosition}). This either means the server is badly overloaded or a user created an evil __gc method, accidentally or not.")
OpenComputers.log.warn(s"Error cleaning up loaded computer @ ${machine.host().machinePosition()}. This either means the server is badly overloaded or a user created an evil __gc method, accidentally or not.")
machine.crash("error in garbage collector, most likely __gc method timed out")
}
} catch {
case e: LuaRuntimeException =>
OpenComputers.log.warn(s"Could not persist computer @ (${machine.host.xPosition}, ${machine.host.yPosition}, ${machine.host.zPosition}).\n${e.toString}" + (if (e.getLuaStackTrace.isEmpty) "" else "\tat " + e.getLuaStackTrace.mkString("\n\tat ")))
OpenComputers.log.warn(s"Could not persist computer @ ${machine.host().machinePosition()}.\n${e.toString}" + (if (e.getLuaStackTrace.isEmpty) "" else "\tat " + e.getLuaStackTrace.mkString("\n\tat ")))
nbt.removeTag("state")
case e: LuaGcMetamethodException =>
OpenComputers.log.warn(s"Could not persist computer @ (${machine.host.xPosition}, ${machine.host.yPosition}, ${machine.host.zPosition}).\n${e.toString}")
OpenComputers.log.warn(s"Could not persist computer @ ${machine.host().machinePosition()}.\n${e.toString}")
nbt.removeTag("state")
}

Expand Down
38 changes: 26 additions & 12 deletions src/main/scala/li/cil/oc/util/InventoryUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,33 +40,40 @@ object InventoryUtils {
(!checkNBT || ItemStack.areItemStackTagsEqual(stackA, stackB))

/**
* Retrieves an actual inventory implementation for a specified world coordinate.
* <br>
* This performs special handling for (double-)chests and also checks for
* mine carts with chests.
* Retrieves an actual inventory implementation for a specified world coordinate,
* complete with a reference to the source of said implementation.
*/
def inventoryAt(position: BlockPosition, side: EnumFacing): Option[IItemHandler] = position.world match {
def inventorySourceAt(position: BlockPosition, side: EnumFacing): Option[InventorySource] = position.world match {
case Some(world) if world.blockExists(position) => world.getTileEntity(position) match {
case tile: TileEntity if tile.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side) => Option(tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side))
case tile: IInventory => Option(asItemHandler(tile, side))
case tile: TileEntity if tile.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side) => Option(BlockInventorySource(position, side, tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side)))
case tile: IInventory => Option(BlockInventorySource(position, side, asItemHandler(tile, side)))
case _ => world.getEntitiesWithinAABB(classOf[Entity], position.bounds)
.filter(e => !e.isDead && e.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side))
.map(_.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side))
.find(_ != null)
.map(a => EntityInventorySource(a, side, a.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side)))
.find(a => a != null && a.inventory != null)
}
case _ => None
}

def anyInventoryAt(position: BlockPosition): Option[IItemHandler] = {
/**
* Retrieves an actual inventory implementation for a specified world coordinate.
*/
def inventoryAt(position: BlockPosition, side: EnumFacing): Option[IItemHandler] = inventorySourceAt(position, side)
.map(a => a.inventory)

def anyInventorySourceAt(position: BlockPosition): Option[InventorySource] = {
for(side <- null :: EnumFacing.VALUES.toList) {
inventoryAt(position, side) match {
case inv: Some[IItemHandler] => return inv
inventorySourceAt(position, side) match {
case inv: Some[InventorySource] => return inv
case _ =>
}
}
None
}

def anyInventoryAt(position: BlockPosition): Option[IItemHandler] = anyInventorySourceAt(position)
.map(a => a.inventory)

/**
* Inserts a stack into an inventory.
* <br>
Expand Down Expand Up @@ -397,3 +404,10 @@ object InventoryUtils {
case _ => null
}
}

sealed trait InventorySource {
def side: EnumFacing
def inventory: IItemHandler
}
final case class BlockInventorySource(position: BlockPosition, side: EnumFacing, inventory: IItemHandler) extends InventorySource
final case class EntityInventorySource(entity: Entity, side: EnumFacing, inventory: IItemHandler) extends InventorySource

0 comments on commit 0b5de85

Please sign in to comment.