messy WIP; default objects + witch stuff
parent
89e4c4b095
commit
1664d678cb
|
@ -84,6 +84,10 @@ func newServer() (*gameWorldServer, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err = db.Ensure(); err != nil {
|
||||
return nil, fmt.Errorf("failed to ensure default entities: %w", err)
|
||||
}
|
||||
|
||||
if err = db.ClearSessions(); err != nil {
|
||||
return nil, fmt.Errorf("could not clear sessions: %w", err)
|
||||
}
|
||||
|
@ -91,12 +95,17 @@ func newServer() (*gameWorldServer, error) {
|
|||
s := &gameWorldServer{
|
||||
msgRouter: make(map[string]func(*proto.ClientMessage) error),
|
||||
db: db,
|
||||
Gateway: witch.NewGateway(),
|
||||
}
|
||||
gw := witch.NewGateway(s.HandleCmd)
|
||||
s.Gateway = gw
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *gameWorldServer) HandleCmd(verb, rest string, sender *db.Object) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func (s *gameWorldServer) Commands(stream proto.GameWorld_CommandsServer) error {
|
||||
var sid string
|
||||
for {
|
||||
|
@ -129,6 +138,10 @@ func (s *gameWorldServer) Commands(stream proto.GameWorld_CommandsServer) error
|
|||
}
|
||||
log.Printf("found avatar %#v", avatar)
|
||||
|
||||
s.HandleCmd(cmd.Verb, cmd.Rest, avatar)
|
||||
|
||||
/*
|
||||
|
||||
switch cmd.Verb {
|
||||
case "say":
|
||||
if err = s.HandleSay(avatar, cmd.Rest); err != nil {
|
||||
|
@ -144,6 +157,8 @@ func (s *gameWorldServer) Commands(stream proto.GameWorld_CommandsServer) error
|
|||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
msg := &proto.ClientMessage{
|
||||
|
@ -202,6 +217,7 @@ func (s *gameWorldServer) Register(ctx context.Context, auth *proto.AuthInfo) (s
|
|||
return nil, fmt.Errorf("failed to find avatar for %s: %w", sessionID, err)
|
||||
}
|
||||
|
||||
/*
|
||||
bedroom, err := s.db.BedroomBySessionID(sessionID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find bedroom for %s: %w", sessionID, err)
|
||||
|
@ -211,6 +227,16 @@ func (s *gameWorldServer) Register(ctx context.Context, auth *proto.AuthInfo) (s
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to move %d into %d: %w", av.ID, bedroom.ID, err)
|
||||
}
|
||||
*/
|
||||
|
||||
foyer, err := s.db.GetObject("system", "foyer")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find foyer: %w", err)
|
||||
}
|
||||
|
||||
if err = s.db.MoveInto(*av, *foyer); err != nil {
|
||||
return nil, fmt.Errorf("failed to move %d into %d: %w", av.ID, foyer.ID, err)
|
||||
}
|
||||
|
||||
// TODO send room info, avatar info to client (need to figure this out and update proto)
|
||||
|
||||
|
|
118
server/db/db.go
118
server/db/db.go
|
@ -26,6 +26,12 @@ type DB interface {
|
|||
EndSession(string) error
|
||||
ClearSessions() error
|
||||
|
||||
// General
|
||||
GetObject(owner, name string) (*Object, error)
|
||||
|
||||
// Defaults
|
||||
Ensure() error
|
||||
|
||||
// Presence
|
||||
ActiveSessions() ([]Session, error)
|
||||
AvatarBySessionID(string) (*Object, error)
|
||||
|
@ -38,6 +44,7 @@ type Account struct {
|
|||
ID int
|
||||
Name string
|
||||
Pwhash string
|
||||
God bool
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
|
@ -70,7 +77,59 @@ func NewDB(connURL string) (DB, error) {
|
|||
return pgdb, nil
|
||||
}
|
||||
|
||||
// Ensure checks for and then creates default resources if they do not exist (like the Foyer)
|
||||
func (db *pgDB) Ensure() error {
|
||||
// TODO this is sloppy but shrug
|
||||
_, err := db.pool.Exec(context.Background(), schema)
|
||||
//log.Println(err)
|
||||
sysAcc, err := db.GetAccount("system")
|
||||
if err != nil {
|
||||
// TODO actually check error. for now assuming it means does not exist
|
||||
sysAcc, err = db.CreateGod("system", "")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create system account: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("%#v", sysAcc)
|
||||
|
||||
if _, err := db.GetObject("system", "foyer"); err != nil {
|
||||
data := map[string]string{}
|
||||
data["name"] = "foyer"
|
||||
data["description"] = "a big room. the ceiling is painted with constellations."
|
||||
foyer := &Object{
|
||||
Data: data,
|
||||
Script: "",
|
||||
// TODO default room script
|
||||
}
|
||||
if err = db.CreateObject(sysAcc, foyer); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *pgDB) CreateGod(name, password string) (account *Account, err error) {
|
||||
account = &Account{
|
||||
Name: name,
|
||||
Pwhash: password,
|
||||
God: true,
|
||||
}
|
||||
|
||||
return account, db.createAccount(account)
|
||||
}
|
||||
|
||||
func (db *pgDB) CreateAccount(name, password string) (account *Account, err error) {
|
||||
account = &Account{
|
||||
Name: name,
|
||||
Pwhash: password,
|
||||
}
|
||||
|
||||
return account, db.createAccount(account)
|
||||
}
|
||||
|
||||
func (db *pgDB) createAccount(account *Account) (err error) {
|
||||
ctx := context.Background()
|
||||
tx, err := db.pool.Begin(ctx)
|
||||
if err != nil {
|
||||
|
@ -79,13 +138,8 @@ func (db *pgDB) CreateAccount(name, password string) (account *Account, err erro
|
|||
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
account = &Account{
|
||||
Name: name,
|
||||
Pwhash: password,
|
||||
}
|
||||
|
||||
stmt := "INSERT INTO accounts (name, pwhash) VALUES ( $1, $2 ) RETURNING id"
|
||||
err = tx.QueryRow(ctx, stmt, name, password).Scan(&account.ID)
|
||||
stmt := "INSERT INTO accounts (name, pwhash, god) VALUES ( $1, $2, $3 ) RETURNING id"
|
||||
err = tx.QueryRow(ctx, stmt, account.Name, account.Pwhash, account.God).Scan(&account.ID)
|
||||
// TODO handle and cleanup unqiue violations
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -97,10 +151,11 @@ func (db *pgDB) CreateAccount(name, password string) (account *Account, err erro
|
|||
av := &Object{
|
||||
Avatar: true,
|
||||
Data: data,
|
||||
Script: "",
|
||||
}
|
||||
|
||||
stmt = "INSERT INTO objects ( avatar, data, owner ) VALUES ( $1, $2, $3 ) RETURNING id"
|
||||
err = tx.QueryRow(ctx, stmt, av.Avatar, av.Data, account.ID).Scan(&av.ID)
|
||||
stmt = "INSERT INTO objects ( avatar, data, owner, script ) VALUES ( $1, $2, $3, $4 ) RETURNING id"
|
||||
err = tx.QueryRow(ctx, stmt, av.Avatar, av.Data, account.ID, av.Script).Scan(&av.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -117,10 +172,11 @@ func (db *pgDB) CreateAccount(name, password string) (account *Account, err erro
|
|||
bedroom := &Object{
|
||||
Bedroom: true,
|
||||
Data: data,
|
||||
Script: "",
|
||||
}
|
||||
|
||||
stmt = "INSERT INTO objects ( bedroom, data, owner ) VALUES ( $1, $2, $3 ) RETURNING id"
|
||||
err = tx.QueryRow(ctx, stmt, bedroom.Bedroom, bedroom.Data, account.ID).Scan(&bedroom.ID)
|
||||
stmt = "INSERT INTO objects ( bedroom, data, owner, script ) VALUES ( $1, $2, $3, $4 ) RETURNING id"
|
||||
err = tx.QueryRow(ctx, stmt, bedroom.Bedroom, bedroom.Data, account.ID, bedroom.Script).Scan(&bedroom.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -131,9 +187,7 @@ func (db *pgDB) CreateAccount(name, password string) (account *Account, err erro
|
|||
return
|
||||
}
|
||||
|
||||
err = tx.Commit(ctx)
|
||||
|
||||
return
|
||||
return tx.Commit(ctx)
|
||||
}
|
||||
|
||||
func (db *pgDB) ValidateCredentials(name, password string) (*Account, error) {
|
||||
|
@ -142,6 +196,10 @@ func (db *pgDB) ValidateCredentials(name, password string) (*Account, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if a.Pwhash == "" {
|
||||
return nil, errors.New("this account cannot be logged into")
|
||||
}
|
||||
|
||||
// TODO hashing lol
|
||||
|
||||
if a.Pwhash != password {
|
||||
|
@ -276,6 +334,20 @@ func (db *pgDB) Earshot(obj Object) ([]Object, error) {
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (db *pgDB) GetObject(owner, name string) (obj *Object, err error) {
|
||||
ctx := context.Background()
|
||||
obj = &Object{}
|
||||
stmt := `
|
||||
SELECT id, avatar, data, owner, script
|
||||
FROM objects
|
||||
WHERE owner = $1 AND data['name'] = $2`
|
||||
err = db.pool.QueryRow(ctx, stmt, owner, fmt.Sprintf(`"%s"`, name)).Scan(
|
||||
&obj.ID, &obj.Avatar, &obj.Data, &obj.OwnerID, &obj.Script)
|
||||
// TODO i think the escaping here is going to create a sadness ^
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (db *pgDB) ActiveSessions() (out []Session, err error) {
|
||||
stmt := `SELECT id, account FROM sessions`
|
||||
rows, err := db.pool.Query(context.Background(), stmt)
|
||||
|
@ -299,6 +371,24 @@ func (db *pgDB) ClearSessions() (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (db *pgDB) CreateObject(owner *Account, obj *Object) error {
|
||||
ctx := context.Background()
|
||||
stmt := `
|
||||
INSERT INTO objects (avatar, bedroom, data, script, owner)
|
||||
VALUES ( $1, $2, $3, $4, $5)
|
||||
RETURNING id
|
||||
`
|
||||
|
||||
err := db.pool.QueryRow(ctx, stmt,
|
||||
obj.Avatar, obj.Bedroom, obj.Data, obj.Script, owner.ID).Scan(
|
||||
&obj.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func randSmell() string {
|
||||
// TODO seeding
|
||||
smells := []string{
|
||||
|
|
|
@ -72,7 +72,7 @@ func newScriptContext(obj db.Object) (*scriptContext, error) {
|
|||
return &scriptContext{}, nil
|
||||
}
|
||||
|
||||
func (sc *scriptContext) Handle(ver, rest string, sender, target *db.Object) error {
|
||||
func (sc *scriptContext) Handle(verb, rest string, sender, target *db.Object) error {
|
||||
|
||||
// TODO call _handle function from the Lstate
|
||||
return nil
|
||||
|
@ -82,12 +82,15 @@ type Gateway struct {
|
|||
// maps game object IDs to script contexts
|
||||
m map[int]*scriptContext
|
||||
mu sync.RWMutex
|
||||
cb func(string, string, *db.Object)
|
||||
}
|
||||
|
||||
func NewGateway() *Gateway {
|
||||
func NewGateway(cb func(string, string, *db.Object)) *Gateway {
|
||||
return &Gateway{
|
||||
m: map[int]*scriptContext{},
|
||||
mu: sync.RWMutex{},
|
||||
// TODO use cb from scriptContext
|
||||
cb: cb,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue