fix lots of little bugs and get last_online working
This commit is contained in:
parent
ee19412965
commit
cfc1256d02
BIN
data/dk.db
BIN
data/dk.db
Binary file not shown.
@ -340,7 +340,7 @@ CREATE TABLE towns (
|
||||
`shop_list` TEXT NOT NULL
|
||||
);
|
||||
INSERT INTO towns VALUES
|
||||
(1, 'Midworld', 0, 0, 5, 0, 0, '1,2,3,17,18,19,28,29'),
|
||||
(1, 'Midworld', 0, 0, 1, 0, 0, '1,2,3,17,18,19,28,29'),
|
||||
(2, 'Roma', 30, 30, 10, 25, 5, '2,3,4,18,19,29'),
|
||||
(3, 'Bris', 70, -70, 25, 50, 15, '2,3,4,5,18,19,20,29.30'),
|
||||
(4, 'Kalle', -100, 100, 40, 100, 30, '5,6,8,10,12,21,22,23,29,30'),
|
||||
|
2
go.mod
2
go.mod
@ -3,7 +3,7 @@ module dk
|
||||
go 1.25.0
|
||||
|
||||
require (
|
||||
git.sharkk.net/Sharkk/Sushi v1.1.1
|
||||
git.sharkk.net/Sharkk/Sushi v1.2.0
|
||||
github.com/valyala/fasthttp v1.65.0
|
||||
zombiezen.com/go/sqlite v1.4.2
|
||||
)
|
||||
|
4
go.sum
4
go.sum
@ -1,5 +1,5 @@
|
||||
git.sharkk.net/Sharkk/Sushi v1.1.1 h1:ynU16l6vAhY/JUwHlI4zMQiPuL9lcs88W/mAGZsL4Rw=
|
||||
git.sharkk.net/Sharkk/Sushi v1.1.1/go.mod h1:S84ACGkuZ+BKzBO4lb5WQnm5aw9+l7VSO2T1bjzxL3o=
|
||||
git.sharkk.net/Sharkk/Sushi v1.2.0 h1:RwOCZmgaOqtkmuK2Z7/esdLbhSXJZphsOsWEHni4Sss=
|
||||
git.sharkk.net/Sharkk/Sushi v1.2.0/go.mod h1:S84ACGkuZ+BKzBO4lb5WQnm5aw9+l7VSO2T1bjzxL3o=
|
||||
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
|
||||
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
|
@ -20,6 +20,38 @@ type FightResult struct {
|
||||
Ended bool
|
||||
Victory bool
|
||||
Won bool
|
||||
RewardGold int
|
||||
RewardExp int
|
||||
}
|
||||
|
||||
func (r *FightResult) EndFightWithVictory(monster *monsters.Monster, user *users.User) {
|
||||
rewardGold, rewardExp := calculateRewards(monster, user)
|
||||
|
||||
r.FightUpdates["victory"] = true
|
||||
r.FightUpdates["won"] = true
|
||||
r.FightUpdates["reward_gold"] = rewardGold
|
||||
r.FightUpdates["reward_exp"] = rewardExp
|
||||
|
||||
r.UserUpdates = map[string]any{
|
||||
"fight_id": 0,
|
||||
"currently": "Exploring",
|
||||
"gold": user.Gold + rewardGold,
|
||||
"exp": user.Exp + rewardExp,
|
||||
}
|
||||
|
||||
// Handle level up
|
||||
newLevel, newStats := calculateLevelUp(user.Level, user.Exp+rewardExp, user.Strength, user.Dexterity)
|
||||
if newLevel > user.Level {
|
||||
r.UserUpdates["level"] = newLevel
|
||||
r.UserUpdates["strength"] = newStats.Strength
|
||||
r.UserUpdates["dexterity"] = newStats.Dexterity
|
||||
}
|
||||
|
||||
r.Ended = true
|
||||
r.Victory = true
|
||||
r.Won = true
|
||||
r.RewardGold = rewardGold
|
||||
r.RewardExp = rewardExp
|
||||
}
|
||||
|
||||
func HandleAttack(fight *fights.Fight, user *users.User) *FightResult {
|
||||
@ -61,10 +93,7 @@ func HandleAttack(fight *fights.Fight, user *users.User) *FightResult {
|
||||
}
|
||||
|
||||
finalDamage := int(damage)
|
||||
newMonsterHP := fight.MonsterHP - finalDamage
|
||||
if newMonsterHP < 0 {
|
||||
newMonsterHP = 0
|
||||
}
|
||||
newMonsterHP := max(fight.MonsterHP-finalDamage, 0)
|
||||
|
||||
result := &FightResult{
|
||||
FightUpdates: map[string]any{"monster_hp": newMonsterHP},
|
||||
@ -73,37 +102,13 @@ func HandleAttack(fight *fights.Fight, user *users.User) *FightResult {
|
||||
|
||||
// Check if monster defeated
|
||||
if newMonsterHP <= 0 {
|
||||
rewardGold, rewardExp := calculateRewards(monster, user)
|
||||
|
||||
result.FightUpdates["victory"] = true
|
||||
result.FightUpdates["won"] = true
|
||||
result.FightUpdates["reward_gold"] = rewardGold
|
||||
result.FightUpdates["reward_exp"] = rewardExp
|
||||
|
||||
result.UserUpdates = map[string]any{
|
||||
"fight_id": 0,
|
||||
"currently": "Exploring",
|
||||
"gold": user.Gold + rewardGold,
|
||||
"exp": user.Exp + rewardExp,
|
||||
}
|
||||
|
||||
// Handle level up
|
||||
newLevel, newStats := calculateLevelUp(user.Level, user.Exp+rewardExp, user.Strength, user.Dexterity)
|
||||
if newLevel > user.Level {
|
||||
result.UserUpdates["level"] = newLevel
|
||||
result.UserUpdates["strength"] = newStats.Strength
|
||||
result.UserUpdates["dexterity"] = newStats.Dexterity
|
||||
}
|
||||
|
||||
result.EndFightWithVictory(monster, user)
|
||||
result.LogAction = func() error {
|
||||
if err := fightlogs.AddAttackHit(fight.ID, finalDamage); err != nil {
|
||||
return err
|
||||
}
|
||||
return fightlogs.AddMonsterDeath(fight.ID, monster.Name)
|
||||
}
|
||||
result.Ended = true
|
||||
result.Victory = true
|
||||
result.Won = true
|
||||
}
|
||||
|
||||
return result
|
||||
@ -135,31 +140,20 @@ func HandleSpell(fight *fights.Fight, user *users.User, spellID int) *FightResul
|
||||
|
||||
switch spell.Type {
|
||||
case spells.TypeHealing:
|
||||
newHP := user.HP + spell.Attribute
|
||||
if newHP > user.MaxHP {
|
||||
newHP = user.MaxHP
|
||||
}
|
||||
newHP := min(user.HP+spell.Attribute, user.MaxHP)
|
||||
result.UserUpdates["hp"] = newHP
|
||||
result.LogAction = func() error { return fightlogs.AddSpellHeal(fight.ID, spell.Name, spell.Attribute) }
|
||||
|
||||
case spells.TypeHurt:
|
||||
newMonsterHP := fight.MonsterHP - spell.Attribute
|
||||
if newMonsterHP < 0 {
|
||||
newMonsterHP = 0
|
||||
}
|
||||
newMonsterHP := max(fight.MonsterHP-spell.Attribute, 0)
|
||||
result.FightUpdates = map[string]any{"monster_hp": newMonsterHP}
|
||||
result.LogAction = func() error { return fightlogs.AddSpellHurt(fight.ID, spell.Name, spell.Attribute) }
|
||||
|
||||
if newMonsterHP <= 0 {
|
||||
result.FightUpdates["victory"] = true
|
||||
result.FightUpdates["won"] = true
|
||||
result.FightUpdates["reward_gold"] = 10
|
||||
result.FightUpdates["reward_exp"] = 5
|
||||
result.UserUpdates["fight_id"] = 0
|
||||
result.UserUpdates["currently"] = "Exploring"
|
||||
result.Ended = true
|
||||
result.Victory = true
|
||||
result.Won = true
|
||||
monster, err := monsters.Find(fight.MonsterID)
|
||||
if err == nil {
|
||||
result.EndFightWithVictory(monster, user)
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
@ -218,10 +212,7 @@ func HandleMonsterAttack(fight *fights.Fight, user *users.User) *FightResult {
|
||||
}
|
||||
|
||||
finalDamage := int(damage)
|
||||
newHP := user.HP - finalDamage
|
||||
if newHP < 0 {
|
||||
newHP = 0
|
||||
}
|
||||
newHP := max(user.HP-finalDamage, 0)
|
||||
|
||||
result := &FightResult{
|
||||
UserUpdates: map[string]any{"hp": newHP},
|
||||
@ -301,14 +292,22 @@ func findClosestTown(x, y int) *towns.Town {
|
||||
}
|
||||
|
||||
func calculateRewards(monster *monsters.Monster, user *users.User) (int, int) {
|
||||
minExp := (monster.MaxExp * 5) / 6
|
||||
// More generous reward range: 90-100% of max instead of 83-100%
|
||||
minExp := (monster.MaxExp * 9) / 10
|
||||
maxExp := monster.MaxExp
|
||||
exp := rand.Intn(maxExp-minExp+1) + minExp
|
||||
if exp < 1 {
|
||||
exp = 1 // Guaranteed minimum
|
||||
}
|
||||
|
||||
minGold := (monster.MaxGold * 5) / 6
|
||||
minGold := (monster.MaxGold * 9) / 10
|
||||
maxGold := monster.MaxGold
|
||||
gold := rand.Intn(maxGold-minGold+1) + minGold
|
||||
if gold < 1 {
|
||||
gold = 1 // Guaranteed minimum
|
||||
}
|
||||
|
||||
// Apply bonuses
|
||||
expBonus := (user.ExpBonus * exp) / 100
|
||||
exp += expBonus
|
||||
|
||||
|
@ -44,7 +44,7 @@ func RightAside(ctx sushi.Ctx) map[string]any {
|
||||
return data
|
||||
}
|
||||
|
||||
user := ctx.UserValue("user").(*users.User)
|
||||
user := ctx.GetCurrentUser().(*users.User)
|
||||
|
||||
data["_expprog"] = fmt.Sprintf("%.1f", user.ExpProgress())
|
||||
|
||||
|
@ -95,46 +95,35 @@ func showRegister(ctx sushi.Ctx) {
|
||||
|
||||
// processRegister handles registration form submission
|
||||
func processRegister(ctx sushi.Ctx) {
|
||||
fmt.Println("DEBUG: Starting registration process")
|
||||
|
||||
username := strings.TrimSpace(ctx.Form("username").String())
|
||||
email := strings.TrimSpace(ctx.Form("email").String())
|
||||
userPassword := ctx.Form("password").String()
|
||||
confirmPassword := ctx.Form("confirm_password").String()
|
||||
|
||||
fmt.Printf("DEBUG: Form data - username: '%s', email: '%s', password length: %d\n",
|
||||
username, email, len(userPassword))
|
||||
|
||||
formData := map[string]string{
|
||||
"username": username,
|
||||
"email": email,
|
||||
}
|
||||
|
||||
if err := validateRegistration(username, email, userPassword, confirmPassword); err != nil {
|
||||
fmt.Printf("DEBUG: Validation failed: %v\n", err)
|
||||
setFlashAndFormData(ctx, err.Error(), formData)
|
||||
ctx.Redirect("/register")
|
||||
return
|
||||
}
|
||||
fmt.Println("DEBUG: Validation passed")
|
||||
|
||||
// Check if username already exists
|
||||
if _, err := users.ByUsername(username); err == nil {
|
||||
fmt.Printf("DEBUG: Username '%s' already exists\n", username)
|
||||
setFlashAndFormData(ctx, "Username already exists", formData)
|
||||
ctx.Redirect("/register")
|
||||
return
|
||||
}
|
||||
fmt.Printf("DEBUG: Username '%s' is available\n", username)
|
||||
|
||||
// Check if email already exists
|
||||
if _, err := users.ByEmail(email); err == nil {
|
||||
fmt.Printf("DEBUG: Email '%s' already exists\n", email)
|
||||
setFlashAndFormData(ctx, "Email already registered", formData)
|
||||
ctx.Redirect("/register")
|
||||
return
|
||||
}
|
||||
fmt.Printf("DEBUG: Email '%s' is available\n", email)
|
||||
|
||||
// Create new user
|
||||
user := users.New()
|
||||
@ -144,34 +133,26 @@ func processRegister(ctx sushi.Ctx) {
|
||||
user.ClassID = 1
|
||||
user.Auth = 1
|
||||
|
||||
fmt.Printf("DEBUG: Created user struct with ID: %d\n", user.ID)
|
||||
|
||||
// Validate before inserting
|
||||
if err := user.Validate(); err != nil {
|
||||
fmt.Printf("DEBUG: User validation failed: %v\n", err)
|
||||
setFlashAndFormData(ctx, fmt.Sprintf("Invalid user data: %s", err.Error()), formData)
|
||||
ctx.Redirect("/register")
|
||||
return
|
||||
}
|
||||
fmt.Println("DEBUG: User validation passed")
|
||||
|
||||
if err := user.Insert(); err != nil {
|
||||
fmt.Printf("DEBUG: User insert failed: %v\n", err)
|
||||
setFlashAndFormData(ctx, "Failed to create account", formData)
|
||||
ctx.Redirect("/register")
|
||||
return
|
||||
}
|
||||
fmt.Printf("DEBUG: User inserted successfully with ID: %d\n", user.ID)
|
||||
|
||||
// Auto-login after registration
|
||||
ctx.Login(user.ID, user)
|
||||
fmt.Printf("DEBUG: User logged in with ID: %d\n", user.ID)
|
||||
|
||||
// Set success message
|
||||
sess := ctx.GetCurrentSession()
|
||||
sess.SetFlash("success", fmt.Sprintf("Greetings, %s!", user.Username))
|
||||
|
||||
fmt.Println("DEBUG: Registration completed successfully")
|
||||
ctx.Redirect("/")
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,7 @@ func handleFightAction(ctx sushi.Ctx) {
|
||||
// Handle fight end states
|
||||
if result.Ended {
|
||||
if result.Won {
|
||||
sess.SetFlash("success", fmt.Sprintf("Victory! You gained rewards!"))
|
||||
sess.SetFlash("success", fmt.Sprintf("Victory! You gained %d gold and %d experience!", result.RewardGold, result.RewardExp))
|
||||
ctx.Redirect("/explore", 302)
|
||||
} else if result.Victory {
|
||||
sess.SetFlash("error", "You have been defeated! You lost some gold and were sent to the nearest town.")
|
||||
|
@ -54,12 +54,18 @@ func Move(ctx sushi.Ctx) {
|
||||
return
|
||||
}
|
||||
|
||||
err = database.Transaction(func() error {
|
||||
return database.Update("users", map[string]any{
|
||||
updateData := map[string]any{
|
||||
"currently": currently,
|
||||
"x": newX,
|
||||
"y": newY,
|
||||
}, "id", user.ID)
|
||||
}
|
||||
|
||||
if currently == "Fighting" {
|
||||
updateData["fight_id"] = user.FightID
|
||||
}
|
||||
|
||||
err = database.Transaction(func() error {
|
||||
return database.Update("users", updateData, "id", user.ID)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
@ -77,9 +77,17 @@ func showTown(ctx sushi.Ctx) {
|
||||
|
||||
func showInn(ctx sushi.Ctx) {
|
||||
town := ctx.UserValue("town").(*towns.Town)
|
||||
sess := ctx.GetCurrentSession()
|
||||
|
||||
value, exists := sess.GetFlash("rested")
|
||||
rested := false
|
||||
if exists && value == true {
|
||||
rested = true
|
||||
}
|
||||
|
||||
components.RenderPage(ctx, town.Name+" Inn", "town/inn.html", map[string]any{
|
||||
"town": town,
|
||||
"rested": false,
|
||||
"rested": rested,
|
||||
})
|
||||
}
|
||||
|
||||
@ -102,17 +110,14 @@ func rest(ctx sushi.Ctx) {
|
||||
"tp": user.MaxTP,
|
||||
}, "id", user.ID)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
sess.SetFlash("error", "Failed to rest at inn.")
|
||||
ctx.Redirect("/town/inn")
|
||||
return
|
||||
}
|
||||
|
||||
components.RenderPage(ctx, town.Name+" Inn", "town/inn.html", map[string]any{
|
||||
"town": town,
|
||||
"rested": true,
|
||||
})
|
||||
sess.SetFlash("rested", true)
|
||||
ctx.Redirect("/town/inn")
|
||||
}
|
||||
|
||||
func showShop(ctx sushi.Ctx) {
|
||||
|
17
main.go
17
main.go
@ -8,6 +8,7 @@ import (
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"dk/internal/control"
|
||||
"dk/internal/database"
|
||||
@ -68,13 +69,27 @@ func start(port string) error {
|
||||
|
||||
template.InitializeCache(cwd)
|
||||
|
||||
authMW := auth.New(getUserByID)
|
||||
|
||||
app := sushi.New()
|
||||
sushi.InitSessions(filepath.Join(cwd, "data/sessions.json"))
|
||||
|
||||
app.Use(session.Middleware())
|
||||
app.Use(auth.Middleware(getUserByID))
|
||||
app.Use(authMW.Middleware())
|
||||
app.Use(csrf.Middleware())
|
||||
app.Use(timing.Middleware())
|
||||
app.Use(func(ctx sushi.Ctx, next func()) {
|
||||
if ctx.IsAuthenticated() {
|
||||
user := ctx.GetCurrentUser().(*users.User)
|
||||
now := time.Now().Unix()
|
||||
if (now - user.LastOnline) >= 540 { // 540 seconds = 9 minutes
|
||||
database.Update("users", map[string]any{
|
||||
"last_online": now,
|
||||
}, "id", user.ID)
|
||||
}
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
app.Get("/", routes.Index)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user