diff --git a/cmd/game/main.go b/cmd/game/main.go index 7cafeb4..fddb1af 100644 --- a/cmd/game/main.go +++ b/cmd/game/main.go @@ -60,7 +60,8 @@ func main() { var logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}).Level(logLevels[config.Verbosity]) // set up context - mainCtx := appctx.NewClientContext(config, &logger) + appctx.NewClientContext(config, &logger) + mainCtx := appctx.ClientState //set up main window mw := mainwindow.Init(mainCtx) @@ -72,9 +73,9 @@ func main() { go decodeInput(mainCtx, mw.GetLayer("base")) //fixme set up (load / generate) level - move to game / enter or title / exit - //level, rooms := _default.DefaultGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1)) + level, rooms := mapgens.DefaultGen(gamemap.NewLevel("test", 1)) //level, rooms := mapgens.DelaunayMstGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1)) - level, rooms := mapgens.DelaunayMstExtGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1)) + //level, rooms := mapgens.DelaunayMstExtGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1)) //level, rooms := mapgens.DelaunayPureGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1)) State.Level = level @@ -85,7 +86,7 @@ func main() { //set up controller - controller := ecs.NewController(mainCtx) + controller := ecs.NewController() controller.MapComponentClass(ecs.CoordsComponent, types.Coords{}) controller.MapComponentClass(ecs.AppearanceComponent, types.Appearance{}) @@ -105,9 +106,9 @@ func main() { bp := items.Backpack{MaxMass:100, MaxBulk:100} //Set up Screen Manager - screenMgr := types.NewScreenManager(mainCtx) + screenMgr := types.NewScreenManager() screenMgr.AddScreen("title", screens.NewTitleScreen(mw, screenMgr)) - screenMgr.AddScreen("game", screens.NewGameScreen(mainCtx, mw, &State, vp, controller, screenMgr)) + screenMgr.AddScreen("game", screens.NewGameScreen(mw, &State, vp, controller, screenMgr)) screenMgr.AddScreen("help", screens.NewMenuScreen( mw, screenMgr, @@ -126,7 +127,7 @@ func main() { "i - inventory", "? - this screen", "Ctrl+q - exit", - "f or F - fire or throw weapon", + "f or F - fire weapon or throw item", "z or Z - cast a spell", "p - pray", "Ctrl+p - message log", @@ -183,7 +184,7 @@ func main() { }, }) controller.AddComponent(potion, rooms[0].Center) //implicit Coords - controller.AddComponent(potion, items.Carried{Mass:5, Bulk:3}) + controller.AddComponent(potion, items.Carried{Mass:5, Bulk:3}) //fixme generate from blueprint! controller.AddComponent(potion, items.Usable{}) controller.AddComponent(potion, items.Consumable{}) controller.AddComponent(potion, ecs.Named{Name:"first potion"}) @@ -222,7 +223,7 @@ func main() { // f() // break case <-State.Exit: - appctx.Logger(mainCtx).Warn().Msg("quitting NOW") + appctx.Logger().Warn().Msg("quitting NOW") exit = true break // не оставляйте default в бесконечном select {} - сожрет всё CPU @@ -233,7 +234,7 @@ func main() { } } - appctx.Logger(mainCtx).Info().Msg("pre-shutdown sequence") + appctx.Logger().Info().Msg("pre-shutdown sequence") } func setupLayers(mainwindow *mainwindow.MainWindow) { @@ -253,9 +254,9 @@ func decodeInput(ctx context.Context, baseLayer *mainwindow.Layer) { continue } if keycode == blt.TK_CLOSE && !waitForWCspam { - appctx.Logger(ctx).Warn().Msg("exiting on window close...") + appctx.Logger().Warn().Msg("exiting on window close...") State.Exit <- struct{}{} - appctx.Logger(ctx).Warn().Msg("...done") + appctx.Logger().Warn().Msg("...done") return } var pressed = "" @@ -279,9 +280,9 @@ func decodeInput(ctx context.Context, baseLayer *mainwindow.Layer) { case "Ctrl+q": //fallthrough //case "Escape": - appctx.Logger(ctx).Info().Msg("exiting on quit command...") + appctx.Logger().Info().Msg("exiting on quit command...") State.Exit <- struct{}{} - appctx.Logger(ctx).Info().Msg("...done") + appctx.Logger().Info().Msg("...done") exit = true return default: diff --git a/engine/ecs/controller.go b/engine/ecs/controller.go index 68eeb8e..77d3f59 100644 --- a/engine/ecs/controller.go +++ b/engine/ecs/controller.go @@ -3,13 +3,11 @@ package ecs // ECS system by jcerise, github.com/jcerise/gogue import ( - "context" "lab.zaar.be/thefish/alchemyst-go/util/appctx" "sort" ) type Controller struct { - ctx context.Context systems map[string]System sortedSystems map[int][]System priorityKeys []int @@ -23,8 +21,8 @@ type Controller struct { } // NewController is a convenience/constructor method to properly initialize a new processor -func NewController(ctx context.Context) *Controller { - controller := Controller{ctx: ctx} +func NewController() *Controller { + controller := Controller{} controller.systems = make(map[string]System) controller.sortedSystems = make(map[int][]System) controller.priorityKeys = []int{} @@ -80,7 +78,7 @@ func (c *Controller) GetMappedComponentClass(componentName string) Component { return c.componentMap[componentName] } else { // TODO: Add better (read: actual) error handling here - appctx.Logger(c.ctx).Warn().Msgf("Component[%s] not registered on Controller.\n", componentName) + appctx.Logger().Warn().Msgf("Component[%s] not registered on Controller.\n", componentName) return nil } } @@ -208,7 +206,7 @@ func (c *Controller) AddSystem(system System, priority int) { c.sortedSystems[priority] = append(c.sortedSystems[priority], system) sort.Ints(c.priorityKeys) } else { - appctx.Logger(c.ctx).Warn().Msgf("A system of type %v was already added to the controller %v!", systemType, c) + appctx.Logger().Warn().Msgf("A system of type %v was already added to the controller %v!", systemType, c) } } diff --git a/engine/gamemap/level.go b/engine/gamemap/level.go index 472fc67..8c82464 100644 --- a/engine/gamemap/level.go +++ b/engine/gamemap/level.go @@ -1,7 +1,6 @@ package gamemap import ( - "context" "lab.zaar.be/thefish/alchemyst-go/engine/ecs" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/util/appctx" @@ -14,7 +13,6 @@ var mapHeight = 90 type Level struct { types.Rect - ctx context.Context Name string Branch string Depth int @@ -66,23 +64,22 @@ func (l *Level) MakePassByXY (x,y int, tile *Tile) { func (l *Level) Put (x, y int, tileFunc interface{}) { tile := tileFunc.(func() *Tile)() if tile == nil { - appctx.Logger(l.ctx).Fatal().Msgf("Got non-tile type to put into level: %v", tile) + appctx.Logger().Fatal().Msgf("Got non-tile type to put into level: %v", tile) } if l.InBounds(types.Coords{x, y}) { l.Tiles[y*l.W+x] = tile } } -func NewLevel(ctx context.Context, branch string, depth int) *Level { +func NewLevel(branch string, depth int) *Level { l := &Level{ - ctx: ctx, Name: branch + string(depth), Depth: depth, Rect: types.NewRect(0,0, mapWidth, mapHeight), } l.Tiles = make([]*Tile, l.W*l.H) - appctx.Logger(ctx).Debug().Msgf("Generating level of branch %s depth %d", branch, depth) + appctx.Logger().Debug().Msgf("Generating level of branch %s depth %d", branch, depth) return l } diff --git a/engine/gamemap/mapgens/common.go b/engine/gamemap/mapgens/common.go index 6410aca..c32e30d 100644 --- a/engine/gamemap/mapgens/common.go +++ b/engine/gamemap/mapgens/common.go @@ -1,7 +1,6 @@ package mapgens import ( - "context" "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/util" @@ -39,9 +38,9 @@ var fges = map[int]types.RectFill{ }, } -func GetRandomRoomList(ctx context.Context, rng *util.RNG, l *gamemap.Level, maxRooms, minRoomSize, maxRoomSize int, ) []gamemap.Room{ +func GetRandomRoomList(rng *util.RNG, l *gamemap.Level, maxRooms, minRoomSize, maxRoomSize int, ) []gamemap.Room{ rooms := make([]gamemap.Room, 0) - pfLoader := gamemap.NewPrefabLoader(ctx) + pfLoader := gamemap.NewPrefabLoader() pfRooms := pfLoader.PrefabRoomsList() var fillage types.RectFill @@ -102,11 +101,12 @@ func GetRandomRoomList(ctx context.Context, rng *util.RNG, l *gamemap.Level, max return rooms } -func BlitToLevel (ctx context.Context, l *gamemap.Level, rooms[]gamemap.Room) { +//fixme overlapping rooms +func BlitToLevel (l *gamemap.Level, rooms[]gamemap.Room) { for _, room := range rooms { - err := room.BlitToLevel(ctx, l) + err := room.BlitToLevel(l) if err != nil { - appctx.Logger(ctx).Err(err) + appctx.Logger().Err(err) } } } diff --git a/engine/gamemap/mapgens/default.go b/engine/gamemap/mapgens/default.go index 9845486..db6bbb0 100644 --- a/engine/gamemap/mapgens/default.go +++ b/engine/gamemap/mapgens/default.go @@ -3,10 +3,9 @@ package mapgens import ( "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" "lab.zaar.be/thefish/alchemyst-go/util" - "lab.zaar.be/thefish/alchemyst-go/util/appctx" ) -func DefaultGen(ctx appctx.ClientCtx,l *gamemap.Level) (*gamemap.Level, []gamemap.Room) { +func DefaultGen(l *gamemap.Level) (*gamemap.Level, []gamemap.Room) { rng := util.NewRNG() @@ -17,9 +16,9 @@ func DefaultGen(ctx appctx.ClientCtx,l *gamemap.Level) (*gamemap.Level, []gamema } } - rooms := GetRandomRoomList(ctx, rng, l, maxrooms, minRoomSize, maxRoomSize) + rooms := GetRandomRoomList(rng, l, maxrooms, minRoomSize, maxRoomSize) - BlitToLevel(ctx, l, rooms) + BlitToLevel(l, rooms) for idx, room := range rooms { if idx > 0 { diff --git a/engine/gamemap/mapgens/delaunay_mst.go b/engine/gamemap/mapgens/delaunay_mst.go index 624687c..c6cceb8 100644 --- a/engine/gamemap/mapgens/delaunay_mst.go +++ b/engine/gamemap/mapgens/delaunay_mst.go @@ -18,10 +18,10 @@ func DelaunayMstGen(ctx context.Context, l *gamemap.Level) (*gamemap.Level, []ga l.SetTileByXY(i, j, gamemap.NewWall()) } } - rooms := GetRandomRoomList(ctx, rng, l, maxrooms, minRoomSize, maxRoomSize) + rooms := GetRandomRoomList(rng, l, maxrooms, minRoomSize, maxRoomSize) - BlitToLevel(ctx, l, rooms) + BlitToLevel(l, rooms) centers := make([]types.Coords, 0) for _, room := range rooms { diff --git a/engine/gamemap/mapgens/delaunay_mst_ext.go b/engine/gamemap/mapgens/delaunay_mst_ext.go index fd7fe0c..255d7eb 100644 --- a/engine/gamemap/mapgens/delaunay_mst_ext.go +++ b/engine/gamemap/mapgens/delaunay_mst_ext.go @@ -4,11 +4,10 @@ import ( "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/util" - "lab.zaar.be/thefish/alchemyst-go/util/appctx" "lab.zaar.be/thefish/alchemyst-go/util/delaunay" ) -func DelaunayMstExtGen(ctx appctx.ClientCtx, l *gamemap.Level) (*gamemap.Level, []gamemap.Room) { +func DelaunayMstExtGen(l *gamemap.Level) (*gamemap.Level, []gamemap.Room) { rng := util.NewRNG() @@ -18,9 +17,9 @@ func DelaunayMstExtGen(ctx appctx.ClientCtx, l *gamemap.Level) (*gamemap.Level, l.SetTileByXY(i, j, gamemap.NewWall()) } } - rooms := GetRandomRoomList(ctx, rng, l, maxrooms, minRoomSize, maxRoomSize) + rooms := GetRandomRoomList(rng, l, maxrooms, minRoomSize, maxRoomSize) - BlitToLevel(ctx, l, rooms) + BlitToLevel(l, rooms) centers := make([]types.Coords, 0) for _, room := range rooms { diff --git a/engine/gamemap/mapgens/delaunay_pure.go b/engine/gamemap/mapgens/delaunay_pure.go index df1ee84..af5c14c 100644 --- a/engine/gamemap/mapgens/delaunay_pure.go +++ b/engine/gamemap/mapgens/delaunay_pure.go @@ -18,9 +18,9 @@ func DelaunayPureGen(ctx context.Context, l *gamemap.Level) (*gamemap.Level, []g l.SetTileByXY(i, j, gamemap.NewWall()) } } - rooms := GetRandomRoomList(ctx, rng, l, maxrooms, minRoomSize, maxRoomSize) + rooms := GetRandomRoomList(rng, l, maxrooms, minRoomSize, maxRoomSize) - BlitToLevel(ctx, l, rooms) + BlitToLevel(l, rooms) centers := make([]types.Coords, 0) for _, room := range rooms { diff --git a/engine/gamemap/prefab.go b/engine/gamemap/prefab.go index 4bdf750..fcdba80 100644 --- a/engine/gamemap/prefab.go +++ b/engine/gamemap/prefab.go @@ -1,7 +1,6 @@ package gamemap import ( - "context" "encoding/json" "io/ioutil" "lab.zaar.be/thefish/alchemyst-go/engine/items" @@ -42,12 +41,10 @@ func LoadPrefabFile(filename string) (*PrefabFile, error) { return instance, nil } -type PrefabLoader struct { - ctx context.Context -} +type PrefabLoader struct {} -func NewPrefabLoader(ctx context.Context) PrefabLoader { - return PrefabLoader{ctx: ctx} +func NewPrefabLoader() PrefabLoader { + return PrefabLoader{} } func (pfbl PrefabLoader) PrefabRoomsList() []Room { @@ -106,7 +103,7 @@ func (pfbl PrefabLoader) PrefabRoomsList() []Room { } else { f, ok = TileTypeMap[shortName] if (!ok) { - appctx.Logger(pfbl.ctx).Warn().Msgf("Unknown tile: %s", shortName) + appctx.Logger().Warn().Msgf("Unknown tile: %s", shortName) } } room.Geometry[i+ j*room.W] = f diff --git a/engine/gamemap/room.go b/engine/gamemap/room.go index 9111455..4c6edbe 100644 --- a/engine/gamemap/room.go +++ b/engine/gamemap/room.go @@ -1,7 +1,6 @@ package gamemap import ( - "context" "errors" "fmt" "lab.zaar.be/thefish/alchemyst-go/engine/items" @@ -33,7 +32,7 @@ func (r *Room) Put (x, y int, tileFunc interface{}) { } } -func (room *Room) BlitToLevel(ctx context.Context, l *Level) error { +func (room *Room) BlitToLevel(l *Level) error { //copy tiles like this: //https://stackoverflow.com/questions/21011023/copy-pointer-values-a-b-in-golang @@ -51,7 +50,7 @@ func (room *Room) BlitToLevel(ctx context.Context, l *Level) error { //check underlying tile if underlyingTile == nil || underlyingTile.Name != "Wall" { - appctx.Logger(ctx).Warn().Msg("Invalid blit!") + appctx.Logger().Warn().Msg("Invalid blit!") return invalidBlit } l.Put(mapCoords.X, mapCoords.Y, tileFunc) diff --git a/engine/items/carried.go b/engine/items/carried.go index fbed570..41e43be 100644 --- a/engine/items/carried.go +++ b/engine/items/carried.go @@ -4,6 +4,7 @@ import ( "fmt" "lab.zaar.be/thefish/alchemyst-go/engine/ecs" "lab.zaar.be/thefish/alchemyst-go/engine/types" + "lab.zaar.be/thefish/alchemyst-go/util/appctx" ) type CarriedFace interface { @@ -96,8 +97,16 @@ func FindCarriedUnder(who ecs.Entity) []ecs.Entity { pickerCoords := Controller.GetComponent(who, ecs.CoordsComponent).(types.Coords) carrieds := Controller.GetEntitiesWithComponent(ecs.CarriedComponent) result := make([]ecs.Entity, 0) - for _, carried := range carrieds { - carriedCoords := Controller.GetComponent(carried, ecs.CoordsComponent).(types.Coords) + for idx, carried := range carrieds { + + appctx.Logger().Info().Msgf("%d - %s", idx, carried) + + maybeCoords := Controller.GetComponent(carried, ecs.CoordsComponent) + //if maybeCoords == nil { + // continue + //} + // убедились что что-то есть? тогда кастуем в тип + carriedCoords := maybeCoords.(types.Coords) if pickerCoords.IsAdjacentTo(&carriedCoords) { result = append(result, carried) } diff --git a/engine/screens/game.go b/engine/screens/game.go index dfdacf7..a475ad3 100644 --- a/engine/screens/game.go +++ b/engine/screens/game.go @@ -1,7 +1,6 @@ package screens import ( - "context" "lab.zaar.be/thefish/alchemyst-go/engine/ecs" "lab.zaar.be/thefish/alchemyst-go/engine/ecs/systems" "lab.zaar.be/thefish/alchemyst-go/engine/fov" @@ -15,7 +14,6 @@ import ( ) type GameScreen struct { - ctx context.Context mw *mainwindow.MainWindow state *gamestate.GameState vp *mainwindow.ViewPort @@ -24,9 +22,8 @@ type GameScreen struct { fov fov.Fov } -func NewGameScreen(ctx context.Context, mw *mainwindow.MainWindow, state *gamestate.GameState, viewPort *mainwindow.ViewPort, controller *ecs.Controller, scm *types.ScreenManager) *GameScreen { +func NewGameScreen(mw *mainwindow.MainWindow, state *gamestate.GameState, viewPort *mainwindow.ViewPort, controller *ecs.Controller, scm *types.ScreenManager) *GameScreen { ts := &GameScreen{ - ctx: ctx, mw: mw, state: state, vp: viewPort, @@ -101,7 +98,7 @@ func (ts *GameScreen) HandleInput(input string) { } //do nothing //select if there is more than 1 if len(carrieds) > 1 { - appctx.Logger(ts.ctx).Warn().Msg("Passing item list to inventory not implemented yet") + appctx.Logger().Warn().Msg("Passing item list to inventory not implemented yet") } else { //call pickup in selected cc := items.Controller.GetComponent(carrieds[0], ecs.CarriedComponent).(items.Carried) @@ -110,7 +107,7 @@ func (ts *GameScreen) HandleInput(input string) { // Message with error //gameLog.Log.Error(err) //@fixme! - appctx.Logger(ts.ctx).Warn().Err(err) + appctx.Logger().Warn().Err(err) break; } diff --git a/engine/screens/inventory.go b/engine/screens/inventory.go index 18d83ca..e3eece5 100644 --- a/engine/screens/inventory.go +++ b/engine/screens/inventory.go @@ -121,7 +121,8 @@ func (is *InventoryScreen) HandleInput(input string) { } break case "enter": - //select current under cursor + //show actions menu for item under cursor + //fixme implement break; case "Escape": fallthrough diff --git a/engine/types/screen.go b/engine/types/screen.go index 2ea0292..285b2a3 100644 --- a/engine/types/screen.go +++ b/engine/types/screen.go @@ -1,7 +1,6 @@ package types import ( - "context" "lab.zaar.be/thefish/alchemyst-go/util/appctx" ) @@ -14,16 +13,14 @@ type Screen interface { } type ScreenManager struct { - ctx context.Context Screens map[string]Screen CurrentScreen Screen PreviousScreen Screen } // NewScreenManager is a convenience/constructor method to properly initialize a new ScreenManager -func NewScreenManager(ctx context.Context) *ScreenManager { +func NewScreenManager() *ScreenManager { manager := ScreenManager{ - ctx:ctx, Screens: make(map[string]Screen), CurrentScreen: nil, } @@ -36,7 +33,7 @@ func (sm *ScreenManager) AddScreen(screenName string, screen Screen) { // A screen with the given name does not yet exist on the ScreenManager, go ahead and add it sm.Screens[screenName] = screen } else { - appctx.Logger(sm.ctx).Warn().Msgf("A screen with name %v was already added to the ScreenManager %v!", screenName, sm) + appctx.Logger().Warn().Msgf("A screen with name %v was already added to the ScreenManager %v!", screenName, sm) } } @@ -49,7 +46,7 @@ func (sm *ScreenManager) RemoveScreen(screenName string, screen Screen) { delete(sm.Screens, screenName) } else { // A screen with the given name does not exist - appctx.Logger(sm.ctx).Warn().Msgf("A screen with name %v was not found on ScreenManager %v!", screenName, sm) + appctx.Logger().Warn().Msgf("A screen with name %v was not found on ScreenManager %v!", screenName, sm) } } @@ -84,6 +81,6 @@ func (sm *ScreenManager) SetScreenByName(screenName string) { sm.CurrentScreen.Enter() } else { // A screen with the given name does not exist - appctx.Logger(sm.ctx).Warn().Msgf("A screen with name %v was not found on ScreenManager %v!", screenName, sm) + appctx.Logger().Warn().Msgf("A screen with name %v was not found on ScreenManager %v!", screenName, sm) } } \ No newline at end of file diff --git a/story/choose_your_pill.md b/story/choose_your_pill.md index e69de29..ff92a2b 100644 --- a/story/choose_your_pill.md +++ b/story/choose_your_pill.md @@ -0,0 +1,14 @@ +1 Почему Go? +--- + +потому что круто. (тут бла-бла про управление памятью, многопоточность, сборку и либы) + +2 Почему Libbearterminal? +--- + +Дьявол предложил расчесать манту. + +3 Почему нет звука? +--- + +Бля, да лень возиться. И ни к чему это тут. \ No newline at end of file diff --git a/story/go_game_dos_and_donts.md b/story/go_game_dos_and_donts.md index e98a51c..c601f9c 100644 --- a/story/go_game_dos_and_donts.md +++ b/story/go_game_dos_and_donts.md @@ -155,6 +155,9 @@ func (tr *TerrainRender) Render() { ... } ``` +TODO: троттлинг + + #### Каналы состояний и их Listеner-ы @@ -167,7 +170,7 @@ func (tr *TerrainRender) Render() { - reflect в main loop. Лишь **только** выкинув рефлкесию и больше ничего не делая - я снизил потребление CPU приложением **вдвое**. Это удобная штука, не спорю, но пользоваться ей надо при загрузке ресурсов, при сохранении/загрузке состояния -приложения - т.е. при разовых операциях. Как оказалось, она _очень_ дорогая по CPU. Кто пользоуется ей в main loop, ORM +приложения - т.е. при разовых операциях. Как оказалось, она _очень_ дорогая по CPU. Кто пользуется ей в main loop, ORM и прочих нагруженных местах - да будет предан анафеме. diff --git a/story/index.md b/story/index.md index f97494c..2bede94 100644 --- a/story/index.md +++ b/story/index.md @@ -4,6 +4,8 @@ RLG и Golang - некоторые полезные советы 1. [Установка и некоторые особенности работы](linux_go_blt_install_quickstart.md) связки BLT + Go на Linux 2. Что [стоит и НЕ стоит](go_game_dos_and_donts.md) делать с возможностями Go - +chans, +tickers, +throttling, -closures 3. [Система типов](./static_types_vs_ecs.md) - нативная или ECS? На самом деле и то, и то +4. Немножко конкретики: [предметы и обращение с ними](./item_objecttypes_and_blueprints.md). Как правильно готовить +предметы - чтобы потом не было мучительно больно. Дополнения --- diff --git a/story/item_objecttypes_and_blueprints.md b/story/item_objecttypes_and_blueprints.md new file mode 100644 index 0000000..455277a --- /dev/null +++ b/story/item_objecttypes_and_blueprints.md @@ -0,0 +1,16 @@ +Blueprints, паттерн Object Type и сериализация +== + +Посмотрите внимательно вот это видео, [чувак дело говорит](https://www.youtube.com/watch?v=JxI3Eu5DPwE). + + +Итого: + + - Всё что может делать предмет - в типы - или компоненты, если решились на ECS. + - Суперкласс/архетип для предмета + - Всё данные предмета - в человекочитаемый формат, json например + - Код для сериализации данных в экземпляр а памяти и обратно - **тщательно тестируем**! (TODO: примеры смешных багов) + - Названия типов - тоже в json, ни грамма данных врагу (т.е. коду). Позволит быстро менять/модифицировать игру чуть ли + не текстовым редактором. + + И кстати. Чертежи не только на предметы работают, но об этом с следующей главе. \ No newline at end of file diff --git a/story/static_types_vs_ecs.md b/story/static_types_vs_ecs.md index cd94f5a..0420094 100644 --- a/story/static_types_vs_ecs.md +++ b/story/static_types_vs_ecs.md @@ -1,4 +1,5 @@ -Система типов в Go +Система типов и Go +--- Плюсы использования нативной системы типов diff --git a/ui/mainwindow/mainwindow.go b/ui/mainwindow/mainwindow.go index ac0a3f2..8772ebe 100644 --- a/ui/mainwindow/mainwindow.go +++ b/ui/mainwindow/mainwindow.go @@ -15,7 +15,7 @@ type MainWindow struct { } func Init(ctx context.Context) *MainWindow { - appctx.Logger(ctx).Info().Msgf("Opening main window...") + appctx.Logger().Info().Msgf("Opening main window...") mw := MainWindow{ctx: ctx, layers: make(map[string]types.Renderable, 0)} mw.Open() return &mw @@ -33,7 +33,7 @@ func (mw *MainWindow) GetLayer(name string) *Layer { if layer, ok := mw.layers[name]; ok { return layer.(*Layer) } - appctx.Logger(mw.ctx).Fatal().Msgf("No layer with such name %s", name) + appctx.Logger().Fatal().Msgf("No layer with such name %s", name) return nil } @@ -58,7 +58,7 @@ func (mw *MainWindow) Open() { } func (mw *MainWindow) Close() { - appctx.Logger(mw.ctx).Info().Msg("Closing main window...") + appctx.Logger().Info().Msg("Closing main window...") blt.Close() } diff --git a/util/appctx/context.go b/util/appctx/context.go index f51bcda..b3c3c46 100644 --- a/util/appctx/context.go +++ b/util/appctx/context.go @@ -12,15 +12,17 @@ const ( loggerKey = "logger" ) -type ClientCtx struct { +type clientCtx struct { context.Context } -func NewClientContext(config *util.Config, logger *zerolog.Logger) ClientCtx { +var ClientState clientCtx + +func NewClientContext(config *util.Config, logger *zerolog.Logger) { ctx := context.Context(context.TODO()) ctx = context.WithValue(ctx, configKey, config) ctx = context.WithValue(ctx, loggerKey, logger) - return ClientCtx{ ctx} + ClientState = clientCtx{ctx} } func Config(c context.Context) *util.Config { @@ -31,7 +33,11 @@ func Config(c context.Context) *util.Config { return cfg } -func Logger(c context.Context) *zerolog.Logger { +func Logger() *zerolog.Logger { + return getLogger(ClientState.Context) +} + +func getLogger(c context.Context) *zerolog.Logger { logger, ok := c.Value(loggerKey).(*zerolog.Logger) if !ok { panic(fmt.Errorf("no access to logger from context"))