Skip to content

Commit

Permalink
Merge pull request #78 from metaworking/spatial-static-objects
Browse files Browse the repository at this point in the history
Spatial static objects
  • Loading branch information
indiest authored Jun 21, 2024
2 parents d09d56c + 08acc5f commit 7ec43c8
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 7 deletions.
7 changes: 7 additions & 0 deletions pkg/channeld/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ var Event_AuthComplete = &Event[AuthEventData]{}

var Event_FsmDisallowed = &Event[*Connection]{}

type EntityChannelSpatiallyOwnedEventData struct {
EntityChannel *Channel
SpatialChanel *Channel
}

var Event_EntityChannelSpatiallyOwned = &Event[EntityChannelSpatiallyOwnedEventData]{}

type EventData interface {
}

Expand Down
40 changes: 40 additions & 0 deletions pkg/channeld/message_spatial.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,46 @@ func handleCreateEntityChannel(ctx MessageContext) {
newChannel.Logger().Error("failed to unmarshal data message for the new channel", zap.Error(err))
} else {
newChannel.InitData(dataMsg, msg.MergeOptions)

// If the entity channel is created from GLOBAL channel(master server), but its data contains spatial info,
// we should set the owner of the entity channel to the spatial channel's.
if ctx.Channel == globalChannel {
dataMsgWithSpatialInfo, ok := dataMsg.(EntityChannelDataWithSpatialInfo)
if ok {
spatialInfo := dataMsgWithSpatialInfo.GetSpatialInfo()
if spatialInfo != nil {
spatialChId, err := spatialController.GetChannelId(*spatialInfo)
if err != nil {
ctx.Connection.Logger().Error("failed to set the entity channel owner to the spatial channel's", zap.Error(err))
} else {
spatialCh := GetChannel(spatialChId)
if spatialCh == nil {
newChannel.Logger().Error("failed to set the entity channel owner as the spatial channel does not exist",
zap.Uint32("spatialChId", uint32(spatialChId)))
} else {
ownerConn := spatialCh.GetOwner()
if ownerConn != nil && !ownerConn.IsClosing() {
newChannel.SetOwner(ownerConn)
newChannel.Logger().Info("set the entity channel owner to the spatial channel's",
zap.Uint32("spatialChId", uint32(spatialChId)))

Event_EntityChannelSpatiallyOwned.Broadcast(EntityChannelSpatiallyOwnedEventData{newChannel, spatialCh})

// Sub-and-send happens at the end of this function

// Set the messge context so that the CreateChannelResultMessage will be sent to the owner
// instead of the message sender (the master server).
ctx.Connection = ownerConn
ctx.ChannelId = uint32(spatialChId)
} else {
newChannel.Logger().Warn("the entity's owning spatial channel does not have an owner connection",
zap.Uint32("spatialChId", uint32(spatialChId)))
}
}
}
}
}
}
}
} else {
// Channel data should always be initialized
Expand Down
12 changes: 12 additions & 0 deletions pkg/channeld/spatial.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,10 @@ func (ctl *StaticGrid2DSpatialController) GetAdjacentChannels(spatialChannelId c
return channelIds, nil
}

type EntityChannelDataWithSpatialInfo interface {
GetSpatialInfo() *common.SpatialInfo
}

func (ctl *StaticGrid2DSpatialController) CreateChannels(ctx MessageContext) ([]*Channel, error) {
ctl.initServerConnections()
serverIndex := ctl.nextServerIndex()
Expand Down Expand Up @@ -461,6 +465,14 @@ func (ctl *StaticGrid2DSpatialController) CreateChannels(ctx MessageContext) ([]
Msg: readyMsg,
})
}

// ...and the master server too.
if globalChannel.ownerConnection != nil {
globalChannel.ownerConnection.Send(MessageContext{
MsgType: channeldpb.MessageType_SPATIAL_CHANNELS_READY,
Msg: readyMsg,
})
}
}

return channels, nil
Expand Down
23 changes: 17 additions & 6 deletions pkg/unreal/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
func InitMessageHandlers() {
channeld.RegisterMessageHandler(uint32(unrealpb.MessageType_SPAWN), &channeldpb.ServerForwardMessage{}, handleUnrealSpawnObject)
channeld.RegisterMessageHandler(uint32(unrealpb.MessageType_DESTROY), &channeldpb.ServerForwardMessage{}, handleUnrealDestroyObject)

channeld.Event_EntityChannelSpatiallyOwned.Listen(handleEntityChannelSpatiallyOwned)
}

// Executed in the spatial channels or the GLOBAL channel (no-spatial scenario)
Expand Down Expand Up @@ -49,12 +51,7 @@ func handleUnrealSpawnObject(ctx channeld.MessageContext) {
// Update the message's spatial channelId based on the actor's location
oldChId := *spawnMsg.ChannelId
if spawnMsg.Location != nil {
// Swap the Y and Z as UE uses the Z-Up rule but channeld uses the Y-up rule.
spatialChId, err := channeld.GetSpatialController().GetChannelId(common.SpatialInfo{
X: float64(*spawnMsg.Location.X),
Y: float64(*spawnMsg.Location.Z),
Z: float64(*spawnMsg.Location.Y),
})
spatialChId, err := channeld.GetSpatialController().GetChannelId(*spawnMsg.Location.ToSpatialInfo())
if err != nil {
ctx.Connection.Logger().Warn("failed to GetChannelId", zap.Error(err),
zap.Float32("x", *spawnMsg.Location.X),
Expand Down Expand Up @@ -121,6 +118,8 @@ type UnrealObjectEntityData interface {
SetObjRef(objRef *unrealpb.UnrealObjectRef)
}

// Add the SpatialEntityState to the spatial channel data. If an entity doesn't exist in the spatial channel data,
// handover will not work properly.
func addSpatialEntity(ch *channeld.Channel, objRef *unrealpb.UnrealObjectRef) {
if ch.Type() != channeldpb.ChannelType_SPATIAL {
return
Expand Down Expand Up @@ -188,3 +187,15 @@ func handleUnrealDestroyObject(ctx channeld.MessageContext) {
channeld.RemoveChannel(entityCh)
}
}

func handleEntityChannelSpatiallyOwned(data channeld.EntityChannelSpatiallyOwnedEventData) {
dataMsgWithObjRef, ok := data.EntityChannel.GetDataMessage().(unrealpb.EntityChannelDataWithObjRef)
if !ok {
data.EntityChannel.Logger().Error("spatial-owned entity channel data doesn't implement EntityChannelDataWithObjRef")
return
}

data.SpatialChanel.Execute(func(ch *channeld.Channel) {
addSpatialEntity(ch, dataMsgWithObjRef.GetObjRef())
})
}
15 changes: 15 additions & 0 deletions pkg/unrealpb/extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@ import (
"github.com/metaworking/channeld/pkg/common"
)

func (vec *FVector) ToSpatialInfo() *common.SpatialInfo {
info := &common.SpatialInfo{}
if vec.X != nil {
info.X = float64(*vec.X)
}
// Swap the Y and Z as UE uses the Z-Up rule but channeld uses the Y-up rule.
if vec.Y != nil {
info.Z = float64(*vec.Y)
}
if vec.Z != nil {
info.Y = float64(*vec.Z)
}
return info
}

// Implement [channeld.HandoverDataWithPayload]
func (data *HandoverData) ClearPayload() {
data.ChannelData = nil
Expand Down
2 changes: 1 addition & 1 deletion pkg/unrealpb/unreal_common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ message HandoverContext {
}

// Wrapped in ChannelDataHandoverMessage.data
// Implements [channeld.HandoverDataPayload]
// Implements [channeld.HandoverDataWithPayload]
message HandoverData {
repeated HandoverContext context = 1;
// The channel data message that will be handed over to the destination channel.
Expand Down

0 comments on commit 7ec43c8

Please sign in to comment.