summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorraven <citrons@mondecitronne.com>2026-03-21 14:15:43 -0500
committerraven <citrons@mondecitronne.com>2026-03-21 14:15:43 -0500
commitf29c5d9c8a25d1271b51203f0a481fc33f08d564 (patch)
tree78ec271a4b58dc5798d09293250288ccb0cad88e
parent426709baff567ea0666cea9b317c5c3dddfc53f9 (diff)
/tp command
-rw-r--r--server/commands.go89
-rw-r--r--server/coords.go4
-rw-r--r--server/player.go16
3 files changed, 104 insertions, 5 deletions
diff --git a/server/commands.go b/server/commands.go
index 8154b7b..1bad5f6 100644
--- a/server/commands.go
+++ b/server/commands.go
@@ -2,6 +2,7 @@ package server
import (
"sort"
+ "strconv"
"strings"
)
@@ -59,6 +60,74 @@ func usage(cmd string) string {
}
var commands = map[string]commandHandler {
+ "tp": func(ctx commandCtx) string {
+ var (
+ sourcePlayer string
+ destPlayer string
+ )
+ ctx.arg.flags["-p"] = func(arg *arguments) {
+ sourcePlayer, _ = arg.nextArg()
+ }
+ ctx.arg.flags["-t"] = func(arg *arguments) {
+ destPlayer, _ = arg.nextArg()
+ }
+ for name, pl := range(ctx.server.players) {
+ if ctx.sender == pl {
+ sourcePlayer = name
+ }
+ }
+ args := ctx.arg.allArgs()
+ if sourcePlayer == "" {
+ return "Teleport who?"
+ }
+ if sourcePlayer != "" && ctx.server.players[sourcePlayer] == nil {
+ return "Unknown player: " + sourcePlayer
+ }
+ if destPlayer != "" && ctx.server.players[destPlayer] == nil {
+ return "Unknown player: " + destPlayer
+ }
+ if len(args) == 0 {
+ if destPlayer == "" {
+ return usage("tp")
+ }
+ var (
+ pl1 = ctx.server.players[sourcePlayer]
+ pl2 = ctx.server.players[destPlayer]
+ )
+ pl2.GetInfo(ctx.server, func(_ string, state playerState) {
+ pl1.MovePlayer(ctx.server, state.Pos, state.Facing)
+ })
+ } else {
+ if destPlayer != "" {
+ return usage("tp")
+ }
+ var values []float64
+ for _, value := range args {
+ n, err := strconv.ParseFloat(value, 64)
+ if err != nil {
+ return usage("tp")
+ }
+ values = append(values, n)
+ }
+ if len(values) < 3 {
+ return usage("tp")
+ }
+ pos := entityPos {
+ fromFloat(values[0]),
+ fromFloat(values[1]),
+ fromFloat(values[2]),
+ }
+ pl := ctx.server.players[sourcePlayer]
+ if len(values) == 3 {
+ pl.MovePlayer(ctx.server, pos, entityFacing {})
+ } else if len(values) == 4 {
+ pl.ChangeLevel(ctx.server, levelId(values[3]), pos)
+ } else {
+ return usage("tp")
+ }
+ }
+ return ""
+ },
"op": func(ctx commandCtx) string {
name, ok := ctx.arg.nextArg()
if !ok {
@@ -130,6 +199,7 @@ var commands = map[string]commandHandler {
}
var commandAuth = map[string]authLevel {
+ "tp": cheatAuth,
"op": opAuth,
"deop": opAuth,
"save": opAuth,
@@ -137,6 +207,15 @@ var commandAuth = map[string]authLevel {
}
var help = map[string][]string {
+ "tp": []string {
+ "/tp [-p player] <-t player | <x> <y> <z> [level]>",
+ "* -p: Player to teleport (default: you)",
+ "* -t: Teleport to player",
+ "Examples:",
+ "* /tp 128 128 128 4",
+ "* /tp -p alice -t eve",
+ "* /tp -p bob 0 -1000000 0",
+ },
"op": []string {
"/op <player>",
"Grant operator status",
@@ -160,10 +239,14 @@ var help = map[string][]string {
type arguments struct {
rd *strings.Reader
+ flags map[string]func(*arguments)
}
func parseArgs(command string) arguments {
- return arguments {strings.NewReader(command)}
+ return arguments {
+ strings.NewReader(command),
+ make(map[string]func(*arguments)),
+ }
}
func (arg *arguments) nextArg() (string, bool) {
@@ -207,6 +290,10 @@ func (arg *arguments) nextArg() (string, bool) {
}
out.WriteByte(b)
}
+ if arg.flags[out.String()] != nil {
+ arg.flags[out.String()](arg)
+ return arg.nextArg()
+ }
return out.String(), true
}
diff --git a/server/coords.go b/server/coords.go
index ebe71c9..7add606 100644
--- a/server/coords.go
+++ b/server/coords.go
@@ -17,6 +17,10 @@ type entityPos struct {
X, Y, Z entityCoord
}
+func fromFloat(f float64) entityCoord {
+ return entityCoord(f * 32)
+}
+
func entityToBlock(pos entityPos) blockPos {
return blockPos {
blockCoord(pos.X >> 5),
diff --git a/server/player.go b/server/player.go
index ba4767c..396a152 100644
--- a/server/player.go
+++ b/server/player.go
@@ -28,9 +28,10 @@ type playerState struct {
}
const (
- defaultAuth = iota
- opAuth
- ConsoleAuth
+ defaultAuth
+ cheatAuth = 100
+ opAuth = 200
+ ConsoleAuth = 900
)
var playerNameRegex = regexp.MustCompile("^[.-_a-zA-Z0-9]*$")
@@ -160,7 +161,14 @@ func (p *player) ChangeLevel(from phony.Actor, lvl levelId, pos entityPos) {
func (p *player) MovePlayer(
from phony.Actor, pos entityPos, facing entityFacing) {
p.Act(from, func() {
- p.level.OnMovePlayer(p, pos, facing)
+ p.client.SendPacket(p, &classic.SpawnPlayer {
+ PlayerId: -1,
+ X: classic.FShort(pos.X),
+ Y: classic.FShort(pos.Y),
+ Z: classic.FShort(pos.Z),
+ Yaw: facing.Yaw,
+ Pitch: facing.Pitch,
+ })
})
}