123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- package funmow
-
- import "fmt"
-
- const (
- EventTypeEmit = iota // everyone in the containing object hears it,
- EventTypeOEmit // everyone in the containing object except the player hears it
- EventTypePEmit // only the player hears it
- EventTypeWall // broadcast message
- EventTypePage
- EventTypeSay
- EventTypePose
- EventTypeCommand //7
- EventTypeOutput //8
- EventTypeQuit
- EventTypeTeardown
- EventTypeTeardownComplete
- EventTypeForce
- )
-
- type PlayerEvent struct {
- connectionID int
- src DBRef
- dst DBRef
- messageType int
- message string
- }
-
- type playerRegistration struct {
- execContext *ExecutionContext
- connInbound map[int]chan PlayerEvent
- execInbound chan PlayerEvent
- }
-
- type EventSubscribeRequest struct {
- connectionID int
- playerID DBRef
- inbound chan PlayerEvent
- outbound chan chan PlayerEvent
- }
-
- type EventDistributor struct {
- subscribeChan chan EventSubscribeRequest
- db *DB
- players map[DBRef]*playerRegistration
- }
-
- func NewEventDistributor(db *DB) *EventDistributor {
- e := new(EventDistributor)
- e.db = db
- e.subscribeChan = make(chan EventSubscribeRequest)
- return e
- }
-
- func (e *EventDistributor) Subscribe(req EventSubscribeRequest) chan PlayerEvent {
- e.subscribeChan <- req
- outbound := <-req.outbound
- return outbound
- }
-
- func (e *EventDistributor) OnlinePlayers() DBRefList {
- //replyChan := make(chan DBRefList)
- //e.whoChan <- replyChan
- //onlinePlayers := <-replyChan
- //return onlinePlayers
- return DBRefList{}
- }
-
- //[client runs quit command]
- //connection -> "quit" -> exec
- //exec -> EventTypeQuit -> connection
- //[connection stops doing connectiony stuff]
- //connection -> EventTypeTeardown -> exec
- //[exec stops, kills off goroutines]
- //exec -> EventTypeTeardownComplete -> Event Distributor
- //Event Distributor cleans up
-
- //[client dies]
- //connection -> EventTypeTeardown -> exec
- //[exec stops, kills off goroutines]
- //exec -> EventTypeTeardownComplete -> Event Distributor
- //Event Distributor cleans up
-
- func (e *EventDistributor) Run() {
-
- //ipcChans := make(map[int]playerRegistration)
-
- e.players = make(map[DBRef]*playerRegistration)
-
- outbound := make(chan PlayerEvent)
-
- forceContext := NewForceContext(e, e.db, outbound)
- forceInbound := forceContext.StartInboundChannel()
-
- for {
-
- select {
- case sub := <-e.subscribeChan:
-
- if _, exists := e.players[sub.playerID]; !exists {
- c := NewExecutionContext(sub.playerID, e, e.db, outbound)
- e.players[sub.playerID] = &playerRegistration{
- execInbound: c.StartInboundChannel(),
- execContext: c,
- connInbound: make(map[int]chan PlayerEvent),
- }
- }
- reg := e.players[sub.playerID]
- fmt.Println("connection id", sub.connectionID)
- reg.connInbound[sub.connectionID] = sub.inbound
- sub.outbound <- outbound
- case event := <-outbound: // message
- fmt.Printf("received message src:%d dest:%d type: %d\n", event.src, event.dst, event.messageType)
-
- destPlayer, validDest := e.players[event.dst]
-
- switch event.messageType {
- case EventTypeForce:
- forceInbound <- event
- case EventTypeTeardownComplete:
- if validDest {
- delete(e.players, event.dst)
- fmt.Println("EventTypeTeardownComplete")
- }
- case EventTypeOutput: // from context to connection
- if validDest {
- e.sendToAllConnections(destPlayer.connInbound, event)
- }
- //destPlayer.connInbound <- event
- case EventTypeQuit: // from context to connection
- if validDest {
- e.players[event.dst].connInbound[event.connectionID] <- event
- }
- case EventTypeTeardown: // comes from client when connection is dropped
- fmt.Println("received EventTypeTeardown")
- if validDest {
- close(e.players[event.dst].connInbound[event.connectionID])
- delete(e.players[event.dst].connInbound, event.connectionID)
- fmt.Println("EventTypeTeardown delete", event.connectionID, "len: ", len(e.players[event.dst].connInbound))
- if len(e.players[event.dst].connInbound) == 0 {
- fmt.Println("EventTypeTeardown killing exe")
- close(e.players[event.dst].execInbound) // closing the inbound channel signals the exec to stop
- }
- }
- case EventTypeCommand: // from connection to context
- if validDest {
- destPlayer.execInbound <- event
- }
- case EventTypePEmit:
- if validDest {
- destPlayer.execInbound <- event
- }
- case EventTypePage:
- if validDest {
- destPlayer.execInbound <- event
- }
- case EventTypeEmit:
- e.broadcastEvent(event, false)
- case EventTypeOEmit:
- e.broadcastEvent(event, true) // fix
- case EventTypeSay:
- e.broadcastEvent(event, true)
- case EventTypePose:
- e.broadcastEvent(event, false)
- case EventTypeWall:
- e.broadcastEvent(event, false)
- }
- }
- }
- }
-
- func (e *EventDistributor) sendToAllConnections(connections map[int]chan PlayerEvent, event PlayerEvent) {
-
- for _, channel := range connections {
- channel <- event
- }
-
- }
-
- func (e *EventDistributor) broadcastEvent(event PlayerEvent, omitSrc bool) {
- for playerID, player := range e.players {
- if !omitSrc || playerID != event.src {
- player.execInbound <- event
- }
- }
- }
|