From e738568c148fd86d3e2bd8049fb5ff269b2e2e85 Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Tue, 28 Jan 2020 15:25:32 +0300 Subject: [PATCH 1/5] test fixes --- TODO | 6 +++--- cmd/game/main.go | 1 + config.json | 2 +- delaunay_test.go | 12 ++++++------ engine/screens/devmenu.go | 10 ++++++++-- engine/screens/title.go | 2 +- 6 files changed, 20 insertions(+), 13 deletions(-) diff --git a/TODO b/TODO index 6d046bf..6f28312 100644 --- a/TODO +++ b/TODO @@ -27,7 +27,7 @@ Assets and i18n: ECS & engine: - implement time queue (how to deal with closures?) (?) github.com/thefish/scheduleq - get rid od time.Now inside - move all rendering to systems - - try to move input handling to systems + + try to move input handling to systems Dungeon and branches: General: @@ -53,7 +53,7 @@ Combat: - mass - damage calculated from: kinetic energy is calculated by mass / speed / material density (p = mv) масса на скорость = кинетическая энергия - next you determine target and its subpart (accuracy appied) + next you determine target and its subpart (accuracy applied) next we calculate the area, on which kinetic energy is applied (determined by piercing, hacking, crushing damage profile) находим площадь next we calculate @@ -81,5 +81,5 @@ Combat: Quest engine: - look at parsers like URQL etc - - distorted Aschenputtel story / partisans / rapist prince / Grey Mountains + - distorted Aschenputtel story / partisans / rapist prince / Grey Mountains / No gold diff --git a/cmd/game/main.go b/cmd/game/main.go index d01e179..4a2d66a 100644 --- a/cmd/game/main.go +++ b/cmd/game/main.go @@ -148,6 +148,7 @@ func main() { } screenMgr.AddScreen("devmenu", screens.NewDevmenuScreen( + mainCtx, mw, controller, screenMgr, diff --git a/config.json b/config.json index 8be09b4..1b77443 100644 --- a/config.json +++ b/config.json @@ -1,5 +1,5 @@ { - "version": "v0.0.1.7", + "version": "v0.0.1.7-16-gbf13c9c", "title": "Alchemyst", "sizeX": 100, "sizeY": 47, diff --git a/delaunay_test.go b/delaunay_test.go index 42864bb..541d1d1 100644 --- a/delaunay_test.go +++ b/delaunay_test.go @@ -18,14 +18,14 @@ func TestDelaunay(t *testing.T) { } expected := []types.Edge{ - {types.Coords{10, 60}, types.Coords{10, 10}}, - {types.Coords{30, 10}, types.Coords{40, 20}}, - {types.Coords{60, 10}, types.Coords{40, 60}}, - {types.Coords{40, 20}, types.Coords{40, 60}}, - {types.Coords{10, 10,}, types.Coords{30, 10}}, + {types.Coords{ 60, 10}, types.Coords{40, 20}}, + {types.Coords{40, 20}, types.Coords{10, 10}}, + {types.Coords{30, 10}, types.Coords{60, 10}}, + {types.Coords{40, 60}, types.Coords{10, 60}}, + {types.Coords{40, 20,}, types.Coords{10, 60}}, } - result := delaunay.GetMst(coords, 100, 100) + result := delaunay.GetMst(coords, 100, 100, 100 ) for idx, _ := range result { if result[idx] != expected[idx] { diff --git a/engine/screens/devmenu.go b/engine/screens/devmenu.go index edbcca8..4849d29 100644 --- a/engine/screens/devmenu.go +++ b/engine/screens/devmenu.go @@ -7,10 +7,12 @@ import ( "lab.zaar.be/thefish/alchemyst-go/engine/gamestate" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" + "lab.zaar.be/thefish/alchemyst-go/util/appctx" "strings" ) type DevmenuScreen struct { + ctx appctx.ClientCtx mw *mainwindow.MainWindow controller *ecs.Controller scm *types.ScreenManager @@ -23,8 +25,9 @@ type DevmenuScreen struct { fgColor string } -func NewDevmenuScreen(mw *mainwindow.MainWindow, controller *ecs.Controller, scm *types.ScreenManager, state *gamestate.GameState, rect types.Rect, renderParent bool) *DevmenuScreen { +func NewDevmenuScreen(ctx appctx.ClientCtx, mw *mainwindow.MainWindow, controller *ecs.Controller, scm *types.ScreenManager, state *gamestate.GameState, rect types.Rect, renderParent bool) *DevmenuScreen { return &DevmenuScreen{ + ctx: ctx, mw: mw, controller: controller, scm: scm, @@ -58,6 +61,7 @@ func (devm *DevmenuScreen) HandleInput(input string) { level.Tiles[idx].Explored = false } devm.scm.SetScreen(devm.scm.PreviousScreen) + appctx.Logger(devm.ctx).Info().Msg("resetting to normal visibility") break case "v": level := devm.state.Level @@ -65,13 +69,15 @@ func (devm *DevmenuScreen) HandleInput(input string) { level.Tiles[idx].Visible = true level.Tiles[idx].Explored = true } - fmt.Printf("making everything visible!") + appctx.Logger(devm.ctx).Info().Msg("making everything visible") devm.scm.SetScreen(devm.scm.PreviousScreen) break case "p": if devm.controller.HasComponent(devm.state.Player, effects.BuffPassWall) { + appctx.Logger(devm.ctx).Info().Msg("disabling passwall") devm.controller.RemoveComponent(devm.state.Player, effects.BuffPassWall) } else { + appctx.Logger(devm.ctx).Info().Msg("enabling passwall") devm.controller.AddComponent(devm.state.Player, effects.PassWall{}) } case "Escape": diff --git a/engine/screens/title.go b/engine/screens/title.go index 693c2cc..5dbbeb4 100644 --- a/engine/screens/title.go +++ b/engine/screens/title.go @@ -55,5 +55,5 @@ Roguebasin Libtcod Tutorial (c) 2010-2011, Jotaf Henriques Brogue 1.3 (c) 2010 Brian Walker Madness (c) 2010 hmp BearLibTerminal (c) Cfyz 2009-2019 -Gogue (c) jcerise +Gogue (c) 2019 jcerise ` From 2352ec4f0a9c4f85e48c14b685fe5207664e8dc5 Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Thu, 27 Feb 2020 17:40:49 +0300 Subject: [PATCH 2/5] wu algo --- TODO | 12 +++++++ engine/screens/game.go | 2 +- util/wu/line.go | 78 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 util/wu/line.go diff --git a/TODO b/TODO index 6f28312..e23ff37 100644 --- a/TODO +++ b/TODO @@ -83,3 +83,15 @@ Quest engine: - look at parsers like URQL etc - distorted Aschenputtel story / partisans / rapist prince / Grey Mountains / No gold + +No Gold in Gery Mountains / Kim Newman + +- Drakenfells castle //location +- Greteschele // char / rogue / charred zombie +- Yom Lamprecht // char / rogue / +- Tiley manor(?) // location / княжество +- Melissa d'Acu // char / small girl + + + + diff --git a/engine/screens/game.go b/engine/screens/game.go index d46393e..801ea26 100644 --- a/engine/screens/game.go +++ b/engine/screens/game.go @@ -49,7 +49,7 @@ func (ts *GameScreen) UseEcs() bool { return true } func (ts *GameScreen) Enter() { ts.mw.GetLayer("overlay").ClearArea(0, ts.mw.H-3, 30, 3) ts.mw.GetLayer("overlay").WithColor("#77777777"). - Print(1, ts.mw.H-2, "Press [color=white]?[/color] for help") + Print(ts.mw.W - 17 , 1, "Press [color=white]?[/color] for help") } func (ts *GameScreen) Exit() { //trs := ts.controller.GetSystem(ecs.LevelRenderSystem) diff --git a/util/wu/line.go b/util/wu/line.go new file mode 100644 index 0000000..47926ef --- /dev/null +++ b/util/wu/line.go @@ -0,0 +1,78 @@ +package wu + +import ( + "lab.zaar.be/thefish/alchemyst-go/engine/types" + "math" +) + +func ipart(x float64) float64 { + return math.Floor(x) +} + +func round(x float64) float64 { + return ipart(x + .5) +} + +func fpart(x float64) float64 { + return x - ipart(x) +} + +func rfpart(x float64) float64 { + return 1 - fpart(x) +} + +func (Layer types.Putable) WuLine(x1, y1, x2, y2 float64, w int) { + dx := x2 - x1 + dy := y2 - y1 + ax := dx + if ax < 0 { + ax = -ax + } + ay := dy + if ay < 0 { + ay = -ay + } + + var plot func(int, int, float64) + + if ax < ay { + x1, y1 = y1, x1 + x2, y2 = y2, x2 + dx, dy = dy, dx + plot = func(x, y int, c float64) { + Layer.Put(y, x, uint8(255 * c)) + } + } else { + plot = func(x, y int, c float64) { + Layer.Put(x, y, uint8(255 * c)) + } + } + if x2 < x1 { + x1, x2 = x2, x1 + y1, y2 = y2, y1 + } + gradient := dy / dx + + xend := round(x1) + yend := y1 + gradient*(xend-x1) + xgap := rfpart(x1 + .5) + xpxl1 := int(xend) + ypxl1 := int(ipart(yend)) + plot(xpxl1, ypxl1, rfpart(yend)*xgap) + plot(xpxl1, ypxl1+1, fpart(yend)*xgap) + intery := yend + gradient + + xend = round(x2) + yend = y2 + gradient*(xend-x2) + xgap = fpart(x2 + 0.5) + xpxl2 := int(xend) + ypxl2 := int(ipart(yend)) + plot(xpxl2, ypxl2, rfpart(yend)*xgap) + plot(xpxl2, ypxl2+1, fpart(yend)*xgap) + + for x := xpxl1 + 1; x <= xpxl2-1; x++ { + plot(x, int(ipart(intery)), rfpart(intery)) + plot(x, int(ipart(intery))+1, fpart(intery)) + intery = intery + gradient + } +} From d2b22f47604ce68d0e509dc0c91c77f3d5c4c96d Mon Sep 17 00:00:00 2001 From: thefish Date: Thu, 24 Sep 2020 23:47:36 +0300 Subject: [PATCH 3/5] pick up in adjacent tiles, fix bulk check --- cmd/game/main.go | 2 +- delaunay_test.go | 2 +- .../precomputed_shade/precomputed_shade.go | 2 +- engine/items/backpack.go | 22 +++++++------ engine/items/carried.go | 31 ++++++++++--------- engine/screens/game.go | 14 +++++++-- engine/screens/inventory.go | 6 ++-- engine/screens/title.go | 2 ++ go.mod | 1 + story/makefile_and_crosscompiling.md | 2 +- 10 files changed, 53 insertions(+), 31 deletions(-) diff --git a/cmd/game/main.go b/cmd/game/main.go index d01e179..7cafeb4 100644 --- a/cmd/game/main.go +++ b/cmd/game/main.go @@ -33,7 +33,7 @@ func init() { //we can run logic in separate goroutines // -// go doSometing(State,...) +// go doSomething(State,...) // //and there we go like this: // func doSomething(State main.GameState, args...) { diff --git a/delaunay_test.go b/delaunay_test.go index 42864bb..b5a471a 100644 --- a/delaunay_test.go +++ b/delaunay_test.go @@ -25,7 +25,7 @@ func TestDelaunay(t *testing.T) { {types.Coords{10, 10,}, types.Coords{30, 10}}, } - result := delaunay.GetMst(coords, 100, 100) + result := delaunay.GetMst(coords, 100, 100, -1) for idx, _ := range result { if result[idx] != expected[idx] { diff --git a/engine/fov/precomputed_shade/precomputed_shade.go b/engine/fov/precomputed_shade/precomputed_shade.go index 4123033..1bf15fe 100644 --- a/engine/fov/precomputed_shade/precomputed_shade.go +++ b/engine/fov/precomputed_shade/precomputed_shade.go @@ -124,7 +124,7 @@ func (ps *precomputedShade) FindByCoords(c types.Coords) (int, *Cell, error) { func (ps *precomputedShade) IsInFov(coords types.Coords) bool { rc := ps.fromLevelCoords(coords) - if rc.X == 0 && rc.Y ==0 {return true} + if rc.X == 0 && rc.Y ==0 {return true} _, cell, err := ps.FindByCoords(rc) if err != nil { return false diff --git a/engine/items/backpack.go b/engine/items/backpack.go index c3e2a0f..bacc0f7 100644 --- a/engine/items/backpack.go +++ b/engine/items/backpack.go @@ -1,7 +1,13 @@ package items -import "lab.zaar.be/thefish/alchemyst-go/engine/ecs" - +import ( + "fmt" + "lab.zaar.be/thefish/alchemyst-go/engine/ecs" +) +var ( + ErrorInvTooHeavy = fmt.Errorf("too heavy") + ErrorInvTooBulky = fmt.Errorf("too bulky") +) type Backpack struct { MaxNumber int MaxBulk int @@ -13,7 +19,7 @@ func (b Backpack) Type() string { return ecs.BackpackComponent } -func (b *Backpack) HasFreeSpace(Bulk, Mass int) bool { +func (b *Backpack) HasFreeSpace(Bulk, Mass int) error { totalBulk, totalMass := 0, 0 for i, _ := range b.items { tmp := Controller.GetComponent(b.items[i], Carried{}.Type()).(Carried) @@ -22,14 +28,12 @@ func (b *Backpack) HasFreeSpace(Bulk, Mass int) bool { totalMass += carried.Mass } if totalMass >= b.MaxMass { - //fixme return message along - 'too heavy' - return false + return ErrorInvTooHeavy } - if totalBulk >= b.MaxMass { - //fixme return message along - 'doesnt fit to your backpack' - return false + if totalBulk >= b.MaxBulk { + return ErrorInvTooBulky } - return true + return nil } func (b *Backpack) GetItems() []ecs.Entity { diff --git a/engine/items/carried.go b/engine/items/carried.go index 9df2123..fbed570 100644 --- a/engine/items/carried.go +++ b/engine/items/carried.go @@ -1,6 +1,7 @@ package items import ( + "fmt" "lab.zaar.be/thefish/alchemyst-go/engine/ecs" "lab.zaar.be/thefish/alchemyst-go/engine/types" ) @@ -19,32 +20,33 @@ func (c Carried) Type() string { return ecs.CarriedComponent } -func (c Carried) Pickup(who, what ecs.Entity) { +func (c Carried) Pickup(who, what ecs.Entity) error { // check if im lying on ground if !Controller.HasComponent(what, ecs.CoordsComponent) { - return + return fmt.Errorf("bug! item with no coords?!") } // something inexistent on map trying to pickup an item?! if !Controller.HasComponent(who, ecs.CoordsComponent) { //todo log error - investigate this situation - return + return fmt.Errorf("bug! actor with no coords?!") } - //check if who and what are on the same tile + //check if who and what are in adjacent tiles whoCoords := Controller.GetComponent(who, ecs.CoordsComponent).(types.Coords) whatCoords := Controller.GetComponent(what, ecs.CoordsComponent).(types.Coords) - if whoCoords != whatCoords { + if !whoCoords.IsAdjacentTo(&whatCoords) { //todo log error - something strange happened - return + return fmt.Errorf("bug! actor and item in inadjacent coords?!") } //does not have inventory? if !Controller.HasComponent(who, ecs.BackpackComponent) { //todo send message - you cant carry items - return + return fmt.Errorf("bug! actor cannot carry items") } bp := Controller.GetComponent(who, Backpack{}.Type()).(Backpack) - if !bp.HasFreeSpace(c.Bulk, c.Mass) { + err := bp.HasFreeSpace(c.Bulk, c.Mass) + if err != nil { //todo send message - does not fit to your inventory - return + return err } //do not remove appearance //remove coords instead (does not exist on map anymore) @@ -52,6 +54,7 @@ func (c Carried) Pickup(who, what ecs.Entity) { bp.items = append(bp.items, what) //fuck that, we need to update constantly Controller.UpdateComponent(who, ecs.BackpackComponent, bp) + return nil } func (c Carried) Drop(who, what ecs.Entity) { @@ -90,13 +93,13 @@ func (c *Carried) GetBulk(what ecs.Entity) int { } func FindCarriedUnder(who ecs.Entity) []ecs.Entity { - coords := Controller.GetComponent(who, ecs.CoordsComponent).(types.Coords) + pickerCoords := Controller.GetComponent(who, ecs.CoordsComponent).(types.Coords) carrieds := Controller.GetEntitiesWithComponent(ecs.CarriedComponent) result := make([]ecs.Entity, 0) - for _, ent := range carrieds { - car := Controller.GetComponent(ent, ecs.CoordsComponent) - if car == coords { - result = append(result, ent) + for _, carried := range carrieds { + carriedCoords := Controller.GetComponent(carried, ecs.CoordsComponent).(types.Coords) + if pickerCoords.IsAdjacentTo(&carriedCoords) { + result = append(result, carried) } } return result diff --git a/engine/screens/game.go b/engine/screens/game.go index d46393e..dfdacf7 100644 --- a/engine/screens/game.go +++ b/engine/screens/game.go @@ -58,6 +58,7 @@ func (ts *GameScreen) Exit() { //remove what we dont need } +//fixme kry names to action constants! func (ts *GameScreen) HandleInput(input string) { //ts.state.Do(func(){ switch input { @@ -104,9 +105,18 @@ func (ts *GameScreen) HandleInput(input string) { } else { //call pickup in selected cc := items.Controller.GetComponent(carrieds[0], ecs.CarriedComponent).(items.Carried) - items.Carried.Pickup(cc, ts.state.Player, carrieds[0]) - } + err := items.Carried.Pickup(cc, ts.state.Player, carrieds[0]) + if err != nil { + // Message with error + //gameLog.Log.Error(err) + //@fixme! + appctx.Logger(ts.ctx).Warn().Err(err) + break; + } + } + //log picked up + //gameLog.Log.Message(err) break; case "i": diff --git a/engine/screens/inventory.go b/engine/screens/inventory.go index b5e4685..18d83ca 100644 --- a/engine/screens/inventory.go +++ b/engine/screens/inventory.go @@ -63,6 +63,8 @@ func (is *InventoryScreen) Enter() { is.prepared.Prepare(is) } +//fixme key names to action constants! +//fixme unify scrolling controls! func (is *InventoryScreen) HandleInput(input string) { if strings.Contains(string(runeIndex), strings.Replace(input, "Shift+", "", -1)) { if strings.Contains("Shift+", input) { @@ -76,7 +78,7 @@ func (is *InventoryScreen) HandleInput(input string) { return } switch input { - case "Up": + case "Up", "k": is.cursor = is.cursor - 1 if is.cursor < 0 { is.cursor = 0 @@ -88,7 +90,7 @@ func (is *InventoryScreen) HandleInput(input string) { } } break - case "Down": + case "Down", "j": is.cursor = is.cursor + 1 if is.cursor >= len(is.prepared) { is.cursor = len(is.prepared) - 1 diff --git a/engine/screens/title.go b/engine/screens/title.go index 693c2cc..dc00e01 100644 --- a/engine/screens/title.go +++ b/engine/screens/title.go @@ -19,6 +19,8 @@ func (ts *TitleScreen) UseEcs() bool { return false } func (ts *TitleScreen) Enter() { blt.Clear() } + +//fixme key names to action constants! func (ts *TitleScreen) HandleInput(input string) { switch input { case "n": diff --git a/go.mod b/go.mod index bedfbfa..e195fb1 100644 --- a/go.mod +++ b/go.mod @@ -5,5 +5,6 @@ go 1.12 require ( github.com/gammazero/deque v0.0.0-20190521012701-46e4ffb7a622 github.com/rs/zerolog v1.15.0 + golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc lab.zaar.be/thefish/bearlibterminal v0.0.0-20191018101635-dd37bbc90d77 ) diff --git a/story/makefile_and_crosscompiling.md b/story/makefile_and_crosscompiling.md index 72cd100..438ea0c 100644 --- a/story/makefile_and_crosscompiling.md +++ b/story/makefile_and_crosscompiling.md @@ -5,7 +5,7 @@ Почему это важно --- -Про сборку под разные ОС я даже уюеждать не буду - аудитория рогаликов мало того что крохотная, так еще и сильно +Про сборку под разные ОС я даже убеждать не буду - аудитория рогаликов мало того что крохотная, так еще и сильно сегментирована по осям. Go почти бесплатно дает вам возможность сборки под все мажорные оси, пользуйтесь этим - и потенциально в разы больше народа ознакомится с вашим творением. From 9f3eaafa3fefed1761001ab0a342176597ad912f Mon Sep 17 00:00:00 2001 From: thefish Date: Fri, 25 Sep 2020 00:45:45 +0300 Subject: [PATCH 4/5] fix logger --- cmd/game/main.go | 29 +++++++++++----------- engine/ecs/controller.go | 10 +++----- engine/gamemap/level.go | 9 +++---- engine/gamemap/mapgens/common.go | 12 ++++----- engine/gamemap/mapgens/default.go | 7 +++--- engine/gamemap/mapgens/delaunay_mst.go | 4 +-- engine/gamemap/mapgens/delaunay_mst_ext.go | 7 +++--- engine/gamemap/mapgens/delaunay_pure.go | 4 +-- engine/gamemap/prefab.go | 11 +++----- engine/gamemap/room.go | 5 ++-- engine/items/carried.go | 13 ++++++++-- engine/screens/game.go | 9 +++---- engine/screens/inventory.go | 3 ++- engine/types/screen.go | 11 +++----- story/choose_your_pill.md | 14 +++++++++++ story/go_game_dos_and_donts.md | 5 +++- story/index.md | 2 ++ story/item_objecttypes_and_blueprints.md | 16 ++++++++++++ story/static_types_vs_ecs.md | 3 ++- ui/mainwindow/mainwindow.go | 6 ++--- util/appctx/context.go | 14 ++++++++--- 21 files changed, 115 insertions(+), 79 deletions(-) create mode 100644 story/item_objecttypes_and_blueprints.md 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")) From 76780d793672385cce873aecde6e4b5a06b4f0c7 Mon Sep 17 00:00:00 2001 From: thefish Date: Fri, 25 Sep 2020 01:13:26 +0300 Subject: [PATCH 5/5] fix GetEntitiesWuthComponent, pickup logic fixed accordingly --- engine/ecs/controller.go | 13 +++++++++---- engine/items/carried.go | 16 ++++------------ 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/engine/ecs/controller.go b/engine/ecs/controller.go index 77d3f59..8383668 100644 --- a/engine/ecs/controller.go +++ b/engine/ecs/controller.go @@ -138,15 +138,20 @@ func (c *Controller) GetEntities() map[Entity]map[string]Component { } // GetEntitiesWithComponent returns a list of all entities with a given component attached -// TODO: Allow for passing a list of components -func (c *Controller) GetEntitiesWithComponent(componentType string) []Entity { +func (c *Controller) GetEntitiesWithComponent(componentTypes... string) []Entity { entitiesWithComponent := make([]Entity, 0) for entity := range c.entities { - if c.HasComponent(entity, componentType) { + mustAddThis := true + for _, componentType := range componentTypes { + if !c.HasComponent(entity, componentType) { + mustAddThis = false + break + } + } + if mustAddThis { entitiesWithComponent = append(entitiesWithComponent, entity) } } - return entitiesWithComponent } diff --git a/engine/items/carried.go b/engine/items/carried.go index 41e43be..a190823 100644 --- a/engine/items/carried.go +++ b/engine/items/carried.go @@ -4,7 +4,6 @@ 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 { @@ -95,18 +94,11 @@ func (c *Carried) GetBulk(what ecs.Entity) int { func FindCarriedUnder(who ecs.Entity) []ecs.Entity { pickerCoords := Controller.GetComponent(who, ecs.CoordsComponent).(types.Coords) - carrieds := Controller.GetEntitiesWithComponent(ecs.CarriedComponent) + // _И_ носимые _И_ имеющие координаты, т.е. где-то лежащие + carrieds := Controller.GetEntitiesWithComponent(ecs.CarriedComponent, ecs.CoordsComponent) result := make([]ecs.Entity, 0) - 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) + for _, carried := range carrieds { + carriedCoords := Controller.GetComponent(carried, ecs.CoordsComponent).(types.Coords) if pickerCoords.IsAdjacentTo(&carriedCoords) { result = append(result, carried) }