Skip to content

Commit

Permalink
Implementation of a view layer
Browse files Browse the repository at this point in the history
Co-authored-by: RestartFU <[email protected]>
  • Loading branch information
Flonja committed Jan 23, 2024
1 parent 43bbbd0 commit 1b94867
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 1 deletion.
5 changes: 5 additions & 0 deletions server/player/player.go
Original file line number Diff line number Diff line change
Expand Up @@ -2286,6 +2286,11 @@ func (p *Player) Tick(w *world.World, current int64) {
}
}

// ViewLayer ...
func (p *Player) ViewLayer() *world.ViewLayer {
return p.session().ViewLayer()
}

// tickAirSupply tick's the player's air supply, consuming it when underwater, and replenishing it when out of water.
func (p *Player) tickAirSupply(w *world.World) {
if !p.canBreathe(w) {
Expand Down
4 changes: 4 additions & 0 deletions server/session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ type Session struct {

joinMessage, quitMessage string

viewLayer *world.ViewLayer

closeBackground chan struct{}
}

Expand Down Expand Up @@ -164,6 +166,7 @@ func New(conn Conn, maxChunkRadius int, log Logger, joinMessage, quitMessage str
heldSlot: atomic.NewUint32(0),
joinMessage: joinMessage,
quitMessage: quitMessage,
viewLayer: world.NewViewLayer(),
openedWindow: *atomic.NewValue(inventory.New(1, nil)),
}

Expand Down Expand Up @@ -232,6 +235,7 @@ func (s *Session) Close() error {
// close closes the session, which in turn closes the controllable and the connection that the session
// manages.
func (s *Session) close() {
_ = s.viewLayer.Close()
_ = s.c.Close()

// Move UI inventory items to the main inventory.
Expand Down
11 changes: 11 additions & 0 deletions server/session/view_layer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package session

import "github.com/df-mc/dragonfly/server/world"

type LayerViewer interface {
ViewLayer() *world.ViewLayer
}

func (s *Session) ViewLayer() *world.ViewLayer {
return s.viewLayer
}
12 changes: 11 additions & 1 deletion server/session/world.go
Original file line number Diff line number Diff line change
Expand Up @@ -908,9 +908,19 @@ func (s *Session) ViewEntityAction(e world.Entity, a world.EntityAction) {

// ViewEntityState ...
func (s *Session) ViewEntityState(e world.Entity) {
metadata := s.parseEntityMetadata(e)
if v, ok := e.(LayerViewer); ok {
if nt := s.viewLayer.NameTag(v); len(nt) > 0 {
metadata[protocol.EntityDataKeyName] = nt
}
invisFlag := metadata.Flag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagInvisible)
if invis := s.viewLayer.Invisible(v); !invisFlag && invis {
metadata.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagInvisible)
}
}
s.writePacket(&packet.SetActorData{
EntityRuntimeID: s.entityRuntimeID(e),
EntityMetadata: s.parseEntityMetadata(e),
EntityMetadata: metadata,
})
}

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

import (
"sync"
)

type LayerViewer interface {
ViewLayer() *ViewLayer
}

type Layer struct {
nameTag string
invisible bool
}

// ViewLayer is a view layer that can be used to add a layer to the view of a player.
type ViewLayer struct {
viewerMu sync.RWMutex
viewers map[LayerViewer]Layer
}

// NewViewLayer returns a new ViewLayer.
func NewViewLayer() *ViewLayer {
return &ViewLayer{
viewers: map[LayerViewer]Layer{},
}
}

// Viewers returns all viewers of the view layer.
func (v *ViewLayer) Viewers() []LayerViewer {
v.viewerMu.Lock()
defer v.viewerMu.Unlock()
viewers := make([]LayerViewer, 0, len(v.viewers))
for viewer := range v.viewers {
viewers = append(viewers, viewer)
}
return viewers
}

// ViewNameTag adds a name tag to a viewer.
func (v *ViewLayer) ViewNameTag(viewer LayerViewer, nameTag string) {
v.viewerMu.Lock()
defer v.viewerMu.Unlock()

l := v.viewers[viewer]
l.nameTag = nameTag
v.viewers[viewer] = l
}

// NameTag returns the name tag of a viewer.
func (v *ViewLayer) NameTag(viewer LayerViewer) string {
v.viewerMu.Lock()
defer v.viewerMu.Unlock()
return v.viewers[viewer].nameTag
}

// ViewVisible makes a viewer be visible.
func (v *ViewLayer) ViewVisible(viewer LayerViewer) {
v.viewerMu.Lock()
defer v.viewerMu.Unlock()

l := v.viewers[viewer]
l.invisible = false
v.viewers[viewer] = l
}

// ViewInvisible makes a viewer be invisible.
func (v *ViewLayer) ViewInvisible(viewer LayerViewer) {
v.viewerMu.Lock()
defer v.viewerMu.Unlock()

l := v.viewers[viewer]
l.invisible = true
v.viewers[viewer] = l
}

// Invisible returns the invisibility of a viewer.
func (v *ViewLayer) Invisible(viewer LayerViewer) bool {
v.viewerMu.Lock()
defer v.viewerMu.Unlock()
return v.viewers[viewer].invisible
}

// Close closes the view layer.
func (v *ViewLayer) Close() error {
v.viewerMu.Lock()
defer v.viewerMu.Unlock()
for viewer := range v.viewers {
delete(v.viewers, viewer)
}
return nil
}

0 comments on commit 1b94867

Please sign in to comment.