Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions server/player/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ type Config struct {
Locale language.Tag
GameMode world.GameMode

// PermissionLevel is the permission level the client displays for itself.
PermissionLevel session.PermissionLevel

Position mgl64.Vec3
Rotation cube.Rotation
Velocity mgl64.Vec3
Expand Down Expand Up @@ -72,6 +75,7 @@ func (cfg Config) Apply(data *world.EntityData) {
mc: &entity.MovementComputer{Gravity: 0.08, Drag: 0.02, DragBeforeGravity: true},
heldSlot: &slot,
gameMode: conf.GameMode,
permission: conf.PermissionLevel,
skin: conf.Skin,
enchantSeed: conf.EnchantmentSeed,
s: conf.Session,
Expand Down
28 changes: 24 additions & 4 deletions server/player/player.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ type playerData struct {
absorptionHealth float64
scale float64

gameMode world.GameMode
skin skin.Skin
s *session.Session
h Handler
gameMode world.GameMode
permission session.PermissionLevel
skin skin.Skin
s *session.Session
h Handler

inv, offHand, enderChest, ui *inventory.Inventory
armour *inventory.Armour
Expand Down Expand Up @@ -1546,6 +1547,25 @@ func (p *Player) GameMode() world.GameMode {
return p.gameMode
}

// SetPermissionLevel changes the permission level the Player's client displays
// for itself. It unlocks vanilla functionality that the client restricts to a
// permission level, such as the command button in the chat window, but does not
// authorise the Player to do anything by itself: cmd.Allower decides which
// commands a Player may run.
func (p *Player) SetPermissionLevel(level session.PermissionLevel) {
if p.permission == level {
return
}
p.permission = level
p.session().SendAbilities(p)
}

// PermissionLevel returns the permission level the Player's client displays for
// itself, as set by SetPermissionLevel.
func (p *Player) PermissionLevel() session.PermissionLevel {
return p.permission
}

// HasCooldown returns true if the item passed has an active cooldown, meaning it currently cannot be used again. If the
// world.Item passed is nil, HasCooldown always returns false.
func (p *Player) HasCooldown(item world.Item) bool {
Expand Down
1 change: 1 addition & 0 deletions server/session/controllable.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type Controllable interface {
Chat(msg ...any)
ExecuteCommand(commandLine string)
GameMode() world.GameMode
PermissionLevel() PermissionLevel
SetGameMode(mode world.GameMode)
Effects() []effect.Effect

Expand Down
30 changes: 30 additions & 0 deletions server/session/permission.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package session

import (
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
)

// PermissionLevel is the permission level a client displays for itself. It only
// decides what the client shows and allows locally, such as the command button
// in the chat window: the server does not use it to authorise anything. Whether
// a Controllable may run a command is decided by cmd.Allower alone.
type PermissionLevel byte

const (
// PermissionLevelMember is the level of an ordinary client. It is the level
// a Controllable has unless another one is set.
PermissionLevelMember PermissionLevel = iota
// PermissionLevelOperator is the level of a client that vanilla considers
// an operator.
PermissionLevelOperator
)

// abilityPermissions returns the permission level and command permission level
// sent to a client for the PermissionLevel.
func (l PermissionLevel) abilityPermissions() (byte, byte) {
if l == PermissionLevelOperator {
return packet.PermissionLevelOperator, protocol.CommandPermissionLevelGameDirectors
}
return packet.PermissionLevelMember, protocol.CommandPermissionLevelAny
}
5 changes: 3 additions & 2 deletions server/session/player.go
Original file line number Diff line number Diff line change
Expand Up @@ -545,10 +545,11 @@ func (s *Session) SendAbilities(c Controllable) {
if mode.AllowsInteraction() {
abilities |= protocol.AbilityDoorsAndSwitches | protocol.AbilityOpenContainers | protocol.AbilityAttackPlayers | protocol.AbilityAttackMobs
}
permission, commandPermission := c.PermissionLevel().abilityPermissions()
s.writePacket(&packet.UpdateAbilities{AbilityData: protocol.AbilityData{
EntityUniqueID: selfEntityRuntimeID,
PlayerPermissions: packet.PermissionLevelMember,
CommandPermissions: protocol.CommandPermissionLevelAny,
PlayerPermissions: permission,
CommandPermissions: commandPermission,
Layers: []protocol.AbilityLayer{
{
Type: protocol.AbilityLayerTypeBase,
Expand Down