mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-15 18:30:27 -04:00
showing user list of computers in their analyzer result; some (theoretical) improvements to computer ownership (I really should test this somewhen); reduced range of included players for sending some packets
This commit is contained in:
parent
5ea8d072c0
commit
cbf17609bd
@ -56,6 +56,7 @@ oc:gui.Analyzer.RobotName=Name
|
||||
oc:gui.Analyzer.RobotOwner=Owner
|
||||
oc:gui.Analyzer.StoredEnergy=Stored energy
|
||||
oc:gui.Analyzer.TotalEnergy=Total stored energy
|
||||
oc:gui.Analyzer.Users=Users
|
||||
oc:gui.Robot.Power=Power
|
||||
oc:gui.Robot.TurnOff=Turn off
|
||||
oc:gui.Robot.TurnOn=Turn on
|
||||
|
@ -26,6 +26,7 @@ class PacketHandler extends CommonPacketHandler {
|
||||
case PacketType.Analyze => onAnalyze(p)
|
||||
case PacketType.ChargerState => onChargerState(p)
|
||||
case PacketType.ComputerState => onComputerState(p)
|
||||
case PacketType.ComputerUserList => onComputerUserList(p)
|
||||
case PacketType.PowerState => onPowerState(p)
|
||||
case PacketType.RedstoneState => onRedstoneState(p)
|
||||
case PacketType.RobotAnimateSwing => onRobotAnimateSwing(p)
|
||||
@ -73,6 +74,14 @@ class PacketHandler extends CommonPacketHandler {
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onComputerUserList(p: PacketParser) =
|
||||
p.readTileEntity[Computer]() match {
|
||||
case Some(t) =>
|
||||
val count = p.readInt()
|
||||
t.users = (0 until count).map(_ => p.readUTF())
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onPowerState(p: PacketParser) =
|
||||
p.readTileEntity[PowerInformation]() match {
|
||||
case Some(t) =>
|
||||
|
@ -6,6 +6,7 @@ object PacketType extends Enumeration {
|
||||
Analyze,
|
||||
ChargerState,
|
||||
ComputerState,
|
||||
ComputerUserList,
|
||||
PowerState,
|
||||
RedstoneState,
|
||||
RobotAnimateSwing,
|
||||
|
@ -80,8 +80,7 @@ abstract class Case(val parent: SimpleDelegator) extends Computer with SimpleDel
|
||||
// TODO do we have to manually sync the client since we can only check this on the server side?
|
||||
override def removedByEntity(world: World, x: Int, y: Int, z: Int, player: EntityPlayer) =
|
||||
world.getBlockTileEntity(x, y, z) match {
|
||||
case c: tileentity.Case if !world.isRemote =>
|
||||
c.computer.canInteract(player.getCommandSenderName)
|
||||
case c: tileentity.Case => c.canInteract(player.getCommandSenderName)
|
||||
case _ => super.removedByEntity(world, x, y, z, player)
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ class RobotAfterimage(val parent: SpecialDelegator) extends SpecialDelegate {
|
||||
|
||||
override def rightClick(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = {
|
||||
findMovingRobot(world, x, y, z) match {
|
||||
case Some(robot) => robot.getBlockType.onBlockActivated(world, robot.x, robot.y, robot.z, player, side.ordinal, hitX, hitY, hitZ)
|
||||
case Some(robot) => Blocks.robotProxy.rightClick(world, robot.x, robot.y, robot.z, player, side, hitX, hitY, hitZ)
|
||||
case _ => world.setBlockToAir(x, y, z)
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package li.cil.oc.common.block
|
||||
|
||||
import java.util
|
||||
import li.cil.oc.common.{GuiType, tileentity}
|
||||
import li.cil.oc.server.PacketSender
|
||||
import li.cil.oc.server.component.robot
|
||||
import li.cil.oc.util.Tooltip
|
||||
import li.cil.oc.{Settings, OpenComputers}
|
||||
@ -84,6 +85,14 @@ class RobotProxy(val parent: SpecialDelegator) extends Computer with SpecialDele
|
||||
side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = {
|
||||
if (!player.isSneaking) {
|
||||
if (!world.isRemote) {
|
||||
// We only send slot changes to nearby players, so if there was no slot
|
||||
// change since this player got into range he might have the wrong one,
|
||||
// so we send him the current one just in case.
|
||||
world.getBlockTileEntity(x, y, z) match {
|
||||
case proxy: tileentity.RobotProxy =>
|
||||
PacketSender.sendRobotSelectedSlotChange(proxy.robot)
|
||||
case _ =>
|
||||
}
|
||||
player.openGui(OpenComputers, GuiType.Robot.id, world, x, y, z)
|
||||
}
|
||||
true
|
||||
|
@ -6,9 +6,10 @@ import li.cil.oc.api.network._
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender, driver, component}
|
||||
import li.cil.oc.util.ExtendedNBT._
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.nbt.{NBTTagString, NBTTagCompound}
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import scala.Some
|
||||
import scala.collection.mutable
|
||||
|
||||
abstract class Computer(isRemote: Boolean) extends Environment with ComponentInventory with Rotatable with BundledRedstone with Analyzable {
|
||||
protected val _computer = if (isRemote) null else new component.Computer(this)
|
||||
@ -23,10 +24,14 @@ abstract class Computer(isRemote: Boolean) extends Environment with ComponentInv
|
||||
|
||||
private var hasChanged = false
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
private val _users = mutable.Set.empty[String]
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def isRunning = _isRunning
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
def isRunning_=(value: Boolean) = {
|
||||
_isRunning = value
|
||||
world.markBlockForRenderUpdate(x, y, z)
|
||||
@ -40,6 +45,21 @@ abstract class Computer(isRemote: Boolean) extends Environment with ComponentInv
|
||||
case _ => false
|
||||
}
|
||||
|
||||
def users: Iterable[String] =
|
||||
if (isServer) computer.users
|
||||
else _users
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
def users_=(list: Iterable[String]) {
|
||||
_users.clear()
|
||||
_users ++= list
|
||||
}
|
||||
|
||||
def canInteract(player: String) =
|
||||
if (isServer) computer.canInteract(player)
|
||||
else !Settings.get.canComputersBeOwned ||
|
||||
_users.isEmpty || _users.contains(player)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def updateEntity() {
|
||||
@ -95,11 +115,14 @@ abstract class Computer(isRemote: Boolean) extends Environment with ComponentInv
|
||||
override def readFromNBTForClient(nbt: NBTTagCompound) {
|
||||
super.readFromNBTForClient(nbt)
|
||||
isRunning = nbt.getBoolean("isRunning")
|
||||
_users.clear()
|
||||
_users ++= nbt.getTagList("users").iterator[NBTTagString].map(_.data)
|
||||
}
|
||||
|
||||
override def writeToNBTForClient(nbt: NBTTagCompound) {
|
||||
super.writeToNBTForClient(nbt)
|
||||
nbt.setBoolean("isRunning", isRunning)
|
||||
nbt.setNewTagList("users", computer.users.map(user => new NBTTagString(null, user)))
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
@ -126,9 +149,14 @@ abstract class Computer(isRemote: Boolean) extends Environment with ComponentInv
|
||||
|
||||
def onAnalyze(stats: NBTTagCompound, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float): Node = {
|
||||
if (computer != null) computer.lastError match {
|
||||
case Some(value) => stats.setString(Settings.namespace + "gui.Analyzer.LastError", value)
|
||||
case Some(value) =>
|
||||
stats.setString(Settings.namespace + "gui.Analyzer.LastError", value)
|
||||
case _ =>
|
||||
}
|
||||
val list = users
|
||||
if (list.size > 0) {
|
||||
stats.setString(Settings.namespace + "gui.Analyzer.Users", list.mkString(", "))
|
||||
}
|
||||
computer.node
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,16 @@ object PacketSender {
|
||||
}
|
||||
}
|
||||
|
||||
def sendComputerUserList(t: Computer, list: Array[String]) {
|
||||
val pb = new PacketBuilder(PacketType.ComputerUserList)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
pb.writeInt(list.length)
|
||||
list.foreach(pb.writeUTF)
|
||||
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendPowerState(t: PowerInformation, player: Option[Player] = None) {
|
||||
val pb = new PacketBuilder(PacketType.PowerState)
|
||||
|
||||
@ -91,7 +101,7 @@ object PacketSender {
|
||||
pb.writeTileEntity(t.proxy)
|
||||
pb.writeInt(t.animationTicksTotal)
|
||||
|
||||
pb.sendToNearbyPlayers(t)
|
||||
pb.sendToNearbyPlayers(t, 64)
|
||||
}
|
||||
|
||||
def sendRobotAnimateTurn(t: Robot) {
|
||||
@ -101,7 +111,7 @@ object PacketSender {
|
||||
pb.writeByte(t.turnAxis)
|
||||
pb.writeInt(t.animationTicksTotal)
|
||||
|
||||
pb.sendToNearbyPlayers(t)
|
||||
pb.sendToNearbyPlayers(t, 64)
|
||||
}
|
||||
|
||||
def sendRobotEquippedItemChange(t: Robot, stack: ItemStack) {
|
||||
@ -119,7 +129,7 @@ object PacketSender {
|
||||
pb.writeTileEntity(t.proxy)
|
||||
pb.writeInt(t.selectedSlot)
|
||||
|
||||
pb.sendToNearbyPlayers(t)
|
||||
pb.sendToNearbyPlayers(t, 16)
|
||||
}
|
||||
|
||||
def sendRotatableState(t: Rotatable, player: Option[Player] = None) {
|
||||
@ -187,7 +197,7 @@ object PacketSender {
|
||||
pb.writeTileEntity(t)
|
||||
pb.writeBoolean(hasPower)
|
||||
|
||||
pb.sendToNearbyPlayers(t)
|
||||
pb.sendToNearbyPlayers(t, 64)
|
||||
}
|
||||
|
||||
def sendScreenResolutionChange(t: Buffer, w: Int, h: Int) {
|
||||
|
@ -7,6 +7,7 @@ import li.cil.oc.api
|
||||
import li.cil.oc.api.network._
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.server
|
||||
import li.cil.oc.server.PacketSender
|
||||
import li.cil.oc.util.ExtendedLuaState.extendLuaState
|
||||
import li.cil.oc.util.ExtendedNBT._
|
||||
import li.cil.oc.util.{ThreadPoolFactory, GameTimeFormatter, LuaStateFactory}
|
||||
@ -45,7 +46,7 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
|
||||
|
||||
private val addedComponents = mutable.Set.empty[Component]
|
||||
|
||||
private val users = mutable.Set.empty[String]
|
||||
private val _users = mutable.Set.empty[String]
|
||||
|
||||
private val signals = new mutable.Queue[Computer.Signal]
|
||||
|
||||
@ -67,6 +68,8 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
|
||||
|
||||
private var remainingPause = 0 // Ticks left to wait before resuming.
|
||||
|
||||
private var usersChanged = false // Send updated users list to clients?
|
||||
|
||||
private var message: Option[String] = None // For error messages.
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
@ -83,6 +86,8 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
|
||||
|
||||
def lastError = message
|
||||
|
||||
def users = _users.synchronized(_users.toArray)
|
||||
|
||||
def isRobot = false
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
@ -90,7 +95,7 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
|
||||
def address = node.address
|
||||
|
||||
def canInteract(player: String) = !Settings.get.canComputersBeOwned ||
|
||||
users.isEmpty || users.contains(player) ||
|
||||
_users.synchronized(_users.isEmpty || _users.contains(player)) ||
|
||||
MinecraftServer.getServer.isSinglePlayer ||
|
||||
MinecraftServer.getServer.getConfigurationManager.isPlayerOpped(player)
|
||||
|
||||
@ -232,6 +237,15 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
|
||||
}
|
||||
})
|
||||
|
||||
// Avoid spamming user list across the network.
|
||||
if (worldTime % 20 == 0 && usersChanged) {
|
||||
val list = _users.synchronized {
|
||||
usersChanged = false
|
||||
users
|
||||
}
|
||||
PacketSender.sendComputerUserList(owner, list)
|
||||
}
|
||||
|
||||
// Check if we should switch states. These are all the states in which we're
|
||||
// guaranteed that the executor thread isn't running anymore.
|
||||
state.synchronized(state.top match {
|
||||
@ -419,14 +433,14 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
|
||||
|
||||
override def load(nbt: NBTTagCompound) = this.synchronized {
|
||||
assert(state.top == Computer.State.Stopped)
|
||||
assert(users.isEmpty)
|
||||
assert(_users.isEmpty)
|
||||
assert(signals.isEmpty)
|
||||
state.clear()
|
||||
|
||||
super.load(nbt)
|
||||
|
||||
state.pushAll(nbt.getTagList("state").iterator[NBTTagInt].reverse.map(s => Computer.State(s.data)))
|
||||
nbt.getTagList("users").foreach[NBTTagString](u => users += u.data)
|
||||
nbt.getTagList("users").foreach[NBTTagString](u => _users += u.data)
|
||||
|
||||
if (state.size > 0 && state.top != Computer.State.Stopped && init()) {
|
||||
// Unlimit memory use while unpersisting.
|
||||
@ -506,7 +520,7 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
|
||||
processAddedComponents()
|
||||
|
||||
nbt.setNewTagList("state", state.map(_.id))
|
||||
nbt.setNewTagList("users", users)
|
||||
nbt.setNewTagList("users", _users)
|
||||
|
||||
if (state.top != Computer.State.Stopped) {
|
||||
// Unlimit memory while persisting.
|
||||
@ -826,25 +840,28 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
|
||||
|
||||
// User management.
|
||||
lua.pushScalaFunction(lua => {
|
||||
users.foreach(lua.pushString)
|
||||
users.size
|
||||
_users.foreach(lua.pushString)
|
||||
_users.size
|
||||
})
|
||||
lua.setField(-2, "users")
|
||||
|
||||
lua.pushScalaFunction(lua => try {
|
||||
if (users.size >= Settings.get.maxUsers)
|
||||
if (_users.size >= Settings.get.maxUsers)
|
||||
throw new Exception("too many users")
|
||||
|
||||
val name = lua.checkString(1)
|
||||
|
||||
if (users.contains(name))
|
||||
if (_users.contains(name))
|
||||
throw new Exception("user exists")
|
||||
if (name.length > Settings.get.maxUsernameLength)
|
||||
throw new Exception("username too long")
|
||||
if (!MinecraftServer.getServer.getConfigurationManager.getAllUsernames.contains(name))
|
||||
throw new Exception("player must be online")
|
||||
|
||||
users += name
|
||||
_users.synchronized {
|
||||
_users += name
|
||||
usersChanged = true
|
||||
}
|
||||
lua.pushBoolean(true)
|
||||
1
|
||||
} catch {
|
||||
@ -857,7 +874,13 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
|
||||
|
||||
lua.pushScalaFunction(lua => {
|
||||
val name = lua.checkString(1)
|
||||
lua.pushBoolean(users.remove(name))
|
||||
_users.synchronized {
|
||||
val success = _users.remove(name)
|
||||
if (success) {
|
||||
usersChanged = true
|
||||
}
|
||||
lua.pushBoolean(success)
|
||||
}
|
||||
1
|
||||
})
|
||||
lua.setField(-2, "removeUser")
|
||||
|
@ -22,15 +22,6 @@ abstract class ManagedComponent extends ManagedEnvironment {
|
||||
if (node != null) nbt.setNewCompoundTag("node", node.save)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handy function for returning a list of results.
|
||||
* <p/>
|
||||
* This is primarily meant to be used for returning result arrays from Lua
|
||||
* callbacks, to avoid having to write `XYZ.box(...)` all the time.
|
||||
*
|
||||
* @param args the values to return.
|
||||
* @return and array of objects.
|
||||
*/
|
||||
final protected def result(args: Any*): Array[AnyRef] = {
|
||||
def unwrap(arg: Any): AnyRef = arg match {
|
||||
case x: ScalaNumber => x.underlying
|
||||
|
Loading…
x
Reference in New Issue
Block a user