mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-13 17:28:52 -04:00
Added whitelisting of debug card owners.
This commit is contained in:
parent
2a5de6868a
commit
537b8c20f6
@ -1510,9 +1510,11 @@ opencomputers {
|
|||||||
# Enable debug card functionality. This may also be of use for custom
|
# Enable debug card functionality. This may also be of use for custom
|
||||||
# maps, so it is enabled by default. If you run a server where people
|
# maps, so it is enabled by default. If you run a server where people
|
||||||
# may cheat in items but should not have op/admin-like rights, you may
|
# may cheat in items but should not have op/admin-like rights, you may
|
||||||
# want to set this to false. This will *not* remove the card, it will
|
# want to set this to false or `deny`. Set this to `whitelist` if you
|
||||||
# just make all functions it provides error out.
|
# want to enable whitelisting of debug card users (managed by command
|
||||||
enableDebugCard: true
|
# /oc_debugWhitelist). This will *not* remove the card, it will just
|
||||||
|
# make all functions it provides error out.
|
||||||
|
debugCardAccess: allow
|
||||||
|
|
||||||
# Whether to always register the LuaJ architecture - even if the native
|
# Whether to always register the LuaJ architecture - even if the native
|
||||||
# library is available. In that case it is possible to switch between
|
# library is available. In that case it is possible to switch between
|
||||||
|
@ -3,6 +3,8 @@ package li.cil.oc
|
|||||||
import java.io._
|
import java.io._
|
||||||
import java.net.Inet4Address
|
import java.net.Inet4Address
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
import java.security.SecureRandom
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
import com.google.common.net.InetAddresses
|
import com.google.common.net.InetAddresses
|
||||||
@ -11,11 +13,16 @@ import com.typesafe.config._
|
|||||||
import cpw.mods.fml.common.Loader
|
import cpw.mods.fml.common.Loader
|
||||||
import cpw.mods.fml.common.versioning.DefaultArtifactVersion
|
import cpw.mods.fml.common.versioning.DefaultArtifactVersion
|
||||||
import cpw.mods.fml.common.versioning.VersionRange
|
import cpw.mods.fml.common.versioning.VersionRange
|
||||||
|
import li.cil.oc.Settings.DebugCardAccess
|
||||||
import li.cil.oc.common.Tier
|
import li.cil.oc.common.Tier
|
||||||
import li.cil.oc.integration.Mods
|
import li.cil.oc.integration.Mods
|
||||||
|
import li.cil.oc.server.component.DebugCard
|
||||||
|
import li.cil.oc.server.component.DebugCard.AccessContext
|
||||||
|
import org.apache.commons.codec.binary.Hex
|
||||||
import org.apache.commons.lang3.StringEscapeUtils
|
import org.apache.commons.lang3.StringEscapeUtils
|
||||||
|
|
||||||
import scala.collection.convert.WrapAsScala._
|
import scala.collection.convert.WrapAsScala._
|
||||||
|
import scala.collection.mutable
|
||||||
import scala.io.Codec
|
import scala.io.Codec
|
||||||
import scala.io.Source
|
import scala.io.Source
|
||||||
import scala.util.matching.Regex
|
import scala.util.matching.Regex
|
||||||
@ -413,7 +420,21 @@ class Settings(val config: Config) {
|
|||||||
val nativeInTmpDir = config.getBoolean("debug.nativeInTmpDir")
|
val nativeInTmpDir = config.getBoolean("debug.nativeInTmpDir")
|
||||||
val periodicallyForceLightUpdate = config.getBoolean("debug.periodicallyForceLightUpdate")
|
val periodicallyForceLightUpdate = config.getBoolean("debug.periodicallyForceLightUpdate")
|
||||||
val insertIdsInConverters = config.getBoolean("debug.insertIdsInConverters")
|
val insertIdsInConverters = config.getBoolean("debug.insertIdsInConverters")
|
||||||
val enableDebugCard = config.getBoolean("debug.enableDebugCard")
|
|
||||||
|
val debugCardAccess = config.getValue("debug.debugCardAccess").unwrapped() match {
|
||||||
|
case "true" | "allow" | java.lang.Boolean.TRUE => DebugCardAccess.Allowed
|
||||||
|
case "false" | "deny" | java.lang.Boolean.FALSE => DebugCardAccess.Forbidden
|
||||||
|
case "whitelist" =>
|
||||||
|
val wlFile = new File(Loader.instance.getConfigDir + File.separator + "opencomputers" + File.separator +
|
||||||
|
"debug_card_whitelist.txt")
|
||||||
|
|
||||||
|
DebugCardAccess.Whitelist(wlFile)
|
||||||
|
|
||||||
|
case _ => // Fallback to most secure configuration
|
||||||
|
OpenComputers.log.warn("Unknown debug card access type, falling back to `deny`. Allowed values: `allow`, `deny`, `whitelist`.")
|
||||||
|
DebugCardAccess.Forbidden
|
||||||
|
}
|
||||||
|
|
||||||
val registerLuaJArchitecture = config.getBoolean("debug.registerLuaJArchitecture")
|
val registerLuaJArchitecture = config.getBoolean("debug.registerLuaJArchitecture")
|
||||||
val disableLocaleChanging = config.getBoolean("debug.disableLocaleChanging")
|
val disableLocaleChanging = config.getBoolean("debug.disableLocaleChanging")
|
||||||
}
|
}
|
||||||
@ -557,4 +578,95 @@ object Settings {
|
|||||||
def apply(inetAddress: InetAddress, host: String) = validator(inetAddress, host)
|
def apply(inetAddress: InetAddress, host: String) = validator(inetAddress, host)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed trait DebugCardAccess {
|
||||||
|
def checkAccess(ctx: Option[DebugCard.AccessContext]): Option[String]
|
||||||
|
}
|
||||||
|
|
||||||
|
object DebugCardAccess {
|
||||||
|
case object Forbidden extends DebugCardAccess {
|
||||||
|
override def checkAccess(ctx: Option[AccessContext]): Option[String] =
|
||||||
|
Some("debug card is disabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
case object Allowed extends DebugCardAccess {
|
||||||
|
override def checkAccess(ctx: Option[AccessContext]): Option[String] = None
|
||||||
|
}
|
||||||
|
|
||||||
|
case class Whitelist(noncesFile: File) extends DebugCardAccess {
|
||||||
|
private val values = mutable.Map.empty[String, String]
|
||||||
|
private val rng = SecureRandom.getInstance("SHA1PRNG")
|
||||||
|
|
||||||
|
load()
|
||||||
|
|
||||||
|
def save(): Unit = {
|
||||||
|
val noncesDir = noncesFile.getParentFile
|
||||||
|
if (!noncesDir.exists() && !noncesDir.mkdirs())
|
||||||
|
throw new IOException(s"Cannot create nonces directory: ${noncesDir.getCanonicalPath}")
|
||||||
|
|
||||||
|
val writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(noncesFile), StandardCharsets.UTF_8), false)
|
||||||
|
try {
|
||||||
|
for ((p, n) <- values)
|
||||||
|
writer.println(s"$p $n")
|
||||||
|
} finally writer.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
def load(): Unit = {
|
||||||
|
values.clear()
|
||||||
|
|
||||||
|
if (!noncesFile.exists())
|
||||||
|
return
|
||||||
|
|
||||||
|
val reader = new BufferedReader(new InputStreamReader(new FileInputStream(noncesFile), StandardCharsets.UTF_8))
|
||||||
|
Iterator.continually(reader.readLine())
|
||||||
|
.takeWhile(_ != null)
|
||||||
|
.map(_.split(" ", 2))
|
||||||
|
.flatMap {
|
||||||
|
case Array(p, n) => Seq(p -> n)
|
||||||
|
case _ => Nil
|
||||||
|
}.foreach(values += _)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def generateNonce(): String = {
|
||||||
|
val buf = new Array[Byte](16)
|
||||||
|
rng.nextBytes(buf)
|
||||||
|
new String(Hex.encodeHex(buf, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
def nonce(player: String) = values.get(player.toLowerCase)
|
||||||
|
|
||||||
|
def isWhitelisted(player: String) = values.contains(player.toLowerCase)
|
||||||
|
|
||||||
|
def whitelist: collection.Set[String] = values.keySet
|
||||||
|
|
||||||
|
def add(player: String): Unit = {
|
||||||
|
if (!values.contains(player.toLowerCase)) {
|
||||||
|
values.put(player.toLowerCase, generateNonce())
|
||||||
|
save()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def remove(player: String): Unit = {
|
||||||
|
if (values.remove(player.toLowerCase).isDefined)
|
||||||
|
save()
|
||||||
|
}
|
||||||
|
|
||||||
|
def invalidate(player: String): Unit = {
|
||||||
|
if (values.contains(player.toLowerCase)) {
|
||||||
|
values.put(player.toLowerCase, generateNonce())
|
||||||
|
save()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def checkAccess(ctxOpt: Option[DebugCard.AccessContext]): Option[String] = ctxOpt match {
|
||||||
|
case Some(ctx) => values.get(ctx.player) match {
|
||||||
|
case Some(x) =>
|
||||||
|
if (x == ctx.nonce) None
|
||||||
|
else Some("debug card is invalidated, please re-bind it to yourself")
|
||||||
|
case None => Some("you are not whitelisted to use debug card")
|
||||||
|
}
|
||||||
|
|
||||||
|
case None => Some("debug card is whitelisted, Shift+Click with it to bind card to yourself")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,23 +2,41 @@ package li.cil.oc.common.item
|
|||||||
|
|
||||||
import java.util
|
import java.util
|
||||||
|
|
||||||
|
import li.cil.oc.Settings
|
||||||
|
import li.cil.oc.Settings.DebugCardAccess
|
||||||
import li.cil.oc.common.item.data.DebugCardData
|
import li.cil.oc.common.item.data.DebugCardData
|
||||||
import net.minecraft.entity.player.EntityPlayer
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
|
import li.cil.oc.server.command.string2text
|
||||||
|
import li.cil.oc.server.component.{DebugCard => CDebugCard}
|
||||||
|
|
||||||
class DebugCard(val parent: Delegator) extends traits.Delegate {
|
class DebugCard(val parent: Delegator) extends traits.Delegate {
|
||||||
override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]): Unit = {
|
override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]): Unit = {
|
||||||
super.tooltipExtended(stack, tooltip)
|
super.tooltipExtended(stack, tooltip)
|
||||||
val data = new DebugCardData(stack)
|
val data = new DebugCardData(stack)
|
||||||
data.player.foreach(name => tooltip.add(s"§8$name§r"))
|
data.access.foreach(access => tooltip.add(s"§8${access.player}§r"))
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ItemStack = {
|
override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ItemStack = {
|
||||||
if (player.isSneaking) {
|
if (player.isSneaking) {
|
||||||
val data = new DebugCardData(stack)
|
val data = new DebugCardData(stack)
|
||||||
if (data.player.contains(player.getCommandSenderName)) data.player = None
|
val name = player.getCommandSenderName
|
||||||
else data.player = Option(player.getCommandSenderName)
|
|
||||||
|
if (data.access.exists(_.player == name)) data.access = None
|
||||||
|
else data.access =
|
||||||
|
Some(CDebugCard.AccessContext(name, Settings.get.debugCardAccess match {
|
||||||
|
case wl: DebugCardAccess.Whitelist => wl.nonce(name) match {
|
||||||
|
case Some(n) => n
|
||||||
|
case None =>
|
||||||
|
player.addChatComponentMessage("§cYou are not whitelisted to use debug card")
|
||||||
|
player.swingItem()
|
||||||
|
return stack
|
||||||
|
}
|
||||||
|
|
||||||
|
case _ => ""
|
||||||
|
}))
|
||||||
|
|
||||||
data.save(stack)
|
data.save(stack)
|
||||||
player.swingItem()
|
player.swingItem()
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package li.cil.oc.common.item.data
|
package li.cil.oc.common.item.data
|
||||||
|
|
||||||
import li.cil.oc.Constants
|
import li.cil.oc.{Constants, Settings}
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.server.component.DebugCard.AccessContext
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
|
||||||
@ -11,19 +11,16 @@ class DebugCardData extends ItemData(Constants.ItemName.DebugCard) {
|
|||||||
load(stack)
|
load(stack)
|
||||||
}
|
}
|
||||||
|
|
||||||
var player: Option[String] = None
|
var access: Option[AccessContext] = None
|
||||||
|
|
||||||
override def load(nbt: NBTTagCompound) {
|
override def load(nbt: NBTTagCompound): Unit = {
|
||||||
val tag = dataTag(nbt)
|
access = AccessContext.load(dataTag(nbt))
|
||||||
if (tag.hasKey(Settings.namespace + "player")) {
|
|
||||||
player = Option(tag.getString(Settings.namespace + "player"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override def save(nbt: NBTTagCompound) {
|
override def save(nbt: NBTTagCompound): Unit = {
|
||||||
val tag = dataTag(nbt)
|
val tag = dataTag(nbt)
|
||||||
tag.removeTag(Settings.namespace + "player")
|
AccessContext.remove(tag)
|
||||||
player.foreach(tag.setString(Settings.namespace + "player", _))
|
access.foreach(_.save(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
private def dataTag(nbt: NBTTagCompound) = {
|
private def dataTag(nbt: NBTTagCompound) = {
|
||||||
|
@ -10,5 +10,6 @@ object CommandHandler {
|
|||||||
e.registerServerCommand(NonDisassemblyAgreementCommand)
|
e.registerServerCommand(NonDisassemblyAgreementCommand)
|
||||||
e.registerServerCommand(WirelessRenderingCommand)
|
e.registerServerCommand(WirelessRenderingCommand)
|
||||||
e.registerServerCommand(SpawnComputerCommand)
|
e.registerServerCommand(SpawnComputerCommand)
|
||||||
|
e.registerServerCommand(DebugWhitelistCommand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package li.cil.oc.server.command
|
||||||
|
|
||||||
|
import li.cil.oc.Settings
|
||||||
|
import li.cil.oc.Settings.DebugCardAccess
|
||||||
|
import li.cil.oc.common.command.SimpleCommand
|
||||||
|
import net.minecraft.command.{ICommandSender, WrongUsageException}
|
||||||
|
|
||||||
|
object DebugWhitelistCommand extends SimpleCommand("oc_debugWhitelist") {
|
||||||
|
// Required OP levels:
|
||||||
|
// to revoke your cards - 0
|
||||||
|
// to do other whitelist manipulation - 2
|
||||||
|
|
||||||
|
override def getRequiredPermissionLevel = 0
|
||||||
|
private def isOp(sender: ICommandSender) = getOpLevel(sender) >= 2
|
||||||
|
|
||||||
|
override def getCommandUsage(sender: ICommandSender): String =
|
||||||
|
if (isOp(sender)) name + " [revoke|add|remove] <player> OR " + name + " [revoke|list]"
|
||||||
|
else name + " revoke"
|
||||||
|
|
||||||
|
override def processCommand(sender: ICommandSender, args: Array[String]): Unit = {
|
||||||
|
val wl = Settings.get.debugCardAccess match {
|
||||||
|
case w: DebugCardAccess.Whitelist => w
|
||||||
|
case _ => throw new WrongUsageException("§cDebug card whitelisting is not enabled.")
|
||||||
|
}
|
||||||
|
|
||||||
|
def revokeUser(player: String): Unit = {
|
||||||
|
if (wl.isWhitelisted(player)) {
|
||||||
|
wl.invalidate(player)
|
||||||
|
sender.addChatMessage("§aAll your debug cards were invalidated.")
|
||||||
|
} else sender.addChatMessage("§cYou are not whitelisted to use debug card.")
|
||||||
|
}
|
||||||
|
|
||||||
|
args match {
|
||||||
|
case Array("revoke") => revokeUser(sender.getCommandSenderName)
|
||||||
|
case Array("revoke", player) if isOp(sender) => revokeUser(player)
|
||||||
|
case Array("list") if isOp(sender) =>
|
||||||
|
val players = wl.whitelist
|
||||||
|
if (players.nonEmpty)
|
||||||
|
sender.addChatMessage("§aCurrently whitelisted players: §e" + players.mkString(", "))
|
||||||
|
else
|
||||||
|
sender.addChatMessage("§cThere is no currently whitelisted players.")
|
||||||
|
case Array("add", player) if isOp(sender) =>
|
||||||
|
wl.add(player)
|
||||||
|
sender.addChatMessage("§aPlayer was added to whitelist.")
|
||||||
|
case Array("remove", player) if isOp(sender) =>
|
||||||
|
wl.remove(player)
|
||||||
|
sender.addChatMessage("§aPlayer was removed from whitelist")
|
||||||
|
case _ =>
|
||||||
|
sender.addChatMessage("§e" + getCommandUsage(sender))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
src/main/scala/li/cil/oc/server/command/package.scala
Normal file
32
src/main/scala/li/cil/oc/server/command/package.scala
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package li.cil.oc.server
|
||||||
|
|
||||||
|
import java.util.logging.Level
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.FMLLog
|
||||||
|
import net.minecraft.command.ICommandSender
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP
|
||||||
|
import net.minecraft.server.MinecraftServer
|
||||||
|
import net.minecraft.server.management.UserListOpsEntry
|
||||||
|
import net.minecraft.util.{ChatComponentText, IChatComponent}
|
||||||
|
|
||||||
|
import scala.language.implicitConversions
|
||||||
|
|
||||||
|
package object command {
|
||||||
|
implicit def string2text(s: String): IChatComponent = new ChatComponentText(s)
|
||||||
|
|
||||||
|
def getOpLevel(sender: ICommandSender): Int = {
|
||||||
|
// Shitty minecraft server logic & shitty minecraft server code.
|
||||||
|
val srv = MinecraftServer.getServer
|
||||||
|
if (srv.isSinglePlayer && srv.worldServers.head.getWorldInfo.areCommandsAllowed &&
|
||||||
|
srv.getServerOwner.equalsIgnoreCase(sender.getCommandSenderName) /* || srv.commandsAllowedForAll */ )
|
||||||
|
return 4
|
||||||
|
|
||||||
|
sender match {
|
||||||
|
case _: MinecraftServer => 4
|
||||||
|
case p: EntityPlayerMP =>
|
||||||
|
val e = srv.getConfigurationManager.func_152603_m.func_152683_b(p.getGameProfile)
|
||||||
|
if (e == null) 0 else e.asInstanceOf[UserListOpsEntry].func_152644_a()
|
||||||
|
case _ => 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,7 @@ import li.cil.oc.api.network.SidedEnvironment
|
|||||||
import li.cil.oc.api.network.Visibility
|
import li.cil.oc.api.network.Visibility
|
||||||
import li.cil.oc.api.prefab
|
import li.cil.oc.api.prefab
|
||||||
import li.cil.oc.api.prefab.AbstractValue
|
import li.cil.oc.api.prefab.AbstractValue
|
||||||
import li.cil.oc.server.component.DebugCard.CommandSender
|
import li.cil.oc.server.component.DebugCard.{AccessContext, CommandSender}
|
||||||
import li.cil.oc.util.BlockPosition
|
import li.cil.oc.util.BlockPosition
|
||||||
import li.cil.oc.util.ExtendedArguments._
|
import li.cil.oc.util.ExtendedArguments._
|
||||||
import li.cil.oc.util.ExtendedNBT._
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
@ -57,7 +57,9 @@ class DebugCard(host: EnvironmentHost) extends prefab.ManagedEnvironment {
|
|||||||
private var remoteNodePosition: Option[(Int, Int, Int)] = None
|
private var remoteNodePosition: Option[(Int, Int, Int)] = None
|
||||||
|
|
||||||
// Player this card is bound to (if any) to use for permissions.
|
// Player this card is bound to (if any) to use for permissions.
|
||||||
var player: Option[String] = None
|
implicit var access: Option[AccessContext] = None
|
||||||
|
|
||||||
|
def player = access.map(_.player)
|
||||||
|
|
||||||
private lazy val CommandSender = {
|
private lazy val CommandSender = {
|
||||||
def defaultFakePlayer = FakePlayerFactory.get(host.world.asInstanceOf[WorldServer], Settings.get.fakePlayerProfile)
|
def defaultFakePlayer = FakePlayerFactory.get(host.world.asInstanceOf[WorldServer], Settings.get.fakePlayerProfile)
|
||||||
@ -72,67 +74,67 @@ class DebugCard(host: EnvironmentHost) extends prefab.ManagedEnvironment {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
import li.cil.oc.server.component.DebugCard.checkEnabled
|
import li.cil.oc.server.component.DebugCard.checkAccess
|
||||||
|
|
||||||
@Callback(doc = """function(value:number):number -- Changes the component network's energy buffer by the specified delta.""")
|
@Callback(doc = """function(value:number):number -- Changes the component network's energy buffer by the specified delta.""")
|
||||||
def changeBuffer(context: Context, args: Arguments): Array[AnyRef] = {
|
def changeBuffer(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(node.changeBuffer(args.checkDouble(0)))
|
result(node.changeBuffer(args.checkDouble(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function():number -- Get the container's X position in the world.""")
|
@Callback(doc = """function():number -- Get the container's X position in the world.""")
|
||||||
def getX(context: Context, args: Arguments): Array[AnyRef] = {
|
def getX(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(host.xPosition)
|
result(host.xPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function():number -- Get the container's Y position in the world.""")
|
@Callback(doc = """function():number -- Get the container's Y position in the world.""")
|
||||||
def getY(context: Context, args: Arguments): Array[AnyRef] = {
|
def getY(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(host.yPosition)
|
result(host.yPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function():number -- Get the container's Z position in the world.""")
|
@Callback(doc = """function():number -- Get the container's Z position in the world.""")
|
||||||
def getZ(context: Context, args: Arguments): Array[AnyRef] = {
|
def getZ(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(host.zPosition)
|
result(host.zPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function([id:number]):userdata -- Get the world object for the specified dimension ID, or the container's.""")
|
@Callback(doc = """function([id:number]):userdata -- Get the world object for the specified dimension ID, or the container's.""")
|
||||||
def getWorld(context: Context, args: Arguments): Array[AnyRef] = {
|
def getWorld(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
if (args.count() > 0) result(new DebugCard.WorldValue(DimensionManager.getWorld(args.checkInteger(0))))
|
if (args.count() > 0) result(new DebugCard.WorldValue(DimensionManager.getWorld(args.checkInteger(0))))
|
||||||
else result(new DebugCard.WorldValue(host.world))
|
else result(new DebugCard.WorldValue(host.world))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function():table -- Get a list of all world IDs, loaded and unloaded.""")
|
@Callback(doc = """function():table -- Get a list of all world IDs, loaded and unloaded.""")
|
||||||
def getWorlds(context: Context, args: Arguments): Array[AnyRef] = {
|
def getWorlds(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(DimensionManager.getStaticDimensionIDs)
|
result(DimensionManager.getStaticDimensionIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(name:string):userdata -- Get the entity of a player.""")
|
@Callback(doc = """function(name:string):userdata -- Get the entity of a player.""")
|
||||||
def getPlayer(context: Context, args: Arguments): Array[AnyRef] = {
|
def getPlayer(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(new DebugCard.PlayerValue(args.checkString(0)))
|
result(new DebugCard.PlayerValue(args.checkString(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function():table -- Get a list of currently logged-in players.""")
|
@Callback(doc = """function():table -- Get a list of currently logged-in players.""")
|
||||||
def getPlayers(context: Context, args: Arguments): Array[AnyRef] = {
|
def getPlayers(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(MinecraftServer.getServer.getAllUsernames)
|
result(MinecraftServer.getServer.getAllUsernames)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(name:string):boolean -- Get whether a mod or API is loaded.""")
|
@Callback(doc = """function(name:string):boolean -- Get whether a mod or API is loaded.""")
|
||||||
def isModLoaded(context: Context, args: Arguments): Array[AnyRef] = {
|
def isModLoaded(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
val name = args.checkString(0)
|
val name = args.checkString(0)
|
||||||
result(Loader.isModLoaded(name) || ModAPIManager.INSTANCE.hasAPI(name))
|
result(Loader.isModLoaded(name) || ModAPIManager.INSTANCE.hasAPI(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(command:string):number -- Runs an arbitrary command using a fake player.""")
|
@Callback(doc = """function(command:string):number -- Runs an arbitrary command using a fake player.""")
|
||||||
def runCommand(context: Context, args: Arguments): Array[AnyRef] = {
|
def runCommand(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
val commands =
|
val commands =
|
||||||
if (args.isTable(0)) collectionAsScalaIterable(args.checkTable(0).values())
|
if (args.isTable(0)) collectionAsScalaIterable(args.checkTable(0).values())
|
||||||
else Iterable(args.checkString(0))
|
else Iterable(args.checkString(0))
|
||||||
@ -149,7 +151,7 @@ class DebugCard(host: EnvironmentHost) extends prefab.ManagedEnvironment {
|
|||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number):boolean -- Connect the debug card to the block at the specified coordinates.""")
|
@Callback(doc = """function(x:number, y:number, z:number):boolean -- Connect the debug card to the block at the specified coordinates.""")
|
||||||
def connectToBlock(context: Context, args: Arguments): Array[AnyRef] = {
|
def connectToBlock(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
val x = args.checkInteger(0)
|
val x = args.checkInteger(0)
|
||||||
val y = args.checkInteger(1)
|
val y = args.checkInteger(1)
|
||||||
val z = args.checkInteger(2)
|
val z = args.checkInteger(2)
|
||||||
@ -177,7 +179,7 @@ class DebugCard(host: EnvironmentHost) extends prefab.ManagedEnvironment {
|
|||||||
|
|
||||||
@Callback(doc = """function():userdata -- Test method for user-data and general value conversion.""")
|
@Callback(doc = """function():userdata -- Test method for user-data and general value conversion.""")
|
||||||
def test(context: Context, args: Arguments): Array[AnyRef] = {
|
def test(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
|
|
||||||
val v1 = mutable.Map("a" -> true, "b" -> "test")
|
val v1 = mutable.Map("a" -> true, "b" -> "test")
|
||||||
val v2 = Map(10 -> "zxc", false -> v1)
|
val v2 = Map(10 -> "zxc", false -> v1)
|
||||||
@ -215,42 +217,63 @@ class DebugCard(host: EnvironmentHost) extends prefab.ManagedEnvironment {
|
|||||||
|
|
||||||
override def load(nbt: NBTTagCompound): Unit = {
|
override def load(nbt: NBTTagCompound): Unit = {
|
||||||
super.load(nbt)
|
super.load(nbt)
|
||||||
|
access = AccessContext.load(nbt)
|
||||||
if (nbt.hasKey(Settings.namespace + "remoteX")) {
|
if (nbt.hasKey(Settings.namespace + "remoteX")) {
|
||||||
val x = nbt.getInteger(Settings.namespace + "remoteX")
|
val x = nbt.getInteger(Settings.namespace + "remoteX")
|
||||||
val y = nbt.getInteger(Settings.namespace + "remoteY")
|
val y = nbt.getInteger(Settings.namespace + "remoteY")
|
||||||
val z = nbt.getInteger(Settings.namespace + "remoteZ")
|
val z = nbt.getInteger(Settings.namespace + "remoteZ")
|
||||||
remoteNodePosition = Some((x, y, z))
|
remoteNodePosition = Some((x, y, z))
|
||||||
}
|
}
|
||||||
if (nbt.hasKey(Settings.namespace + "player")) {
|
|
||||||
player = Option(nbt.getString(Settings.namespace + "player"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override def save(nbt: NBTTagCompound): Unit = {
|
override def save(nbt: NBTTagCompound): Unit = {
|
||||||
super.save(nbt)
|
super.save(nbt)
|
||||||
|
access.foreach(_.save(nbt))
|
||||||
remoteNodePosition.foreach {
|
remoteNodePosition.foreach {
|
||||||
case (x, y, z) =>
|
case (x, y, z) =>
|
||||||
nbt.setInteger(Settings.namespace + "remoteX", x)
|
nbt.setInteger(Settings.namespace + "remoteX", x)
|
||||||
nbt.setInteger(Settings.namespace + "remoteY", y)
|
nbt.setInteger(Settings.namespace + "remoteY", y)
|
||||||
nbt.setInteger(Settings.namespace + "remoteZ", z)
|
nbt.setInteger(Settings.namespace + "remoteZ", z)
|
||||||
}
|
}
|
||||||
player.foreach(nbt.setString(Settings.namespace + "player", _))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object DebugCard {
|
object DebugCard {
|
||||||
|
def checkAccess()(implicit ctx: Option[AccessContext]) =
|
||||||
|
for (msg <- Settings.get.debugCardAccess.checkAccess(ctx))
|
||||||
|
throw new Exception(msg)
|
||||||
|
|
||||||
import li.cil.oc.util.ResultWrapper.result
|
object AccessContext {
|
||||||
|
def remove(nbt: NBTTagCompound): Unit = {
|
||||||
|
nbt.removeTag(Settings.namespace + "player")
|
||||||
|
nbt.removeTag(Settings.namespace + "accessNonce")
|
||||||
|
}
|
||||||
|
|
||||||
def checkEnabled() = if (!Settings.get.enableDebugCard) throw new Exception("debug card functionality is disabled")
|
def load(nbt: NBTTagCompound): Option[AccessContext] = {
|
||||||
|
if (nbt.hasKey(Settings.namespace + "player"))
|
||||||
|
Some(AccessContext(
|
||||||
|
nbt.getString(Settings.namespace + "player"),
|
||||||
|
nbt.getString(Settings.namespace + "accessNonce")
|
||||||
|
))
|
||||||
|
else
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class PlayerValue(var name: String) extends prefab.AbstractValue {
|
case class AccessContext(player: String, nonce: String) {
|
||||||
def this() = this("") // For loading.
|
def save(nbt: NBTTagCompound): Unit = {
|
||||||
|
nbt.setString(Settings.namespace + "player", player)
|
||||||
|
nbt.setString(Settings.namespace + "accessNonce", nonce)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PlayerValue(var name: String)(implicit var ctx: Option[AccessContext]) extends prefab.AbstractValue {
|
||||||
|
def this() = this("")(None) // For loading.
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
def withPlayer(f: (EntityPlayerMP) => Array[AnyRef]) = {
|
def withPlayer(f: (EntityPlayerMP) => Array[AnyRef]) = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
MinecraftServer.getServer.getConfigurationManager.func_152612_a(name) match {
|
MinecraftServer.getServer.getConfigurationManager.func_152612_a(name) match {
|
||||||
case player: EntityPlayerMP => f(player)
|
case player: EntityPlayerMP => f(player)
|
||||||
case _ => result(Unit, "player is offline")
|
case _ => result(Unit, "player is offline")
|
||||||
@ -304,93 +327,95 @@ object DebugCard {
|
|||||||
|
|
||||||
override def load(nbt: NBTTagCompound) {
|
override def load(nbt: NBTTagCompound) {
|
||||||
super.load(nbt)
|
super.load(nbt)
|
||||||
|
ctx = AccessContext.load(nbt)
|
||||||
name = nbt.getString("name")
|
name = nbt.getString("name")
|
||||||
}
|
}
|
||||||
|
|
||||||
override def save(nbt: NBTTagCompound) {
|
override def save(nbt: NBTTagCompound) {
|
||||||
super.save(nbt)
|
super.save(nbt)
|
||||||
|
ctx.foreach(_.save(nbt))
|
||||||
nbt.setString("name", name)
|
nbt.setString("name", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WorldValue(var world: World) extends prefab.AbstractValue {
|
class WorldValue(var world: World)(implicit var ctx: Option[AccessContext]) extends prefab.AbstractValue {
|
||||||
def this() = this(null) // For loading.
|
def this() = this(null)(None) // For loading.
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
@Callback(doc = """function():number -- Gets the numeric id of the current dimension.""")
|
@Callback(doc = """function():number -- Gets the numeric id of the current dimension.""")
|
||||||
def getDimensionId(context: Context, args: Arguments): Array[AnyRef] = {
|
def getDimensionId(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(world.provider.dimensionId)
|
result(world.provider.dimensionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function():string -- Gets the name of the current dimension.""")
|
@Callback(doc = """function():string -- Gets the name of the current dimension.""")
|
||||||
def getDimensionName(context: Context, args: Arguments): Array[AnyRef] = {
|
def getDimensionName(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(world.provider.getDimensionName)
|
result(world.provider.getDimensionName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function():number -- Gets the seed of the world.""")
|
@Callback(doc = """function():number -- Gets the seed of the world.""")
|
||||||
def getSeed(context: Context, args: Arguments): Array[AnyRef] = {
|
def getSeed(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(world.getSeed)
|
result(world.getSeed)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function():boolean -- Returns whether it is currently raining.""")
|
@Callback(doc = """function():boolean -- Returns whether it is currently raining.""")
|
||||||
def isRaining(context: Context, args: Arguments): Array[AnyRef] = {
|
def isRaining(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(world.isRaining)
|
result(world.isRaining)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(value:boolean) -- Sets whether it is currently raining.""")
|
@Callback(doc = """function(value:boolean) -- Sets whether it is currently raining.""")
|
||||||
def setRaining(context: Context, args: Arguments): Array[AnyRef] = {
|
def setRaining(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
world.getWorldInfo.setRaining(args.checkBoolean(0))
|
world.getWorldInfo.setRaining(args.checkBoolean(0))
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function():boolean -- Returns whether it is currently thundering.""")
|
@Callback(doc = """function():boolean -- Returns whether it is currently thundering.""")
|
||||||
def isThundering(context: Context, args: Arguments): Array[AnyRef] = {
|
def isThundering(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(world.isThundering)
|
result(world.isThundering)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(value:boolean) -- Sets whether it is currently thundering.""")
|
@Callback(doc = """function(value:boolean) -- Sets whether it is currently thundering.""")
|
||||||
def setThundering(context: Context, args: Arguments): Array[AnyRef] = {
|
def setThundering(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
world.getWorldInfo.setThundering(args.checkBoolean(0))
|
world.getWorldInfo.setThundering(args.checkBoolean(0))
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function():number -- Get the current world time.""")
|
@Callback(doc = """function():number -- Get the current world time.""")
|
||||||
def getTime(context: Context, args: Arguments): Array[AnyRef] = {
|
def getTime(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(world.getWorldTime)
|
result(world.getWorldTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(value:number) -- Set the current world time.""")
|
@Callback(doc = """function(value:number) -- Set the current world time.""")
|
||||||
def setTime(context: Context, args: Arguments): Array[AnyRef] = {
|
def setTime(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
world.setWorldTime(args.checkDouble(0).toLong)
|
world.setWorldTime(args.checkDouble(0).toLong)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function():number, number, number -- Get the current spawn point coordinates.""")
|
@Callback(doc = """function():number, number, number -- Get the current spawn point coordinates.""")
|
||||||
def getSpawnPoint(context: Context, args: Arguments): Array[AnyRef] = {
|
def getSpawnPoint(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(world.getWorldInfo.getSpawnX, world.getWorldInfo.getSpawnY, world.getWorldInfo.getSpawnZ)
|
result(world.getWorldInfo.getSpawnX, world.getWorldInfo.getSpawnY, world.getWorldInfo.getSpawnZ)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number) -- Set the spawn point coordinates.""")
|
@Callback(doc = """function(x:number, y:number, z:number) -- Set the spawn point coordinates.""")
|
||||||
def setSpawnPoint(context: Context, args: Arguments): Array[AnyRef] = {
|
def setSpawnPoint(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
world.getWorldInfo.setSpawnPosition(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))
|
world.getWorldInfo.setSpawnPosition(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number, sound:string, range:number) -- Play a sound at the specified coordinates.""")
|
@Callback(doc = """function(x:number, y:number, z:number, sound:string, range:number) -- Play a sound at the specified coordinates.""")
|
||||||
def playSoundAt(context: Context, args: Arguments): Array[AnyRef] = {
|
def playSoundAt(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
val (x, y, z) = (args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))
|
val (x, y, z) = (args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))
|
||||||
val sound = args.checkString(3)
|
val sound = args.checkString(3)
|
||||||
val range = args.checkInteger(4)
|
val range = args.checkInteger(4)
|
||||||
@ -402,25 +427,25 @@ object DebugCard {
|
|||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number):number -- Get the ID of the block at the specified coordinates.""")
|
@Callback(doc = """function(x:number, y:number, z:number):number -- Get the ID of the block at the specified coordinates.""")
|
||||||
def getBlockId(context: Context, args: Arguments): Array[AnyRef] = {
|
def getBlockId(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(Block.getIdFromBlock(world.getBlock(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))))
|
result(Block.getIdFromBlock(world.getBlock(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number):number -- Get the metadata of the block at the specified coordinates.""")
|
@Callback(doc = """function(x:number, y:number, z:number):number -- Get the metadata of the block at the specified coordinates.""")
|
||||||
def getMetadata(context: Context, args: Arguments): Array[AnyRef] = {
|
def getMetadata(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(world.getBlockMetadata(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2)))
|
result(world.getBlockMetadata(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number):number -- Check whether the block at the specified coordinates is loaded.""")
|
@Callback(doc = """function(x:number, y:number, z:number):number -- Check whether the block at the specified coordinates is loaded.""")
|
||||||
def isLoaded(context: Context, args: Arguments): Array[AnyRef] = {
|
def isLoaded(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(world.blockExists(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2)))
|
result(world.blockExists(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number):number -- Check whether the block at the specified coordinates has a tile entity.""")
|
@Callback(doc = """function(x:number, y:number, z:number):number -- Check whether the block at the specified coordinates has a tile entity.""")
|
||||||
def hasTileEntity(context: Context, args: Arguments): Array[AnyRef] = {
|
def hasTileEntity(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
val (x, y, z) = (args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))
|
val (x, y, z) = (args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))
|
||||||
val block = world.getBlock(x, y, z)
|
val block = world.getBlock(x, y, z)
|
||||||
result(block != null && block.hasTileEntity(world.getBlockMetadata(x, y, z)))
|
result(block != null && block.hasTileEntity(world.getBlockMetadata(x, y, z)))
|
||||||
@ -428,7 +453,7 @@ object DebugCard {
|
|||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number):table -- Get the NBT of the block at the specified coordinates.""")
|
@Callback(doc = """function(x:number, y:number, z:number):table -- Get the NBT of the block at the specified coordinates.""")
|
||||||
def getTileNBT(context: Context, args: Arguments): Array[AnyRef] = {
|
def getTileNBT(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
val (x, y, z) = (args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))
|
val (x, y, z) = (args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))
|
||||||
world.getTileEntity(x, y, z) match {
|
world.getTileEntity(x, y, z) match {
|
||||||
case tileEntity: TileEntity => result(toNbt(tileEntity.writeToNBT _).toTypedMap)
|
case tileEntity: TileEntity => result(toNbt(tileEntity.writeToNBT _).toTypedMap)
|
||||||
@ -438,7 +463,7 @@ object DebugCard {
|
|||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number, nbt:table):boolean -- Set the NBT of the block at the specified coordinates.""")
|
@Callback(doc = """function(x:number, y:number, z:number, nbt:table):boolean -- Set the NBT of the block at the specified coordinates.""")
|
||||||
def setTileNBT(context: Context, args: Arguments): Array[AnyRef] = {
|
def setTileNBT(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
val (x, y, z) = (args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))
|
val (x, y, z) = (args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))
|
||||||
world.getTileEntity(x, y, z) match {
|
world.getTileEntity(x, y, z) match {
|
||||||
case tileEntity: TileEntity =>
|
case tileEntity: TileEntity =>
|
||||||
@ -456,25 +481,25 @@ object DebugCard {
|
|||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number):number -- Get the light opacity of the block at the specified coordinates.""")
|
@Callback(doc = """function(x:number, y:number, z:number):number -- Get the light opacity of the block at the specified coordinates.""")
|
||||||
def getLightOpacity(context: Context, args: Arguments): Array[AnyRef] = {
|
def getLightOpacity(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(world.getBlockLightOpacity(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2)))
|
result(world.getBlockLightOpacity(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number):number -- Get the light value (emission) of the block at the specified coordinates.""")
|
@Callback(doc = """function(x:number, y:number, z:number):number -- Get the light value (emission) of the block at the specified coordinates.""")
|
||||||
def getLightValue(context: Context, args: Arguments): Array[AnyRef] = {
|
def getLightValue(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(world.getBlockLightValue(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2)))
|
result(world.getBlockLightValue(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number):number -- Get whether the block at the specified coordinates is directly under the sky.""")
|
@Callback(doc = """function(x:number, y:number, z:number):number -- Get whether the block at the specified coordinates is directly under the sky.""")
|
||||||
def canSeeSky(context: Context, args: Arguments): Array[AnyRef] = {
|
def canSeeSky(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
result(world.canBlockSeeTheSky(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2)))
|
result(world.canBlockSeeTheSky(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number, id:number or string, meta:number):number -- Set the block at the specified coordinates.""")
|
@Callback(doc = """function(x:number, y:number, z:number, id:number or string, meta:number):number -- Set the block at the specified coordinates.""")
|
||||||
def setBlock(context: Context, args: Arguments): Array[AnyRef] = {
|
def setBlock(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
val block = if (args.isInteger(3)) Block.getBlockById(args.checkInteger(3)) else Block.getBlockFromName(args.checkString(3))
|
val block = if (args.isInteger(3)) Block.getBlockById(args.checkInteger(3)) else Block.getBlockFromName(args.checkString(3))
|
||||||
val metadata = args.checkInteger(4)
|
val metadata = args.checkInteger(4)
|
||||||
result(world.setBlock(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2), block, metadata, 3))
|
result(world.setBlock(args.checkInteger(0), args.checkInteger(1), args.checkInteger(2), block, metadata, 3))
|
||||||
@ -482,7 +507,7 @@ object DebugCard {
|
|||||||
|
|
||||||
@Callback(doc = """function(x1:number, y1:number, z1:number, x2:number, y2:number, z2:number, id:number or string, meta:number):number -- Set all blocks in the area defined by the two corner points (x1, y1, z1) and (x2, y2, z2).""")
|
@Callback(doc = """function(x1:number, y1:number, z1:number, x2:number, y2:number, z2:number, id:number or string, meta:number):number -- Set all blocks in the area defined by the two corner points (x1, y1, z1) and (x2, y2, z2).""")
|
||||||
def setBlocks(context: Context, args: Arguments): Array[AnyRef] = {
|
def setBlocks(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
val (xMin, yMin, zMin) = (args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))
|
val (xMin, yMin, zMin) = (args.checkInteger(0), args.checkInteger(1), args.checkInteger(2))
|
||||||
val (xMax, yMax, zMax) = (args.checkInteger(3), args.checkInteger(4), args.checkInteger(5))
|
val (xMax, yMax, zMax) = (args.checkInteger(3), args.checkInteger(4), args.checkInteger(5))
|
||||||
val block = if (args.isInteger(6)) Block.getBlockById(args.checkInteger(6)) else Block.getBlockFromName(args.checkString(6))
|
val block = if (args.isInteger(6)) Block.getBlockById(args.checkInteger(6)) else Block.getBlockFromName(args.checkString(6))
|
||||||
@ -501,7 +526,7 @@ object DebugCard {
|
|||||||
|
|
||||||
@Callback(doc = """function(id:string, count:number, damage:number, nbt:string, x:number, y:number, z:number, side:number):boolean - Insert an item stack into the inventory at the specified location. NBT tag is expected in JSON format.""")
|
@Callback(doc = """function(id:string, count:number, damage:number, nbt:string, x:number, y:number, z:number, side:number):boolean - Insert an item stack into the inventory at the specified location. NBT tag is expected in JSON format.""")
|
||||||
def insertItem(context: Context, args: Arguments): Array[AnyRef] = {
|
def insertItem(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
val item = Item.itemRegistry.getObject(args.checkString(0)).asInstanceOf[Item]
|
val item = Item.itemRegistry.getObject(args.checkString(0)).asInstanceOf[Item]
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
throw new IllegalArgumentException("invalid item id")
|
throw new IllegalArgumentException("invalid item id")
|
||||||
@ -523,7 +548,7 @@ object DebugCard {
|
|||||||
|
|
||||||
@Callback(doc = """function(x:number, y:number, z:number, slot:number[, count:number]):number - Reduce the size of an item stack in the inventory at the specified location.""")
|
@Callback(doc = """function(x:number, y:number, z:number, slot:number[, count:number]):number - Reduce the size of an item stack in the inventory at the specified location.""")
|
||||||
def removeItem(context: Context, args: Arguments): Array[AnyRef] = {
|
def removeItem(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
val position = BlockPosition(args.checkDouble(0), args.checkDouble(1), args.checkDouble(2), world)
|
val position = BlockPosition(args.checkDouble(0), args.checkDouble(1), args.checkDouble(2), world)
|
||||||
InventoryUtils.inventoryAt(position) match {
|
InventoryUtils.inventoryAt(position) match {
|
||||||
case Some(inventory) =>
|
case Some(inventory) =>
|
||||||
@ -538,7 +563,7 @@ object DebugCard {
|
|||||||
|
|
||||||
@Callback(doc = """function(id:string, amount:number, x:number, y:number, z:number, side:number):boolean - Insert some fluid into the tank at the specified location.""")
|
@Callback(doc = """function(id:string, amount:number, x:number, y:number, z:number, side:number):boolean - Insert some fluid into the tank at the specified location.""")
|
||||||
def insertFluid(context: Context, args: Arguments): Array[AnyRef] = {
|
def insertFluid(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
val fluid = FluidRegistry.getFluid(args.checkString(0))
|
val fluid = FluidRegistry.getFluid(args.checkString(0))
|
||||||
if (fluid == null) {
|
if (fluid == null) {
|
||||||
throw new IllegalArgumentException("invalid fluid id")
|
throw new IllegalArgumentException("invalid fluid id")
|
||||||
@ -554,7 +579,7 @@ object DebugCard {
|
|||||||
|
|
||||||
@Callback(doc = """function(amount:number, x:number, y:number, z:number, side:number):boolean - Remove some fluid from a tank at the specified location.""")
|
@Callback(doc = """function(amount:number, x:number, y:number, z:number, side:number):boolean - Remove some fluid from a tank at the specified location.""")
|
||||||
def removeFluid(context: Context, args: Arguments): Array[AnyRef] = {
|
def removeFluid(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
checkEnabled()
|
checkAccess()
|
||||||
val amount = args.checkInteger(0)
|
val amount = args.checkInteger(0)
|
||||||
val position = BlockPosition(args.checkDouble(1), args.checkDouble(2), args.checkDouble(3), world)
|
val position = BlockPosition(args.checkDouble(1), args.checkDouble(2), args.checkDouble(3), world)
|
||||||
val side = args.checkSideAny(4)
|
val side = args.checkSideAny(4)
|
||||||
@ -568,11 +593,13 @@ object DebugCard {
|
|||||||
|
|
||||||
override def load(nbt: NBTTagCompound) {
|
override def load(nbt: NBTTagCompound) {
|
||||||
super.load(nbt)
|
super.load(nbt)
|
||||||
|
ctx = AccessContext.load(nbt)
|
||||||
world = DimensionManager.getWorld(nbt.getInteger("dimension"))
|
world = DimensionManager.getWorld(nbt.getInteger("dimension"))
|
||||||
}
|
}
|
||||||
|
|
||||||
override def save(nbt: NBTTagCompound) {
|
override def save(nbt: NBTTagCompound) {
|
||||||
super.save(nbt)
|
super.save(nbt)
|
||||||
|
ctx.foreach(_.save(nbt))
|
||||||
nbt.setInteger("dimension", world.provider.dimensionId)
|
nbt.setInteger("dimension", world.provider.dimensionId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user