Skip to content
Open
2 changes: 1 addition & 1 deletion Controllers/Api/Other/NpcSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public function process(array $args): int
if ($noPicture) {
$storage = Storage::get();
$npcs = array_values(array_filter($npcs, function (array $npc) use ($storage): bool {
return !$storage->exists('npcs/' . $npc['npc_id'] . '.png');
return !$storage->exists('npcs/' . $npc['npc_id'] . '.webp');
}));
}

Expand Down
8 changes: 5 additions & 3 deletions Controllers/Website/Cast.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ class Cast extends WebpageController
*/
public function process(array $args): int
{
$voiceActorId = $args[0];
$contributorId = $args[0];
$cnm = new ContentManager();
$voiceActor = $cnm->getVoiceActor($voiceActorId);
$voiceActor = $cnm->getVoiceActor($contributorId);
if ($voiceActor === false) {
//Voice actor with this ID doesn't exist
return 404;
Expand All @@ -26,7 +26,7 @@ public function process(array $args): int

self::$data['cast_voice_actor'] = $voiceActor;

$questRecordings = $cnm->getVoiceActorRecordings($voiceActorId);
$questRecordings = $cnm->getVoiceActorRecordings($contributorId);
$npcGroups = [];
foreach ($questRecordings as $quest) {
foreach ($quest->getNpcs() as $npc) {
Expand All @@ -49,6 +49,8 @@ public function process(array $args): int
}
}
self::$data['cast_npc_groups'] = array_values($npcGroups);
self::$data['cast_scripted_quests'] = $cnm->getWritersQuests($contributorId);
self::$data['cast_edited_npcs'] = $cnm->getEditorsNpcsByQuests($contributorId);

$uuid = $this->loadUUID(); //Also saves UUID in $_SESSION
self::$data['cast_uuid'] = $uuid;
Expand Down
2 changes: 1 addition & 1 deletion Controllers/Website/Quest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ private function get(array $args): int
return 404;
}

$this->quest->getNpcs(true); //Also load and save NPCs themselves into attribute
$this->quest->getNpcs(true); //Also load and save NPCs themselves into attribute, also loads voice actors and sound editors

self::$data['quest_quest'] = $this->quest;

Expand Down
20 changes: 14 additions & 6 deletions Controllers/Website/WebpageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,14 @@ private function sanitize($value)
$return = $value;
}
else if ($value instanceof Quest) {
$id = $this->sanitize($value->getId());
$name = $this->sanitize($value->getName());
$degeneratedName = $this->sanitize($value->getDegeneratedName());
$quest = new Quest(array('id' => $id, 'name' => $name, 'degenerated_name' => $degeneratedName));
$attributes = [];
$attributes['id'] = $this->sanitize($value->getId());
$attributes['name'] = $this->sanitize($value->getName());
$attributes['degenerated_name'] = $this->sanitize($value->getDegeneratedName());
if ($value->getScriptAuthor() !== null) {
$attributes['writer'] = $this->sanitize($value->getScriptAuthor());
}
$quest = new Quest($attributes);
foreach ($value->getNpcs() ?? [] as $npc) {
$quest->addNpc($this->sanitize($npc));
}
Expand All @@ -160,18 +164,22 @@ private function sanitize($value)
$attr['upvotes'] = $this->sanitize($value->getUpvotes());
$attr['downvotes'] = $this->sanitize($value->getDownvotes());
$attr['comments'] = $this->sanitize($value->getCommentsCount());
$voiceActor = $this->sanitize($value->getVoiceActor());
$voiceActor = ($value->getVoiceActor() !== null) ? $this->sanitize($value->getVoiceActor()) : null;
$npc = new Npc($attr);
if ($voiceActor !== null) {
$npc->setVoiceActor($voiceActor);
}
if ($value->getSoundEditor() !== null) {
foreach ($value->getSoundEditor() as $quest => $editor) {
$npc->setSoundEditor(new Quest(['id' => $this->sanitize($quest)]), $this->sanitize($editor));
}
}
foreach ($value->getRecordings() as $recording) {
$npc->addRecording($this->sanitize($recording));
}
$return = $npc;
}
else if ($value instanceof Recording) {
$return = $value;
$attr = array();
$attr['id'] = $this->sanitize($value->id);
$attr['npc_id'] = $this->sanitize($value->npcId);
Expand Down
6 changes: 3 additions & 3 deletions Models/Api/VersionChecker/VersionConfig/version.ini
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@

; The number of the latest version of the mod (forge and fabric variant)
; Value is a string, using dots to separate numbers
fabric_newestVersion=1.10.7
fabric_newestVersion=1.14.2

; From what version should the player receive an update notification (forge and fabric variant)
fabric_updateNotification=1.10.5
fabric_updateNotification=1.14.1

; From what version should the mod be killed (forge and fabric variant)
fabric_killSwitchVersion=0

; Direct link to download an up-to-date .jar installer file
; Value is a string, starting with "https://voicesofwynn.com/download/"
fabric_directUpdateLink=https://cdn.modrinth.com/data/Hn8Ot3qH/versions/khmPRuYl/Voices-of-Wynn-fabric-1.10.7-fabric%2BMC-1.21.4.jar
fabric_directUpdateLink=https://cdn.modrinth.com/data/Hn8Ot3qH/versions/yDmZmOys/Voices-of-Wynn-fabric-1.14.2-fabric%2BMC-1.21.11.jar

; Link to a download page for the latest version of the mod, containing a changelog and other information
; Value is a string, starting with "https://voicesofwynn.com/downloads/"
Expand Down
43 changes: 42 additions & 1 deletion Models/Website/ContentManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public function getVoiceActorRecordings($id): array
$quests[] = $currentQuest;
}
$currentQuest = new Quest($recording);
$currentNpc = new Npc(array('id' => $recording['npc'], 'name' => $recording['nname'], 'archived' => $recording['archived'], 'upvotes' => $recording['upvotes'], 'downvotes' => $recording['downvotes'], 'comments' => $recording['comments'])); //"npc" is a key for NPC's ID
$currentNpc = new Npc(array('id' => $recording['npc'], 'name' => $recording['nname'], 'archived' => $recording['archived'], 'upvotes' => $recording['upvotes'], 'downvotes' => $recording['downvotes'], 'comments' => $recording['comments'], 'voice_actor' => $id)); //"npc" is a key for NPC's ID
}

$recordingObj = new Recording($recording);
Expand All @@ -183,6 +183,47 @@ public function getVoiceActorRecordings($id): array
return $quests;
}

public function getWritersQuests(int $writerId) : array
{
$query = '
SELECT quest.quest_id, quest.name, quest.degenerated_name, quest.writer
FROM quest
WHERE quest.writer = ?
ORDER BY quest_id;';
$result = (new Db('Website/DbInfo.ini'))->fetchQuery($query, array($writerId), true);

if ($result === false) {
return [];
}

return array_map(function($record) { return new Quest($record); }, $result);
}

public function getEditorsNpcsByQuests(int $editorId) : array
{
$query = '
SELECT
quest.quest_id, quest.name AS "qname", quest.degenerated_name AS "dname",
npc.npc_id, npc.name AS "nname"
FROM quest
JOIN npc_quest ON npc_quest.quest_id = quest.quest_id
JOIN npc ON npc.npc_id = npc_quest.npc_id
WHERE npc_quest.editor = ?
ORDER BY npc_id;';
$result = (new Db('Website/DbInfo.ini'))->fetchQuery($query, array($editorId), true);

if ($result === false) {
return array();
}

$npcsByQuest = [];
foreach ($result as $dbRow) {
$npcsByQuest[] = ['quest' => new Quest($dbRow), 'npc' => new Npc($dbRow)];
}

return $npcsByQuest;
}

public function getNpcRecordings($id): array
{
$db = new Db('Website/DbInfo.ini');
Expand Down
39 changes: 36 additions & 3 deletions Models/Website/Npc.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class Npc implements JsonSerializable
private int $id = 0;
private string $name = '';
private string $degeneratedName = '';
private $voiceActor;
private User $voiceActor;
private array $soundEditors;
private bool $archived = false;
private int $upvotes = 0;
private int $downvotes = 0;
Expand Down Expand Up @@ -67,6 +68,15 @@ public function __construct(array $data)
break;
case 'comments':
$this->comments = $value;
break;
case 'voice_actor':
if ($value instanceof User) {
$this->voiceActor = $value;
break;
}
$va = new User();
$va->setData(['id' => $value]);
$this->voiceActor = $va;
break;
}
}
Expand All @@ -86,6 +96,19 @@ public function setVoiceActor(User $voiceActor) : void
$this->voiceActor = $voiceActor;
}

/**
* SoundEditor setter
* @param Quest $quest Quest in which voicing of this NPC was edited by the given editor
* @param User $editor User who is responsible for editing this NPC's recordings in the given quest
*/
public function setSoundEditor(Quest $quest, User $editor) : void
{
if (!isset($this->soundEditors)) {
$this->soundEditors = [];
}
$this->soundEditors[$quest->getId()] = $editor;
}

/**
* Method setting a new voice actor and updating the database
* @param User $voiceActor
Expand Down Expand Up @@ -363,7 +386,7 @@ public function archive() : int
unset($replacementId);

//Copy profile picture
Storage::get()->copy('npcs/'.$this->id.'.png', 'npcs/'.$replacementNpc->getId().'.png');
Storage::get()->copy('npcs/'.$this->id.'.webp', 'npcs/'.$replacementNpc->getId().'.webp');

//Unlink this NPC from all quests and link the new one
$inString = trim(str_repeat('?,', count($questIds)), ',');
Expand Down Expand Up @@ -458,9 +481,19 @@ public function getDegeneratedName() : ?string
*/
public function getVoiceActor() : ?User
{
return $this->voiceActor;
return isset($this->voiceActor) ? $this->voiceActor : null;
}

/**
* SoundEditor getter
* @param ?Quest $quest Quest in which this NPC has recordings that the sound editor we're interested in edited or NULL if all editors should be returned.
* @return User|array|null Object representing the user responsible for editing recordings of this NPC in the given quest, an array of all editors if no parameter was supplied or NULL if it wasn't set
*/
public function getSoundEditor(?Quest $quest = null) : User|array|null
{
return is_null($quest) ? ($this->soundEditors ?? null) : ($this->soundEditors[$quest->getId()] ?? null);
}
Comment thread
ShadyMedic marked this conversation as resolved.

public function isArchived() : bool
{
return $this->archived;
Expand Down
70 changes: 61 additions & 9 deletions Models/Website/Quest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ class Quest implements JsonSerializable
private int $id;
private ?string $name = null;
private ?string $degeneratedName = null;
private array $npcs;
private User $scriptAuthor;

private array $npcs;


/**
* @param array $data Data returned from database, invalid items are skipped, multiple key names are supported for
Expand All @@ -32,6 +35,19 @@ public function __construct(array $data)
case 'dname':
case 'degenerated_name':
$this->degeneratedName = $value;
break;
case 'writer':
case 'scriptAuthor':
case 'script_author':
if ($value instanceof User) {
$this->scriptAuthor = $value;
break;
} else if (is_null($value)) {
break;
}
$writer = new User();
$writer->setData(['id' => $value]);
$this->scriptAuthor = $writer;
break;
Comment thread
ShadyMedic marked this conversation as resolved.
}
}
Expand All @@ -53,7 +69,7 @@ public function loadFromDegeneratedName() : bool
}

$result = (new Db('Website/DbInfo.ini'))->fetchQuery('
SELECT quest_id, name
SELECT quest_id, name, writer
FROM quest
WHERE degenerated_name = ?;
', array($this->degeneratedName));
Expand All @@ -63,7 +79,13 @@ public function loadFromDegeneratedName() : bool
}
$this->id = $result['quest_id'];
$this->name = $result['name'];

if (is_null($result['writer'])) {
$this->scriptAuthor = null;
} else {
$writer = new User();
$writer->setData(['id' => $result['writer']]);
$this->scriptAuthor = $writer;
}
return true;
}

Expand Down Expand Up @@ -103,6 +125,15 @@ public function getDegeneratedName() : ?string
return $this->degeneratedName;
}

/**
* Script author getter
* @return User|null User who is the writer of the script for this quest
*/
public function getScriptAuthor() : ?User
{
return isset($this->scriptAuthor) ? $this->scriptAuthor : null;
}

/**
* Npcs getter
* @param bool $loadIfNotLoaded Should the list of NPCs be loaded from the database if it is unset at the time this method is called?
Expand All @@ -119,12 +150,26 @@ public function getNpcs(bool $loadIfNotLoaded = false): ?array
private function loadNpcs() : bool
{
$result = (new Db('Website/DbInfo.ini'))->fetchQuery('
SELECT npc_id,npc.name,degenerated_name,voice_actor_id,user.display_name,user.picture,archived,upvotes,downvotes,(SELECT COUNT(*) FROM comment WHERE npc_id = npc.npc_id) AS comments,sorting_order
SELECT
npc_id,
npc.name,
degenerated_name,
voice_actor_id AS "va_id",
voice_actor.display_name AS "va_name",
voice_actor.picture AS "va_picture",
npc_quest.editor AS "se_id",
sound_editor.display_name AS "se_name",
sound_editor.picture AS "se_picture",
archived,
upvotes,
downvotes,
(SELECT COUNT(*) FROM comment WHERE npc_id = npc.npc_id) AS comments
FROM npc
JOIN npc_quest USING (npc_id)
JOIN user ON user.user_id = npc.voice_actor_id
LEFT JOIN user voice_actor ON voice_actor.user_id = npc.voice_actor_id
LEFT JOIN user sound_editor ON sound_editor.user_id = npc_quest.editor
WHERE quest_id = ?
ORDER BY sorting_order;
ORDER BY npc_quest.sorting_order;
', array($this->id), true);

$this->npcs = [];
Expand All @@ -133,9 +178,16 @@ private function loadNpcs() : bool
}
foreach ($result as $dbRow) {
$npc = new Npc($dbRow);
$va = new User();
$va->setData($dbRow);
$npc->setVoiceActor($va);
if (!is_null($dbRow['va_id'])) {
$va = new User();
$va->setData(['id' => $dbRow['va_id'], 'name' => $dbRow['va_name'], 'avatar' => $dbRow['va_picture']]);
$npc->setVoiceActor($va);
}
if (!is_null($dbRow['se_id'])) {
$se = new User();
$se->setData(['id' => $dbRow['se_id'], 'name' => $dbRow['se_name'], 'avatar' => $dbRow['se_picture']]);
$npc->setSoundEditor($this, $se);
}
$this->npcs[] = $npc;
}
return true;
Expand Down
Loading