From 7d1185c314d25708323ab893ef1201618dfdf9cd Mon Sep 17 00:00:00 2001 From: xiaonanln Date: Sun, 11 Feb 2018 00:55:19 +0800 Subject: [PATCH 1/2] fix migrating with multiple dispatchers --- components/dispatcher/DispatcherService.go | 33 ++++--- components/game/GameService.go | 63 +++++++----- components/game/game.go | 2 +- engine/consts/consts.go | 2 +- engine/dispatchercluster/dispatchercluster.go | 4 +- engine/entity/Entity.go | 98 +++++++++++++------ engine/entity/EntityManager.go | 2 +- engine/proto/GoWorldConnection.go | 12 ++- engine/proto/proto.go | 10 +- goworld.go | 4 +- 10 files changed, 151 insertions(+), 79 deletions(-) diff --git a/components/dispatcher/DispatcherService.go b/components/dispatcher/DispatcherService.go index e066495f..6716d1c3 100644 --- a/components/dispatcher/DispatcherService.go +++ b/components/dispatcher/DispatcherService.go @@ -205,6 +205,8 @@ func (service *DispatcherService) messageLoop() { service.handleDoSomethingOnSpecifiedClient(dcp, pkt) } else if msgtype == proto.MT_CALL_ENTITY_METHOD_FROM_CLIENT { service.handleCallEntityMethodFromClient(dcp, pkt) + } else if msgtype == proto.MT_QUERY_SPACE_GAMEID_FOR_MIGRATE { + service.handleQuerySpaceGameIDForMigrate(dcp, pkt) } else if msgtype == proto.MT_MIGRATE_REQUEST { service.handleMigrateRequest(dcp, pkt) } else if msgtype == proto.MT_REAL_MIGRATE { @@ -616,28 +618,33 @@ func (service *DispatcherService) handleCallFilteredClientProxies(dcp *dispatche service.broadcastToGateClients(pkt) } -func (service *DispatcherService) handleMigrateRequest(dcp *dispatcherClientProxy, pkt *netutil.Packet) { - entityID := pkt.ReadEntityID() - spaceID := pkt.ReadEntityID() +func (service *DispatcherService) handleQuerySpaceGameIDForMigrate(dcp *dispatcherClientProxy, pkt *netutil.Packet) { + spaceid := pkt.ReadEntityID() if consts.DEBUG_PACKETS { - gwlog.Debugf("Entity %s is migrating to space %s", entityID, spaceID) + gwlog.Debugf("%s.handleQuerySpaceGameIDForMigrate: spaceid=%s", service, spaceid) } - // mark the entity as migrating - - spaceDispatchInfo := service.entityDispatchInfos[spaceID] - var spaceLoc uint16 + spaceDispatchInfo := service.entityDispatchInfos[spaceid] + var gameid uint16 if spaceDispatchInfo != nil { - spaceLoc = spaceDispatchInfo.gameid + gameid = spaceDispatchInfo.gameid } + pkt.AppendUint16(gameid) + // send the packet back + dcp.SendPacket(pkt) +} - pkt.AppendUint16(spaceLoc) // append the space game location to the packet +func (service *DispatcherService) handleMigrateRequest(dcp *dispatcherClientProxy, pkt *netutil.Packet) { + entityID := pkt.ReadEntityID() + spaceID := pkt.ReadEntityID() + spaceGameID := pkt.ReadUint16() - if spaceLoc > 0 { // almost true - entityDispatchInfo := service.setEntityDispatcherInfoForWrite(entityID) - entityDispatchInfo.blockRPC(consts.DISPATCHER_MIGRATE_TIMEOUT) + if consts.DEBUG_PACKETS { + gwlog.Debugf("Entity %s is migrating to space %s @ game%d", entityID, spaceID, spaceGameID) } + entityDispatchInfo := service.setEntityDispatcherInfoForWrite(entityID) + entityDispatchInfo.blockRPC(consts.DISPATCHER_MIGRATE_TIMEOUT) dcp.SendPacket(pkt) } diff --git a/components/game/GameService.go b/components/game/GameService.go index 1ac40a26..200671c9 100644 --- a/components/game/GameService.go +++ b/components/game/GameService.go @@ -33,7 +33,7 @@ const ( rsFreezed ) -type _GameService struct { +type GameService struct { config *config.GameConfig id uint16 gameDelegate IGameDelegate @@ -50,8 +50,8 @@ type _GameService struct { //collectEntitySycnInfosReply chan interface{} } -func newGameService(gameid uint16, delegate IGameDelegate) *_GameService { - return &_GameService{ +func newGameService(gameid uint16, delegate IGameDelegate) *GameService { + return &GameService{ id: gameid, gameDelegate: delegate, //registeredServices: map[string]entity.EntityIDSet{}, @@ -65,7 +65,7 @@ func newGameService(gameid uint16, delegate IGameDelegate) *_GameService { } } -func (gs *_GameService) run(restore bool) { +func (gs *GameService) run(restore bool) { gs.runState.Store(rsRunning) if !restore { @@ -82,7 +82,7 @@ func (gs *_GameService) run(restore bool) { gwutils.RepeatUntilPanicless(gs.serveRoutine) } -func (gs *_GameService) serveRoutine() { +func (gs *GameService) serveRoutine() { cfg := config.GetGame(gameid) gs.config = cfg gs.positionSyncInterval = time.Millisecond * time.Duration(cfg.PositionSyncIntervalMS) @@ -112,7 +112,9 @@ func (gs *_GameService) serveRoutine() { method := pkt.ReadVarStr() args := pkt.ReadArgs() gs.HandleCallEntityMethod(eid, method, args, "") - } else if msgtype == proto.MT_MIGRATE_REQUEST { // migrate request sent to dispatcher is sent back + } else if msgtype == proto.MT_QUERY_SPACE_GAMEID_FOR_MIGRATE_ACK { + gs.HandleQuerySpaceGameIDForMigrateAck(pkt) + } else if msgtype == proto.MT_MIGRATE_REQUEST_ACK { gs.HandleMigrateRequestAck(pkt) } else if msgtype == proto.MT_REAL_MIGRATE { gs.HandleRealMigrate(pkt) @@ -186,12 +188,12 @@ func (gs *_GameService) serveRoutine() { } } -func (gs *_GameService) waitPostsComplete() { +func (gs *GameService) waitPostsComplete() { gwlog.Infof("waiting for posts to complete ...") post.Tick() // just tick is Ok, tick will consume all posts } -func (gs *_GameService) doTerminate() { +func (gs *GameService) doTerminate() { // wait for all posts to complete gs.waitPostsComplete() // wait for all async to clear @@ -211,7 +213,7 @@ func (gs *_GameService) doTerminate() { var freezePacker = netutil.MessagePackMsgPacker{} -func (gs *_GameService) doFreeze() { +func (gs *GameService) doFreeze() { // wait for all posts to complete st := time.Now() gs.waitPostsComplete() @@ -266,7 +268,7 @@ func freezeFilename(gameid uint16) string { return fmt.Sprintf("game%d_freezed.dat", gameid) } -func (gs *_GameService) doRestore() error { +func (gs *GameService) doRestore() error { t0 := time.Now() freezeFilename := freezeFilename(gameid) data, err := ioutil.ReadFile(freezeFilename) @@ -286,25 +288,25 @@ func (gs *_GameService) doRestore() error { return err } -func (gs *_GameService) String() string { - return fmt.Sprintf("_GameService<%d>", gs.id) +func (gs *GameService) String() string { + return fmt.Sprintf("GameService<%d>", gs.id) } -func (gs *_GameService) HandleCreateEntityAnywhere(entityid common.EntityID, typeName string, data map[string]interface{}) { +func (gs *GameService) HandleCreateEntityAnywhere(entityid common.EntityID, typeName string, data map[string]interface{}) { if consts.DEBUG_PACKETS { gwlog.Debugf("%s.handleCreateEntityAnywhere: %s, typeName=%s, data=%v", gs, entityid, typeName, data) } entity.OnCreateEntityAnywhere(entityid, typeName, data) } -func (gs *_GameService) HandleLoadEntityAnywhere(typeName string, entityID common.EntityID) { +func (gs *GameService) HandleLoadEntityAnywhere(typeName string, entityID common.EntityID) { if consts.DEBUG_PACKETS { gwlog.Debugf("%s.handleLoadEntityAnywhere: typeName=%s, entityID=%s", gs, typeName, entityID) } entity.LoadEntityLocally(typeName, entityID) } -func (gs *_GameService) HandleDeclareService(entityID common.EntityID, serviceName string) { +func (gs *GameService) HandleDeclareService(entityID common.EntityID, serviceName string) { // tell the entity that it is registered successfully if consts.DEBUG_PACKETS { gwlog.Debugf("%s.handleDeclareService: %s declares %s", gs, entityID, serviceName) @@ -312,7 +314,7 @@ func (gs *_GameService) HandleDeclareService(entityID common.EntityID, serviceNa entity.OnDeclareService(serviceName, entityID) } -func (gs *_GameService) HandleUndeclareService(entityID common.EntityID, serviceName string) { +func (gs *GameService) HandleUndeclareService(entityID common.EntityID, serviceName string) { // tell the entity that it is registered successfully if consts.DEBUG_PACKETS { gwlog.Debugf("%s.HandleUndeclareService: %s undeclares %s", gs, entityID, serviceName) @@ -320,17 +322,17 @@ func (gs *_GameService) HandleUndeclareService(entityID common.EntityID, service entity.OnUndeclareService(serviceName, entityID) } -func (gs *_GameService) HandleNotifyAllGamesConnected() { +func (gs *GameService) HandleNotifyAllGamesConnected() { // all games are connected gwlog.Infof("All games connected.") gs.gameDelegate.OnGameReady() } -func (gs *_GameService) HandleGateDisconnected(gateid uint16) { +func (gs *GameService) HandleGateDisconnected(gateid uint16) { entity.OnGateDisconnected(gateid) } -func (gs *_GameService) HandleStartFreezeGameAck(dispid uint16) { +func (gs *GameService) HandleStartFreezeGameAck(dispid uint16) { gwlog.Infof("Start freeze game ACK of dispatcher %d is received, checking ...", dispid) gs.dispatcherStartFreezeAcks[dispid-1] = true for _, acked := range gs.dispatcherStartFreezeAcks { @@ -342,7 +344,7 @@ func (gs *_GameService) HandleStartFreezeGameAck(dispid uint16) { gs.runState.Store(rsFreezing) } -func (gs *_GameService) HandleSyncPositionYawFromClient(pkt *netutil.Packet) { +func (gs *GameService) HandleSyncPositionYawFromClient(pkt *netutil.Packet) { //gwlog.Infof("handleSyncPositionYawFromClient: payload %d", len(pkt.UnreadPayload())) payload := pkt.UnreadPayload() payloadLen := len(payload) @@ -356,14 +358,14 @@ func (gs *_GameService) HandleSyncPositionYawFromClient(pkt *netutil.Packet) { } } -func (gs *_GameService) HandleCallEntityMethod(entityID common.EntityID, method string, args [][]byte, clientid common.ClientID) { +func (gs *GameService) HandleCallEntityMethod(entityID common.EntityID, method string, args [][]byte, clientid common.ClientID) { if consts.DEBUG_PACKETS { gwlog.Debugf("%s.handleCallEntityMethod: %s.%s(%v)", gs, entityID, method, args) } entity.OnCall(entityID, method, args, clientid) } -func (gs *_GameService) HandleNotifyClientConnected(clientid common.ClientID, gateid uint16) { +func (gs *GameService) HandleNotifyClientConnected(clientid common.ClientID, gateid uint16) { client := entity.MakeGameClient(clientid, gateid) if consts.DEBUG_PACKETS { gwlog.Debugf("%s.handleNotifyClientConnected: %s", gs, client) @@ -373,7 +375,7 @@ func (gs *_GameService) HandleNotifyClientConnected(clientid common.ClientID, ga entity.CreateEntityLocally(gs.config.BootEntity, nil, client) } -func (gs *_GameService) HandleNotifyClientDisconnected(clientid common.ClientID) { +func (gs *GameService) HandleNotifyClientDisconnected(clientid common.ClientID) { if consts.DEBUG_CLIENTS { gwlog.Debugf("%s.handleNotifyClientDisconnected: %s", gs, clientid) } @@ -381,7 +383,14 @@ func (gs *_GameService) HandleNotifyClientDisconnected(clientid common.ClientID) entity.OnClientDisconnected(clientid) } -func (gs *_GameService) HandleMigrateRequestAck(pkt *netutil.Packet) { +func (gs *GameService) HandleQuerySpaceGameIDForMigrateAck(pkt *netutil.Packet) { + spaceid := pkt.ReadEntityID() + entityid := pkt.ReadEntityID() + gameid := pkt.ReadUint16() + entity.OnQuerySpaceGameIDForMigrateAck(entityid, spaceid, gameid) +} + +func (gs *GameService) HandleMigrateRequestAck(pkt *netutil.Packet) { eid := pkt.ReadEntityID() spaceid := pkt.ReadEntityID() spaceLoc := pkt.ReadUint16() @@ -393,7 +402,7 @@ func (gs *_GameService) HandleMigrateRequestAck(pkt *netutil.Packet) { entity.OnMigrateRequestAck(eid, spaceid, spaceLoc) } -func (gs *_GameService) HandleRealMigrate(pkt *netutil.Packet) { +func (gs *GameService) HandleRealMigrate(pkt *netutil.Packet) { eid := pkt.ReadEntityID() _ = pkt.ReadUint16() // targetGame is not userful @@ -420,11 +429,11 @@ func (gs *_GameService) HandleRealMigrate(pkt *netutil.Packet) { entity.OnRealMigrate(eid, spaceID, x, y, z, typeName, migrateData, timerData, clientid, clientsrv) } -func (gs *_GameService) terminate() { +func (gs *GameService) terminate() { gs.runState.Store(rsTerminating) } -func (gs *_GameService) startFreeze() { +func (gs *GameService) startFreeze() { dispatcherNum := len(config.GetDispatcherIDs()) gs.dispatcherStartFreezeAcks = make([]bool, dispatcherNum) dispatchercluster.SendStartFreezeGame(gameid) diff --git a/components/game/game.go b/components/game/game.go index 6c5ccfdf..910522e6 100644 --- a/components/game/game.go +++ b/components/game/game.go @@ -39,7 +39,7 @@ var ( logLevel string restore bool runInDaemonMode bool - gameService *_GameService + gameService *GameService signalChan = make(chan os.Signal, 1) gameDispatcherClientDelegate = &dispatcherClientDelegate{} ) diff --git a/engine/consts/consts.go b/engine/consts/consts.go index 7ed4829a..19367c91 100644 --- a/engine/consts/consts.go +++ b/engine/consts/consts.go @@ -4,7 +4,7 @@ import "time" // Optimizations const ( - OPTIMIZE_LOCAL_ENTITIES = true // should be true for performance, set to false for testing + OPTIMIZE_LOCAL_SPACE_ENTERING = false // should be true for performance, set to false for testing only ) // Tunable Options diff --git a/engine/dispatchercluster/dispatchercluster.go b/engine/dispatchercluster/dispatchercluster.go index ffab56b7..11ed0073 100644 --- a/engine/dispatchercluster/dispatchercluster.go +++ b/engine/dispatchercluster/dispatchercluster.go @@ -47,8 +47,8 @@ func SendSetClientFilterProp(gateid uint16, clientid common.ClientID, key, val s return SelectByGateID(gateid).SendSetClientFilterProp(gateid, clientid, key, val) } -func SendMigrateRequest(spaceID common.EntityID, entityID common.EntityID) error { - return SelectByEntityID(entityID).SendMigrateRequest(spaceID, entityID) +func SendMigrateRequest(entityID common.EntityID, spaceID common.EntityID, spaceGameID uint16) error { + return SelectByEntityID(entityID).SendMigrateRequest(entityID, spaceID, spaceGameID) } func SendRealMigrate(eid common.EntityID, targetGame uint16, targetSpace common.EntityID, x, y, z float32, diff --git a/engine/entity/Entity.go b/engine/entity/Entity.go index b4aaf6c0..2c376f30 100644 --- a/engine/entity/Entity.go +++ b/engine/entity/Entity.go @@ -181,8 +181,8 @@ func (e *Entity) ToSpace() *Space { return (*Space)(unsafe.Pointer(e)) } -func (e *Entity) init(typeName string, entityID common.EntityID, entityInstance reflect.Value) { - e.ID = entityID +func (e *Entity) init(typeName string, entityid common.EntityID, entityInstance reflect.Value) { + e.ID = entityid e.V = entityInstance e.I = entityInstance.Interface().(IEntity) e.TypeName = typeName @@ -1003,22 +1003,22 @@ func (e *Entity) GetListAttr(key string) *ListAttr { // Enter Space // EnterSpace let the entity enters space -func (e *Entity) EnterSpace(spaceID common.EntityID, pos Vector3) { +func (e *Entity) EnterSpace(spaceid common.EntityID, pos Vector3) { if e.isEnteringSpace() { - gwlog.Errorf("%s is entering space %s, can not enter space %s", e, e.enteringSpaceRequest.SpaceID, spaceID) + gwlog.Errorf("%s is entering space %s, can not enter space %s", e, e.enteringSpaceRequest.SpaceID, spaceid) e.callCompositiveMethod("OnEnterSpace") return } - if consts.OPTIMIZE_LOCAL_ENTITIES { - localSpace := spaceManager.getSpace(spaceID) + if consts.OPTIMIZE_LOCAL_SPACE_ENTERING { + localSpace := spaceManager.getSpace(spaceid) if localSpace != nil { // target space is local, just enter e.enterLocalSpace(localSpace, pos) } else { // else request migrating to other space - e.requestMigrateTo(spaceID, pos) + e.requestMigrateTo(spaceid, pos) } } else { - e.requestMigrateTo(spaceID, pos) + e.requestMigrateTo(spaceid, pos) } } @@ -1034,7 +1034,7 @@ func (e *Entity) enterLocalSpace(space *Space, pos Vector3) { e.enteringSpaceRequest.RequestTime = time.Now().UnixNano() e.Post(func() { - e.clearEnteringSpaceRequest() + e.cancelEnterSpace() if space.IsDestroyed() { gwlog.Warnf("%s: space %s is destroyed, enter space cancelled", e, space.ID) @@ -1053,50 +1053,88 @@ func (e *Entity) isEnteringSpace() bool { } // Migrate to the server of space -func (e *Entity) requestMigrateTo(spaceID common.EntityID, pos Vector3) { - e.enteringSpaceRequest.SpaceID = spaceID +func (e *Entity) requestMigrateTo(spaceid common.EntityID, pos Vector3) { + e.enteringSpaceRequest.SpaceID = spaceid e.enteringSpaceRequest.EnterPos = pos e.enteringSpaceRequest.RequestTime = time.Now().UnixNano() - dispatchercluster.SendMigrateRequest(spaceID, e.ID) + dispatchercluster.SelectByEntityID(spaceid).SendQuerySpaceGameIDForMigrate(spaceid, e.ID) } -func (e *Entity) clearEnteringSpaceRequest() { +func (e *Entity) cancelEnterSpace() { + // TODO: cancel migrating block in dispatcher e.enteringSpaceRequest.SpaceID = "" e.enteringSpaceRequest.EnterPos = Vector3{} e.enteringSpaceRequest.RequestTime = 0 } -// OnMigrateRequestAck is called by engine when mgirate request Ack is received -func OnMigrateRequestAck(entityID common.EntityID, spaceID common.EntityID, spaceLoc uint16) { - entity := entityManager.get(entityID) +// OnQuerySpaceGameIDForMigrateAck is called by engine when query entity gameid ACK is received +func OnQuerySpaceGameIDForMigrateAck(entityid common.EntityID, spaceid common.EntityID, spaceGameID uint16) { + + //gwlog.Infof("OnQuerySpaceGameIDForMigrateAck: entityid=%s, spaceid=%s, spaceGameID=%v", entityid, spaceid, spaceGameID) + + entity := entityManager.get(entityid) if entity == nil { - //dispatcher_client.GetDispatcherClientForSend().SendCancelMigrateRequest(entityID) - gwlog.Errorf("Migrate failed since entity is destroyed: spaceID=%s, entityID=%s", spaceID, entityID) + //dispatcher_client.GetDispatcherClientForSend().SendCancelMigrateRequest(entityid) + gwlog.Errorf("entity.OnQuerySpaceGameIDForMigrateAck: migrate failed since entity is destroyed: entityid=%s, spaceid=%s", entityid, spaceid) + return + } + + if !entity.isEnteringSpace() { + // replay from dispatcher is too late ? + gwlog.Errorf("entity.OnQuerySpaceGameIDForMigrateAck: migrate failed since entity is not migrating: entity=%s, spaceid=%s", entity, spaceid) + return + } + + if entity.enteringSpaceRequest.SpaceID != spaceid { + // not entering this space ? + gwlog.Errorf("entity.OnQuerySpaceGameIDForMigrateAck: migrate failed since entity is enter other space: entity=%s, spaceid=%s, other space=%s", entity, spaceid, entity.enteringSpaceRequest.SpaceID) return } - if spaceLoc == 0 { + if spaceGameID == 0 { // target space not found, migrate not started - gwlog.Errorf("Migrate failed since target space is not found: spaceID=%s, entity=%s", spaceID, entity) - entity.clearEnteringSpaceRequest() + gwlog.Errorf("entity.OnQuerySpaceGameIDForMigrateAck: migrate failed since target space is not found: entity=%s, spaceid=%s", entity, spaceid) + entity.cancelEnterSpace() + return + } + + dispatchercluster.SendMigrateRequest(entityid, spaceid, spaceGameID) +} + +// OnMigrateRequestAck is called by engine when mgirate request Ack is received +func OnMigrateRequestAck(entityid common.EntityID, spaceid common.EntityID, spaceGameID uint16) { + //gwlog.Infof("OnMigrateRequestAck: entityid=%s, spaceid=%s, spaceGameID=%v", entityid, spaceid, spaceGameID) + entity := entityManager.get(entityid) + if entity == nil { + //dispatcher_client.GetDispatcherClientForSend().SendCancelMigrateRequest(entityid) + gwlog.Errorf("Migrate failed since entity is destroyed: spaceid=%s, entityid=%s", spaceid, entityid) return } if !entity.isEnteringSpace() { // replay from dispatcher is too late ? + gwlog.Errorf("entity.OnQuerySpaceGameIDForMigrateAck: migrate failed since entity is not migrating: entity=%s, spaceid=%s", entity, spaceid) return } - if entity.enteringSpaceRequest.SpaceID != spaceID { + if entity.enteringSpaceRequest.SpaceID != spaceid { // not entering this space ? + gwlog.Errorf("entity.OnQuerySpaceGameIDForMigrateAck: migrate failed since entity is enter other space: entity=%s, spaceid=%s, other space=%s", entity, spaceid, entity.enteringSpaceRequest.SpaceID) + return + } + + if spaceGameID == 0 { + // target space not found, migrate not started + gwlog.Errorf("entity.OnQuerySpaceGameIDForMigrateAck: migrate failed since target space is not found: entity=%s, spaceid=%s", entity, spaceid) + entity.cancelEnterSpace() return } - entity.realMigrateTo(spaceID, entity.enteringSpaceRequest.EnterPos, spaceLoc) + entity.realMigrateTo(spaceid, entity.enteringSpaceRequest.EnterPos, spaceGameID) } -func (e *Entity) realMigrateTo(spaceID common.EntityID, pos Vector3, spaceLoc uint16) { +func (e *Entity) realMigrateTo(spaceid common.EntityID, pos Vector3, spaceGameID uint16) { var clientid common.ClientID var clientsrv uint16 if e.client != nil { @@ -1108,27 +1146,27 @@ func (e *Entity) realMigrateTo(spaceID common.EntityID, pos Vector3, spaceLoc ui timerData := e.dumpTimers() migrateData := e.GetMigrateData() - dispatchercluster.SendRealMigrate(e.ID, spaceLoc, spaceID, + dispatchercluster.SendRealMigrate(e.ID, spaceGameID, spaceid, float32(pos.X), float32(pos.Y), float32(pos.Z), e.TypeName, migrateData, timerData, clientid, clientsrv) } // OnRealMigrate is used by entity migration -func OnRealMigrate(entityID common.EntityID, spaceID common.EntityID, x, y, z float32, typeName string, +func OnRealMigrate(entityid common.EntityID, spaceid common.EntityID, x, y, z float32, typeName string, migrateData map[string]interface{}, timerData []byte, clientid common.ClientID, clientsrv uint16) { - if entityManager.get(entityID) != nil { - gwlog.Panicf("entity %s already exists", entityID) + if entityManager.get(entityid) != nil { + gwlog.Panicf("entity %s already exists", entityid) } // try to find the target space, but might be nil - space := spaceManager.getSpace(spaceID) + space := spaceManager.getSpace(spaceid) var client *GameClient if !clientid.IsNil() { client = MakeGameClient(clientid, clientsrv) } pos := Vector3{Coord(x), Coord(y), Coord(z)} - createEntity(typeName, space, pos, entityID, migrateData, timerData, client, ccMigrate) + createEntity(typeName, space, pos, entityid, migrateData, timerData, client, ccMigrate) } // OnMigrateOut is called when entity is migrating out diff --git a/engine/entity/EntityManager.go b/engine/entity/EntityManager.go index 5b20ebb6..9563620d 100644 --- a/engine/entity/EntityManager.go +++ b/engine/entity/EntityManager.go @@ -399,7 +399,7 @@ func GetServiceProviders(serviceName string) EntityIDSet { } func callEntity(id common.EntityID, method string, args []interface{}) { - if consts.OPTIMIZE_LOCAL_ENTITIES { + if consts.OPTIMIZE_LOCAL_SPACE_ENTERING { e := entityManager.get(id) if e != nil { // this entity is local, just call entity directly e.Post(func() { diff --git a/engine/proto/GoWorldConnection.go b/engine/proto/GoWorldConnection.go index 28271b60..25f2b9c4 100644 --- a/engine/proto/GoWorldConnection.go +++ b/engine/proto/GoWorldConnection.go @@ -289,12 +289,22 @@ func (gwc *GoWorldConnection) SendCallFilterClientProxies(key string, val string return gwc.SendPacketRelease(packet) } +// SendQuerySpaceGameIDForMigrate sends MT_QUERY_SPACE_GAMEID_FOR_MIGRATE message +func (gwc *GoWorldConnection) SendQuerySpaceGameIDForMigrate(spaceid common.EntityID, entityid common.EntityID) error { + packet := gwc.packetConn.NewPacket() + packet.AppendUint16(MT_QUERY_SPACE_GAMEID_FOR_MIGRATE) + packet.AppendEntityID(spaceid) + packet.AppendEntityID(entityid) + return gwc.SendPacketRelease(packet) +} + // SendMigrateRequest sends MT_MIGRATE_REQUEST message -func (gwc *GoWorldConnection) SendMigrateRequest(spaceID common.EntityID, entityID common.EntityID) error { +func (gwc *GoWorldConnection) SendMigrateRequest(entityID common.EntityID, spaceID common.EntityID, spaceGameID uint16) error { packet := gwc.packetConn.NewPacket() packet.AppendUint16(MT_MIGRATE_REQUEST) packet.AppendEntityID(entityID) packet.AppendEntityID(spaceID) + packet.AppendUint16(spaceGameID) return gwc.SendPacketRelease(packet) } diff --git a/engine/proto/proto.go b/engine/proto/proto.go index 9aa32012..5be6e6b1 100644 --- a/engine/proto/proto.go +++ b/engine/proto/proto.go @@ -55,11 +55,19 @@ const ( MT_START_FREEZE_GAME_ACK // Message types for migrating - // MT_MIGRATE_REQUEST is a message type for entity migrations MT_MIGRATE_REQUEST // MT_REAL_MIGRATE is a message type for entity migrations MT_REAL_MIGRATE + // MT_QUERY_SPACE_GAMEID_FOR_MIGRATE is a message type for entity migrations + MT_QUERY_SPACE_GAMEID_FOR_MIGRATE +) + +// Alias message types +const ( + // MT_MIGRATE_REQUEST_ACK is a message type for entity migrations + MT_MIGRATE_REQUEST_ACK = MT_MIGRATE_REQUEST + MT_QUERY_SPACE_GAMEID_FOR_MIGRATE_ACK = MT_QUERY_SPACE_GAMEID_FOR_MIGRATE ) const ( diff --git a/goworld.go b/goworld.go index 0a5a80e5..97189025 100644 --- a/goworld.go +++ b/goworld.go @@ -26,8 +26,8 @@ func RegisterEntity(typeName string, entityPtr entity.IEntity, isPersistent, use } // CreateSpaceAnywhere creates a space with specified kind in any game server -func CreateSpaceAnywhere(kind int) { - entity.CreateSpaceAnywhere(kind) +func CreateSpaceAnywhere(kind int) common.EntityID { + return entity.CreateSpaceAnywhere(kind) } // CreateSpaceLocally creates a space with specified kind in the local game server From b4b00d88ee42755d0011ab00c7ccb43f60fa3e1f Mon Sep 17 00:00:00 2001 From: seis Date: Sun, 11 Feb 2018 10:01:47 +0800 Subject: [PATCH 2/2] test fix --- components/game/game.go | 7 +++++++ engine/consts/consts.go | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/components/game/game.go b/components/game/game.go index 910522e6..f2c22c6f 100644 --- a/components/game/game.go +++ b/components/game/game.go @@ -91,20 +91,27 @@ func Run(delegate IGameDelegate) { } binutil.SetupGWLog(fmt.Sprintf("game%d", gameid), logLevel, gameConfig.LogFile, gameConfig.LogStderr) + gwlog.Infof("Initializing storage ...") storage.Initialize() + gwlog.Infof("Initializing KVDB ...") kvdb.Initialize() + gwlog.Infof("Initializing crontab ...") crontab.Initialize() + gwlog.Infof("Setup http server ...") binutil.SetupHTTPServer(gameConfig.HTTPIp, gameConfig.HTTPPort, nil) entity.SetSaveInterval(gameConfig.SaveInterval) + gwlog.Infof("Start game service ...") gameService = newGameService(gameid, delegate) + gwlog.Infof("Start dispatchercluster ...") dispatchercluster.Initialize(gameid, dispatcherclient.GameDispatcherClientType, restore, &dispatcherClientDelegate{}) setupSignals() + gwlog.Infof("Game service start running ...") gameService.run(restore) } diff --git a/engine/consts/consts.go b/engine/consts/consts.go index 19367c91..8fd59172 100644 --- a/engine/consts/consts.go +++ b/engine/consts/consts.go @@ -4,7 +4,7 @@ import "time" // Optimizations const ( - OPTIMIZE_LOCAL_SPACE_ENTERING = false // should be true for performance, set to false for testing only + OPTIMIZE_LOCAL_SPACE_ENTERING = true // should be true for performance, set to false for testing only ) // Tunable Options