-
Notifications
You must be signed in to change notification settings - Fork 148
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
server/session: Cleaned up and finished refactoring the player/sessio…
…n list code.
- Loading branch information
Showing
4 changed files
with
146 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
package session | ||
|
||
import ( | ||
"github.com/df-mc/dragonfly/server/internal/sliceutil" | ||
"github.com/df-mc/dragonfly/server/player/skin" | ||
"github.com/google/uuid" | ||
"github.com/sandertv/gophertunnel/minecraft/protocol" | ||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet" | ||
"golang.org/x/exp/slices" | ||
"sync" | ||
) | ||
|
||
var sessions = new(sessionList) | ||
|
||
type sessionList struct { | ||
mu sync.Mutex | ||
s []*Session | ||
} | ||
|
||
func (l *sessionList) Add(s *Session) { | ||
l.mu.Lock() | ||
defer l.mu.Unlock() | ||
|
||
l.s = append(l.s, s) | ||
for _, other := range l.s { | ||
// AddStack the player of the session to all sessions currently open, | ||
// and add the players of all sessions currently open to the player list | ||
// of the new session. | ||
l.sendSessionTo(s, other) | ||
if s != other { | ||
l.sendSessionTo(other, s) | ||
} | ||
} | ||
} | ||
|
||
func (l *sessionList) Remove(s *Session) { | ||
l.mu.Lock() | ||
defer l.mu.Unlock() | ||
|
||
for _, other := range l.s { | ||
// Remove the player of the other from the player list of others. | ||
l.unsendSessionFrom(s, other) | ||
} | ||
l.s = sliceutil.DeleteVal(l.s, s) | ||
} | ||
|
||
func (l *sessionList) Lookup(id uuid.UUID) (*Session, bool) { | ||
l.mu.Lock() | ||
defer l.mu.Unlock() | ||
|
||
if index := slices.IndexFunc(l.s, func(session *Session) bool { | ||
return session.ent.UUID() == id | ||
}); index != -1 { | ||
return l.s[index], true | ||
} | ||
return nil, false | ||
} | ||
|
||
func (l *sessionList) sendSessionTo(s, to *Session) { | ||
runtimeID := uint64(1) | ||
|
||
to.entityMutex.Lock() | ||
if s != to { | ||
to.currentEntityRuntimeID += 1 | ||
runtimeID = to.currentEntityRuntimeID | ||
} | ||
to.entityRuntimeIDs[s.ent] = runtimeID | ||
to.entities[runtimeID] = s.ent | ||
to.entityMutex.Unlock() | ||
|
||
to.writePacket(&packet.PlayerList{ | ||
ActionType: packet.PlayerListActionAdd, | ||
Entries: []protocol.PlayerListEntry{{ | ||
UUID: s.ent.UUID(), | ||
EntityUniqueID: int64(runtimeID), | ||
Username: s.conn.IdentityData().DisplayName, | ||
XUID: s.conn.IdentityData().XUID, | ||
Skin: skinToProtocol(s.joinSkin), | ||
}}, | ||
}) | ||
} | ||
|
||
func (l *sessionList) unsendSessionFrom(s, from *Session) { | ||
from.entityMutex.Lock() | ||
delete(from.entities, from.entityRuntimeIDs[s.ent]) | ||
delete(from.entityRuntimeIDs, s.ent) | ||
from.entityMutex.Unlock() | ||
|
||
from.writePacket(&packet.PlayerList{ | ||
ActionType: packet.PlayerListActionRemove, | ||
Entries: []protocol.PlayerListEntry{{UUID: s.ent.UUID()}}, | ||
}) | ||
} | ||
|
||
// skinToProtocol converts a skin to its protocol representation. | ||
func skinToProtocol(s skin.Skin) protocol.Skin { | ||
var animations []protocol.SkinAnimation | ||
for _, animation := range s.Animations { | ||
protocolAnim := protocol.SkinAnimation{ | ||
ImageWidth: uint32(animation.Bounds().Max.X), | ||
ImageHeight: uint32(animation.Bounds().Max.Y), | ||
ImageData: animation.Pix, | ||
FrameCount: float32(animation.FrameCount), | ||
} | ||
switch animation.Type() { | ||
case skin.AnimationHead: | ||
protocolAnim.AnimationType = protocol.SkinAnimationHead | ||
case skin.AnimationBody32x32: | ||
protocolAnim.AnimationType = protocol.SkinAnimationBody32x32 | ||
case skin.AnimationBody128x128: | ||
protocolAnim.AnimationType = protocol.SkinAnimationBody128x128 | ||
} | ||
protocolAnim.ExpressionType = uint32(animation.AnimationExpression) | ||
animations = append(animations, protocolAnim) | ||
} | ||
|
||
return protocol.Skin{ | ||
PlayFabID: s.PlayFabID, | ||
SkinID: uuid.New().String(), | ||
SkinResourcePatch: s.ModelConfig.Encode(), | ||
SkinImageWidth: uint32(s.Bounds().Max.X), | ||
SkinImageHeight: uint32(s.Bounds().Max.Y), | ||
SkinData: s.Pix, | ||
CapeImageWidth: uint32(s.Cape.Bounds().Max.X), | ||
CapeImageHeight: uint32(s.Cape.Bounds().Max.Y), | ||
CapeData: s.Cape.Pix, | ||
SkinGeometry: s.Model, | ||
PersonaSkin: s.Persona, | ||
CapeID: uuid.New().String(), | ||
FullID: uuid.New().String(), | ||
Animations: animations, | ||
Trusted: true, | ||
OverrideAppearance: true, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters