Cleanup plugin code
This commit is contained in:
parent
1f12e916c3
commit
336133d875
@ -7,14 +7,21 @@ import (
|
|||||||
"github.com/josephbmanley/family/server/plugin/gamemap"
|
"github.com/josephbmanley/family/server/plugin/gamemap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// OpCode represents a enum for valid OpCodes
|
||||||
|
// used by the match logic
|
||||||
type OpCode int64
|
type OpCode int64
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// OpCodeTileUpdate is used for tile updates
|
||||||
OpCodeTileUpdate = 1
|
OpCodeTileUpdate = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Match is the object registered
|
||||||
|
// as a runtime.Match interface
|
||||||
type Match struct{}
|
type Match struct{}
|
||||||
|
|
||||||
|
// MatchState holds information that is passed between
|
||||||
|
// Nakama match methods
|
||||||
type MatchState struct {
|
type MatchState struct {
|
||||||
presences map[string]runtime.Presence
|
presences map[string]runtime.Presence
|
||||||
inputs map[string]string
|
inputs map[string]string
|
||||||
@ -23,6 +30,7 @@ type MatchState struct {
|
|||||||
worldMap *gamemap.WorldMap
|
worldMap *gamemap.WorldMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchInit is called when a new match is created
|
||||||
func (m *Match) MatchInit(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, params map[string]interface{}) (interface{}, int, string) {
|
func (m *Match) MatchInit(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, params map[string]interface{}) (interface{}, int, string) {
|
||||||
|
|
||||||
state := &MatchState{
|
state := &MatchState{
|
||||||
@ -38,12 +46,16 @@ func (m *Match) MatchInit(ctx context.Context, logger runtime.Logger, db *sql.DB
|
|||||||
return state, tickRate, label
|
return state, tickRate, label
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchJoinAttempt is called when a player tried to join a match
|
||||||
|
// and validates their attempt
|
||||||
func (m *Match) MatchJoinAttempt(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presence runtime.Presence, metadata map[string]string) (interface{}, bool, string) {
|
func (m *Match) MatchJoinAttempt(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presence runtime.Presence, metadata map[string]string) (interface{}, bool, string) {
|
||||||
mState, ok := state.(*MatchState)
|
mState, ok := state.(*MatchState)
|
||||||
if !ok {
|
if !ok {
|
||||||
logger.Error("Invalid match state on join attempt!")
|
logger.Error("Invalid match state on join attempt!")
|
||||||
return state, false, "Invalid match state!"
|
return state, false, "Invalid match state!"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate user is not already connected
|
||||||
if _, ok := mState.presences[presence.GetUserId()]; ok {
|
if _, ok := mState.presences[presence.GetUserId()]; ok {
|
||||||
return mState, false, "User already logged in."
|
return mState, false, "User already logged in."
|
||||||
} else {
|
} else {
|
||||||
@ -52,32 +64,39 @@ func (m *Match) MatchJoinAttempt(ctx context.Context, logger runtime.Logger, db
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchJoin is called when a player successfully joins the match
|
||||||
func (m *Match) MatchJoin(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presences []runtime.Presence) interface{} {
|
func (m *Match) MatchJoin(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presences []runtime.Presence) interface{} {
|
||||||
mState, ok := state.(*MatchState)
|
mState, ok := state.(*MatchState)
|
||||||
if !ok {
|
if !ok {
|
||||||
logger.Error("Invalid match state on join!")
|
logger.Error("Invalid match state on join!")
|
||||||
return state, false, "Invalid match state!"
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, precense := range presences {
|
for _, precense := range presences {
|
||||||
|
|
||||||
|
// Add presence to map
|
||||||
mState.presences[precense.GetUserId()] = precense
|
mState.presences[precense.GetUserId()] = precense
|
||||||
|
|
||||||
|
// Set player spawn pos
|
||||||
mState.positions[precense.GetUserId()] = map[string]int{"x": 16, "y": 16}
|
mState.positions[precense.GetUserId()] = map[string]int{"x": 16, "y": 16}
|
||||||
|
|
||||||
mState.names[precense.GetUserId()] = "User"
|
mState.names[precense.GetUserId()] = "User"
|
||||||
|
|
||||||
if regionData, err := mState.worldMap.GetJsonRegion(16-8, 16+8, 16-8, 16+8); err != nil {
|
// Get intial tile data around player
|
||||||
|
if regionData, err := mState.worldMap.GetJSONRegionAround(16, 16, 8); err != nil {
|
||||||
logger.Error(err.Error())
|
logger.Error(err.Error())
|
||||||
return mState
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
// Broadcast tile data to client
|
||||||
if sendErr := dispatcher.BroadcastMessage(OpCodeTileUpdate, regionData, []runtime.Presence{precense}, precense, true); sendErr != nil {
|
if sendErr := dispatcher.BroadcastMessage(OpCodeTileUpdate, regionData, []runtime.Presence{precense}, precense, true); sendErr != nil {
|
||||||
logger.Error(sendErr.Error())
|
logger.Error(sendErr.Error())
|
||||||
return mState
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mState
|
return mState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchLeave is called when a player leaves the match
|
||||||
func (m *Match) MatchLeave(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presences []runtime.Presence) interface{} {
|
func (m *Match) MatchLeave(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presences []runtime.Presence) interface{} {
|
||||||
mState, ok := state.(*MatchState)
|
mState, ok := state.(*MatchState)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -90,6 +109,7 @@ func (m *Match) MatchLeave(ctx context.Context, logger runtime.Logger, db *sql.D
|
|||||||
return mState
|
return mState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchLoop is code that is executed every tick
|
||||||
func (m *Match) MatchLoop(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, messages []runtime.MatchData) interface{} {
|
func (m *Match) MatchLoop(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, messages []runtime.MatchData) interface{} {
|
||||||
// Custom code to:
|
// Custom code to:
|
||||||
// - Process the messages received.
|
// - Process the messages received.
|
||||||
@ -99,6 +119,7 @@ func (m *Match) MatchLoop(ctx context.Context, logger runtime.Logger, db *sql.DB
|
|||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchTerminate is code that is executed when the match ends
|
||||||
func (m *Match) MatchTerminate(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, graceSeconds int) interface{} {
|
func (m *Match) MatchTerminate(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, graceSeconds int) interface{} {
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// WorldMap is the data structure used game world
|
||||||
type WorldMap struct {
|
type WorldMap struct {
|
||||||
data [64][64]int
|
data [64][64]int
|
||||||
max_x int
|
max_x int
|
||||||
max_y int
|
max_y int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTile method is used to grab a tile value with error checking
|
||||||
func (m WorldMap) GetTile(x int, y int) (int, error) {
|
func (m WorldMap) GetTile(x int, y int) (int, error) {
|
||||||
if x > m.max_x || y > m.max_y {
|
if x > m.max_x || y > m.max_y {
|
||||||
return -1, fmt.Errorf("Map out of bounds error: %d, %d", x, y)
|
return -1, fmt.Errorf("Map out of bounds error: %d, %d", x, y)
|
||||||
@ -18,11 +20,13 @@ func (m WorldMap) GetTile(x int, y int) (int, error) {
|
|||||||
return m.data[x][y], nil
|
return m.data[x][y], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m WorldMap) GetJsonRegion(start_x, end_x, start_y, end_y int) ([]byte, error) {
|
// GetJSONRegion method returns a JSON object containing the tile values of everything
|
||||||
|
// within a given range
|
||||||
|
func (m WorldMap) GetJSONRegion(startX, endX, startY, endY int) ([]byte, error) {
|
||||||
regionMap := map[int]map[int]int{}
|
regionMap := map[int]map[int]int{}
|
||||||
for x := start_x; x < end_x; x++ {
|
for x := startX; x < endX; x++ {
|
||||||
regionMap[x] = map[int]int{}
|
regionMap[x] = map[int]int{}
|
||||||
for y := start_y; y < end_y; y++ {
|
for y := startY; y < endY; y++ {
|
||||||
if result, err := m.GetTile(x, y); err != nil {
|
if result, err := m.GetTile(x, y); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
@ -35,6 +39,14 @@ func (m WorldMap) GetJsonRegion(start_x, end_x, start_y, end_y int) ([]byte, err
|
|||||||
return jsonString, err
|
return jsonString, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetJSONRegionAround returns a JSON object of tile data from a center point
|
||||||
|
func (m WorldMap) GetJSONRegionAround(centerX, centerY, regionRadius int) ([]byte, error) {
|
||||||
|
jsonString, err := m.GetJSONRegion(centerX-regionRadius, centerX+regionRadius, centerY-regionRadius, centerY+regionRadius)
|
||||||
|
return jsonString, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntializeMap is a method that helps easily
|
||||||
|
// generate WorldMap objects
|
||||||
func IntializeMap() *WorldMap {
|
func IntializeMap() *WorldMap {
|
||||||
worldMap := new(WorldMap)
|
worldMap := new(WorldMap)
|
||||||
worldMap.max_x = 64
|
worldMap.max_x = 64
|
||||||
|
@ -9,27 +9,20 @@ import (
|
|||||||
func getFirstWorld(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule) (string, error) {
|
func getFirstWorld(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule) (string, error) {
|
||||||
|
|
||||||
// List existing matches
|
// List existing matches
|
||||||
// that have been 1 & 4 players
|
// that have been 1 & 32 players
|
||||||
minSize := 1
|
minSize := 1
|
||||||
maxSize := 31
|
maxSize := 32
|
||||||
//5, false, "", &minSize, &maxSize, ""
|
|
||||||
|
// Lists server authorative servers
|
||||||
if matches, err := nk.MatchList(ctx, 1, true, "", &minSize, &maxSize, ""); err != nil {
|
if matches, err := nk.MatchList(ctx, 1, true, "", &minSize, &maxSize, ""); err != nil {
|
||||||
logger.Printf("Failed to list matches when grabing first world! Error: %v\n", err)
|
logger.Printf("Failed to list matches when grabing first world! Error: %v\n", err)
|
||||||
return "", err
|
return "", err
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//For debug purposes
|
|
||||||
for _, match := range matches {
|
|
||||||
logger.Info("Found match with id: %s", match.GetMatchId())
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no matches exist, create one
|
// If no matches exist, create one
|
||||||
if len(matches) <= 0 {
|
if len(matches) <= 0 {
|
||||||
|
|
||||||
// Create match
|
// Create match
|
||||||
//params := map[string]interface{}{}
|
|
||||||
matchID, createErr := nk.MatchCreate(ctx, "control", map[string]interface{}{})
|
matchID, createErr := nk.MatchCreate(ctx, "control", map[string]interface{}{})
|
||||||
//return nakama.match_create("world_control", {})
|
|
||||||
|
|
||||||
// Return if creation error
|
// Return if creation error
|
||||||
if createErr != nil {
|
if createErr != nil {
|
||||||
|
Reference in New Issue
Block a user