Skip to content

Commit

Permalink
Initial module and character for Root RPG
Browse files Browse the repository at this point in the history
Starts on #1754
  • Loading branch information
omnicolor committed Oct 30, 2024
1 parent da5d567 commit 8de243e
Show file tree
Hide file tree
Showing 18 changed files with 774 additions and 0 deletions.
42 changes: 42 additions & 0 deletions Modules/Root/app/Casts/AttributeCast.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Modules\Root\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Database\Eloquent\Model;
use Modules\Root\ValueObjects\Attribute;

/**
* @implements CastsAttributes<Attribute, mixed>
*/
class AttributeCast implements CastsAttributes
{
/**
* @param array<string, mixed> $attributes
*/
public function get(
Model $model,
string $key,
mixed $value,
array $attributes,
): Attribute {
return new Attribute((int)$value);
}

/**
* @param array<string, mixed> $attributes
*/
public function set(
Model $model,
string $key,
mixed $value,
array $attributes
): int {
if ($value instanceof Attribute) {
return $value->value;
}
return $value;
}
}
45 changes: 45 additions & 0 deletions Modules/Root/app/Http/Controllers/CharactersController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace Modules\Root\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Response;
use Illuminate\View\View;
use Modules\Root\Http\Resources\CharacterResource;
use Modules\Root\Models\Character;

class CharactersController extends Controller
{
/**
* @psalm-suppress PossiblyUnusedMethod
*/
public function index(Request $request): JsonResource
{
/** @var User */
$user = $request->user();
return CharacterResource::collection(
Character::where('owner', $user->email)->get()
);
}

/**
* @psalm-suppress PossiblyUnusedMethod
*/
public function show(Request $request, Character $character): JsonResource
{
/** @var User */
$user = $request->user();
$campaign = $character->campaign();
abort_if(
$user->email !== $character->owner
&& (null === $campaign || $user->isNot($campaign->gamemaster)),
Response::HTTP_NOT_FOUND
);
return new CharacterResource($character);
}
}
82 changes: 82 additions & 0 deletions Modules/Root/app/Http/Resources/CharacterResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

declare(strict_types=1);

namespace Modules\Root\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\MissingValue;
use Modules\Root\Models\Character;

/**
* @mixin Character
*/
class CharacterResource extends JsonResource
{
/**
* @return array{
* name: string,
* meta: array{
* look: string,
* species: string
* },
* stats: array{
* charm: int,
* cunning: int,
* finese: int,
* luck: int,
* might: int
* },
* id: string,
* campaign_id: MissingValue|integer,
* system: string,
* owner: array{
* id: integer,
* name: string
* },
* links: array{
* self: string,
* campaign: MissingValue|string
* }
* }
*/
public function toArray(Request $request): array
{
return [
'name' => $this->name,
'meta' => [
'look' => $this->look,
'species' => $this->species,
],
'stats' => [
'charm' => $this->charm->value,
'cunning' => $this->cunning->value,
'finese' => $this->finese->value,
'luck' => $this->luck->value,
'might' => $this->might->value,
],
'id' => $this->id,
'campaign_id' => $this->when(
null !== $this->campaign_id,
$this->campaign_id,
),
'system' => $this->system,
'owner' => [
// @phpstan-ignore staticMethod.dynamicCall
'id' => $this->user()->id,
// @phpstan-ignore staticMethod.dynamicCall
'name' => $this->user()->name,
],
'links' => [
'self' => route('alien.characters.show', $this->id),
'campaign' => $this->when(
null !== $this->campaign_id,
null !== $this->campaign_id
? route('campaigns.show', $this->campaign_id)
: null,
),
],
];
}
}
91 changes: 91 additions & 0 deletions Modules/Root/app/Models/Character.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

declare(strict_types=1);

namespace Modules\Root\Models;

use App\Models\Character as BaseCharacter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Modules\Root\Casts\AttributeCast;
use Modules\Root\Database\Factories\CharacterFactory;
use Modules\Root\ValueObjects\Attribute;
use Stringable;

/**
* @property Attribute $charm
* @property Attribute $cunning
* @property Attribute $finese
* @property string $look
* @property Attribute $luck
* @property Attribute $might
* @property string $name
* @property string $species
* @property string $system
*/
class Character extends BaseCharacter implements Stringable
{
use HasFactory;

/**
* @var array<array-key, mixed>
*/
protected $attributes = [
'system' => 'root',
];

protected $casts = [
'charm' => AttributeCast::class,
'cunning' => AttributeCast::class,
'finese' => AttributeCast::class,
'luck' => AttributeCast::class,
'might' => AttributeCast::class,
'name' => 'string',
'system' => 'string',
];

/**
* The attributes that are mass assignable.
* @var array<int, string>
*/
protected $fillable = [
'charm',
'cunning',
'finese',
'luck',
'might',
'name',
'species',
'system',
];

/**
* @phpstan-ignore-next-line
* @var array<array-key, string>
*/
protected $hidden = [
'_id',
];

public function __toString(): string
{
return $this->name ?? 'Unnamed character';
}

protected static function booted(): void
{
static::addGlobalScope(
'root',
function (Builder $builder): void {
$builder->where('system', 'root');
}
);
}

protected static function newFactory(): Factory
{
return CharacterFactory::new();
}
}
Loading

0 comments on commit 8de243e

Please sign in to comment.