game.go 2.79 KB
package main

import (
	"context"
	"fmt"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"pro2d/common/components"
	"pro2d/conf"
	"pro2d/models"
	//_ "pro2d/cmd/gameserver/plugin"
	"pro2d/utils/db"
	"pro2d/utils/etcd"
	"pro2d/utils/logger"
	"sync"
	"syscall"
)

type GameServer struct {
	components.IServer
	EtcdClient *etcd.EtcdClient

	Agents 		*sync.Map
}

func NewGameServer(sconf *conf.SConf) (*GameServer, error)  {
	s := &GameServer{
		Agents:  new(sync.Map),
	}

	options := []components.Option{
		components.WithPlugin(components.NewPlugin(sconf.PluginPath)),
		components.WithSplitter(components.NewPBSplitter()),
		components.WithConnCbk(s.OnConnection),
		components.WithMsgCbk(s.OnMessage),
		components.WithCloseCbk(s.OnClose),
		components.WithTimerCbk(s.OnTimer),
	}

	iserver := components.NewServer(sconf.Port, options...)
	s.IServer = iserver

	//mongo 初始化
	db.MongoDatabase = db.MongoClient.Database(sconf.DBName)
	models.InitGameServerModels()

	//Etcd 初始化
	var err error
	s.EtcdClient, err = etcd.NewEtcdClient(conf.GlobalConf.Etcd)
	if err != nil {
		return nil, err
	}
	s.EtcdClient.PutWithLeasePrefix(conf.GlobalConf.GameConf.Name, conf.GlobalConf.GameConf.ID, fmt.Sprintf("%s:%d", conf.GlobalConf.GameConf.IP, conf.GlobalConf.GameConf.Port), 5)

	return s, nil
}

func (s *GameServer) OnConnection(conn components.IConnection)  {
	agent := NewAgent(s)
	agent.OnConnection(conn)
	s.Agents.Store(conn.GetID(),agent)
}

func (s *GameServer) OnMessage(msg components.IMessage)  {
	agent, ok := s.Agents.Load(msg.GetSessId())
	if !ok {
		return
	}
	agent.(*Agent).OnMessage(msg)
}

func (s *GameServer) OnTimer(conn components.IConnection)  {
	agent, ok := s.Agents.Load(conn.GetID())
	if !ok {
		return
	}
	agent.(*Agent).OnTimer()
}

func (s *GameServer) OnClose(conn components.IConnection)  {
	agent, ok := s.Agents.Load(conn.GetID())
	if !ok {
		return
	}
	agent.(*Agent).OnClose()
	s.Agents.Delete(conn.GetID())
}

func (s *GameServer) Stop() {
	s.IServer.Stop()

	db.MongoClient.Disconnect(context.TODO())
}


func main()  {
	err := make(chan error)
	stopChan := make(chan os.Signal)
	signal.Notify(stopChan, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)

	userChan := make(chan os.Signal)
	signal.Notify(userChan, syscall.SIGUSR1, syscall.SIGUSR2)

	s,err1 := NewGameServer(conf.GlobalConf.GameConf)
	if err1 != nil {
		fmt.Errorf(err1.Error())
		return
	}
	go func() {
		err <- http.ListenAndServe("localhost:6061", nil)
	}()

	go func() {
		err <- s.Start()
	}()

	for {
		select {
		case e := <- err:
			logger.Error("game server error: %v", e)
			return
		case <-stopChan:
			s.Stop()
			logger.Debug("game stop...")
			return
		case u := <-userChan:
			logger.Debug("userChan .. %v",u.String())
			e := s.IServer.GetPlugin().LoadPlugin()
			if e != nil {
				logger.Error("err: ", e.Error())
			}
		}
	}
}