Skip to content

Commit

Permalink
Merge pull request #6 from TemirkhanN/main
Browse files Browse the repository at this point in the history
Fixes, race system, autologin.
  • Loading branch information
crilleaz committed Aug 31, 2023
2 parents 907bd22 + c78f210 commit ded57ce
Show file tree
Hide file tree
Showing 53 changed files with 1,195 additions and 592 deletions.
5 changes: 4 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
charset = utf-8

[*.yaml]
indent_size = 4
41 changes: 41 additions & 0 deletions data/race.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
- id: 1
name: Wouldren
description: Farmer, harvester and lumberjack. Come from Timberhart.
canCraft: false
canMine: false
canWoodcut: true
canHarvest: true
canGather: false
canBrew: false
stats:
strength: 10
defence: 5
maxHealth: 20

- id: 2
name: Ironhart
description: Miners and crafters. Come from Orveil city.
canCraft: true
canMine: true
canWoodcut: false
canHarvest: false
canGather: false
canBrew: false
stats:
strength: 15
defence: 8
maxHealth: 25

- id: 3
name: Highlander
description: Herb gatherers and brewers. Come from Pit.
canCraft: false
canMine: false
canWoodcut: false
canHarvest: false
canGather: true
canBrew: true
stats:
strength: 10
defence: 3
maxHealth: 30
2 changes: 1 addition & 1 deletion server.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function writeSystemLog(string $msg) {
}

$timer = \React\EventLoop\Loop::addPeriodicTimer($intervalInSeconds, function () use (&$lastExecutedTime) {
$resultLogs = DI::getService(\Game\Engine\Engine::class)->performTasks();
$resultLogs = DI::getService(Game\Server::class)->performTasks();

foreach ($resultLogs as $log) {
echo $log . PHP_EOL;
Expand Down
14 changes: 8 additions & 6 deletions src/API/HttpApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

namespace Game\API;

use Game\Auth\AuthService;
use Game\Chat\Chat;
use Game\Engine\Error;
use Game\Game;
use Game\Client;
use Game\Item\Item;
use Game\Item\ItemPrototypeRepository;
use Game\Player\Player;
use Game\Trade\Offer;
use Game\Trade\ShopRepository;
Expand All @@ -19,14 +19,14 @@ class HttpApi
{
private Player $player;

public function __construct(private readonly Game $game)
public function __construct(private readonly Client $client, private readonly AuthService $authService)
{

}

public function handle(Request $request): Response
{
$currentPlayer = $this->game->getCurrentPlayer();
$currentPlayer = $this->client->getCurrentPlayer();
if ($currentPlayer === null) {
return $this->failure('Player is not authenticated. Please, sign in first.');
}
Expand Down Expand Up @@ -88,11 +88,13 @@ private function banPlayer(Request $request): Response
return $this->failure('Username is empty');
}

if (!$this->player->isAdmin()) {
$user = $this->authService->getCurrentUser();
if ($user === null || !$user->isAdmin()) {
return $this->failure('Only admin can perform this action');
}

\DI::getService(Game::class)->banPlayer($username);
\DI::getService(AuthService::class)->banPlayer($username);
\DI::getService(Chat::class)->addSystemMessage(sprintf('User "%s" has been banned', $username));

return $this->success();
}
Expand Down
92 changes: 92 additions & 0 deletions src/Auth/AuthService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php
declare(strict_types=1);

namespace Game\Auth;

use Game\Engine\DBConnection;
use Game\Engine\Error;
use Game\User;

class AuthService
{
private ?User $currentUser = null;

public function __construct(private readonly DBConnection $db) {}

public function banPlayer(string $name): void
{
$this->db->execute("UPDATE users set banned = 1 WHERE anv = ?", [$name]);
}

public function register(string $playerName, string $password, ?string $ip = ''): null|Error
{
if ($playerName === '') {
return new Error('Username can not be empty');
}

if (mb_strlen($password) < 8) {
return new Error('Password must be at least 8 characters long');
}

if ($this->db->fetchRow('SELECT id FROM users WHERE anv=?', [$playerName]) !== []) {
return new Error('Username is already taken');
}

$ip = $ip ?? $_SERVER['REMOTE_ADDR'];

$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
$this->db->execute('INSERT INTO users (anv, pwd, last_ip) VALUES (?, ?, ?)', [$playerName, $hashedPassword, $ip]);

return null;
}

public function login(string $playerName, string $password): null|Error
{
$user = $this->db->fetchRow('SELECT * FROM users WHERE anv = ?', [$playerName]);

// User does not exist
if ($user === []) {
return new Error('Invalid username or password');
}

// Password does not match
if ($user['pwd'] !== $password && !password_verify($password, $user['pwd'])) {
return new Error('Invalid username or password');
}

if ($user['banned'] === 1) {
return new Error('User is banned');
}

$this->currentUser = null;
$_SESSION['username'] = $user['anv'];

return null;
}

public function logout(): void
{
session_destroy();
}

public function getCurrentUser(): ?User
{
if ($this->currentUser === null) {
if (!isset($_SESSION['username'])) {
return null;
}

$user = $this->db->fetchRow('SELECT id, anv as name, banned FROM users WHERE anv=?', [$_SESSION['username']]);
if ($user === []) {
// This shouldn't be possible but if this happens then it means user was deleted
$this->logout();

return null;
}

$this->currentUser = new User($user['id'], $user['name'], $user['banned'] === 1);
}

return $this->currentUser;
}
}
3 changes: 2 additions & 1 deletion src/Chat/Chat.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use Game\Engine\DBConnection;
use Game\Player\Player;
use Game\User;

readonly class Chat
{
Expand Down Expand Up @@ -40,6 +41,6 @@ public function getLastMessages(int $amount): iterable

private function isFromAdmin(string $sender): bool
{
return $sender === 'System' || Player::loadPlayer($sender, $this->db)->isAdmin();
return $sender === 'System' || User::hasAdminAccess($sender);
}
}
45 changes: 45 additions & 0 deletions src/Client.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);

namespace Game;

use Game\Auth\AuthService;
use Game\Player\CharacterRepository;
use Game\Player\Player;

readonly class Client
{
public function __construct(
private AuthService $authService,
private CharacterRepository $characterRepository
){}

public function run(): void
{
// TODO add self-sufficient front controller handling
}

public function getCurrentPlayer(): ?Player
{
$currentUser = $this->authService->getCurrentUser();
if ($currentUser === null) {
return null;
}

return $this->characterRepository->findByUser($currentUser);
}

/**
* Basically pretends to say that client is not running unless user is signed in
*
* @todo requires rethinking
*
* @return bool
*/
public function isRunning(): bool
{
$currentUser = $this->authService->getCurrentUser();

return $currentUser !== null;
}
}
5 changes: 3 additions & 2 deletions src/Dungeon/RewardCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ public function __construct(private DropChanceRepository $dropRepository)
$this->ttkCalculator = new TTKCalculator();
}

public function calculate(Dungeon $dungeon, Player $hunter, TimeInterval $timesSpentInDungeon): Reward
// TODO SRP is violated here. At the same time encapsulation is not fulfiled. Calculate ttk separately and issue them too.
public function calculate(Dungeon $dungeon, Player $hunter, int $minutesInDungeon): Reward
{
$approximateSpentMinutes = (int)round($timesSpentInDungeon->toMinutes());
$approximateSpentMinutes = $minutesInDungeon;
if ($approximateSpentMinutes === 0) {
return Reward::none();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Dungeon/TTKCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public function calculate(Player $hunter, Monster $prey): TimeInterval

public function calculateForMonster(Monster $hunter, Player $prey): TimeInterval
{
return $this->calculateTtk($hunter->attack, $prey->getDefence(), $prey->getMaxHealth());
return $this->calculateTtk($hunter->attack, $prey->getDefence(), $prey->getCurrentHealth());
}

private function calculateTtk(int $attack, int $defence, int $health): TimeInterval
Expand Down
36 changes: 0 additions & 36 deletions src/Engine/Debug.php

This file was deleted.

Loading

0 comments on commit ded57ce

Please sign in to comment.