Deathgarden_Rebirth-Rewrite/dist/app/Http/Controllers/Api/Player/PlayerController.php

265 lines
9.8 KiB
PHP

<?php
namespace App\Http\Controllers\Api\Player;
use App\Classes\Config\SpecialUnlocksItemsConfig;
use App\Enums\Auth\Permissions;
use App\Enums\Game\RewardType;
use App\Helper\Uuid\UuidHelper;
use App\Http\Controllers\Controller;
use App\Http\Requests\Api\Player\GetInventoryRequest;
use App\Http\Requests\Api\Player\ResetCharacterProgressionForPrestigeRequest;
use App\Http\Requests\Api\Player\UnlockSpecialitemsRequest;
use App\Http\Responses\Api\General\Reward;
use App\Http\Responses\Api\Player\GetBanStatusResponse;
use App\Http\Responses\Api\Player\GetQuitterStateResponse;
use App\Http\Responses\Api\Player\ResetCharacterProgressionForPrestigeResponse;
use App\Models\Game\CatalogItem;
use App\Models\Game\Challenge;
use App\Models\Game\CharacterData;
use App\Models\Game\PickedChallenge;
use App\Models\Game\PrestigeReward;
use App\Models\Game\QuitterState;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\UniqueConstraintViolationException;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Ramsey\Uuid\Uuid;
class PlayerController extends Controller
{
public function getBanStatus()
{
$user = Auth::user();
$banCheckQuery = $user->bans()
->where('start_date', '<', Carbon::now()->toDateTimeString())
->where('end_date', '>', Carbon::now()->toDateTimeString());
if (!$banCheckQuery->exists())
return json_encode(new GetBanStatusResponse(false));
return json_encode(new GetBanStatusResponse(true, $banCheckQuery->first()));
}
public function getInventory(GetInventoryRequest $request)
{
$user = Auth::user();
$playerData = $user->playerData();
$inventoryItems = $playerData->inventory;
$inventoryData = [];
foreach ($inventoryItems as $item) {
$inventoryData[] = [
'quantity' => 1,
'objectId' => Uuid::fromString($item->id)->getHex()->toString(),
'lastUpdateAt' => $item->pivot->updated_at->getTimestamp(),
];
}
$response = [
'code' => 200,
'message' => 'OK',
'data' => [
'playerId' => $user->id,
'inventory' => $inventoryData,
],
];
return json_encode($response);
}
public function unlockSpecialItems(UnlockSpecialitemsRequest $request)
{
if(count($request->appIds) === 0)
return ['unlockedItems' => []];
$user = Auth::user();
$itemsToCheck = [];
foreach ($request->appIds as $appid) {
$itemsToCheck = [...$itemsToCheck, ...SpecialUnlocksItemsConfig::getFromAppId($appid)];
}
if($user->playerData()->has_played_dg_1)
$itemsToCheck = [...$itemsToCheck, ...SpecialUnlocksItemsConfig::LEGACY, ...SpecialUnlocksItemsConfig::BETA];
$itemsToCheck = UuidHelper::convertFromHexToUuidCollecton($itemsToCheck, true);
$foundItems = $user->playerData()->inventory()->allRelatedIds()->intersect($itemsToCheck);
if($foundItems->count() === count($itemsToCheck))
return ['unlockedItems' => []];
$itemsToAdd = $itemsToCheck->diff($foundItems);
$user->playerData()->inventory()->syncWithoutDetaching($itemsToAdd);
return json_encode(['unlockedItems' => UuidHelper::convertFromUuidToHexCollection($itemsToAdd)]);
}
public function getQuitterState()
{
$quitterState = Auth::user()->playerData()->quitterState;
$quitterState->checkStrikeRefresh();
$response = new GetQuitterStateResponse(
$quitterState->strike_refresh_time === null ? 0 : Carbon::parse($quitterState->strike_refresh_time)->getTimestamp(),
$quitterState->strikes_left,
$quitterState->stay_match_streak,
$quitterState->stay_match_streak_previous,
$quitterState->has_quit_once,
$quitterState->quit_match_streak,
$quitterState->quit_match_streak_previous,
);
$response->stayMatchStreakRewards = QuitterState::getReward($quitterState->stay_match_streak);
return json_encode($response);
}
public function resetCharacterProgressionForPrestige(ResetCharacterProgressionForPrestigeRequest $request)
{
$user = Auth::user();
$playerData = $user->playerData();
$characterData = $playerData->characterDataForCharacter($request->character);
$characterCatalogItem = CatalogItem::find(Uuid::fromString($request->characterCatalogId)->toString());
if(!$this->checkPrestigePrerequisites($characterData, $characterCatalogItem))
return json_encode(ResetCharacterProgressionForPrestigeResponse::createAbortResponse($characterData->prestige_level));
$this->resetCharacter($characterData);
/** @var PrestigeReward $prestigeReward */
$prestigeReward = $characterCatalogItem->prestigeRewards[$characterData->prestige_level];
$playerData->currency_a -= $prestigeReward->cost_currency_a;
$playerData->currency_b -= $prestigeReward->cost_currency_b;
$playerData->currency_c -= $prestigeReward->cost_currency_c;
$rewardIdsToAdd = [];
$responseRewards = [];
foreach ($prestigeReward->rewardItems as $rewardItem) {
$rewardIdsToAdd[] = $rewardItem->catalog_item_id;
$responseRewards[] = new Reward(
RewardType::Inventory,
1,
$rewardItem->catalog_item_id,
);
}
try {
$playerData->inventory()->attach($rewardIdsToAdd);
}
catch (UniqueConstraintViolationException $e) {}
++$characterData->prestige_level;
$playerData->save();
$characterData->save();
$response = new ResetCharacterProgressionForPrestigeResponse();
$response->prestigelevel = $characterData->prestige_level;
$response->rewards = $responseRewards;
return json_encode($response);
}
protected function resetCharacter(CharacterData &$characterData): void
{
$config = $characterData->character->getCharacter()->getItemConfigClass();
$allItemsToRemove = CatalogItem::find(UuidHelper::convertFromHexToUuidCollecton($config::getAllItems(), true));
$defaultItems = UuidHelper::convertFromHexToUuidCollecton([
...$config::getDefaultEquipment(),
...$config::getDefaultEquippedPerks(),
...$config::getDefaultPowers(),
...$config::getDefaultEquippedWeapons(),
...$config::getDefaultWeapons(),
...$config::getDefaultEquippedBonuses(),
], true);
$inventory = $characterData->playerData->inventory();
// first detach all character items
$inventory->detach($allItemsToRemove);
//then attach the defaults again
$inventory->syncWithoutDetaching([...$defaultItems, $config::getCharacterId()->toString()]);
// Remove signature challenges
foreach ($allItemsToRemove as $item) {
/** @var Challenge[]|Collection $challenges */
$challenges = $item->requiredChallenges;
foreach ($challenges as $challenge){
$challenge->playerData()->detach($characterData->playerData->id);
}
}
// Remove all picked Challenges
$characterData->pickedChallenges->each(function (PickedChallenge $challenge) {
$challenge->delete();
});
// reset experience and level
$characterData->experience = 0;
$characterData->level = 1;
}
/**
* Checks if the player has the required items in his inventory (Lv. 10) and if he has enough currency
*
* @param CharacterData $characterData
* @param CatalogItem $characterItem
* @return bool Whether the player is allowed to prestige the character or not
*/
protected function checkPrestigePrerequisites(CharacterData $characterData, CatalogItem $characterItem): bool
{
$log = Log::channel('prestige_debug');
$log->info("Checking Requirements for {$characterData->playerData->user_id}");
if($characterData->prestige_level >= 4) {
$log->warning('Prestige forbidden, already at max prestige');
return false;
}
$config = $characterData->character->getCharacter()->getItemConfigClass();
$allCharacterItems = CatalogItem::find(UuidHelper::convertFromHexToUuidCollecton($config::getAllItems(), true));
// Because prestige should only be possible if you have all lvl 10 items for the character,
// we check if all of these level 10 items are in our inventory.
/** @var CatalogItem[]|Collection $itemsToCheck */
$itemsToCheck = $allCharacterItems->filter(function (CatalogItem $item) {
return Str::contains($item->display_name, '_010_');
});
$missingItem = false;
foreach ($itemsToCheck as $item) {
if ($characterData->playerData->inventory()->find($item->id) === null) {
$log->warning("User still needs to unlock item $item->display_name");
$missingItem = true;
}
}
if($missingItem)
return false;
$playerData = $characterData->playerData;
$prestigeReward = $characterItem->prestigeRewards[$characterData->prestige_level];
// Check if we can afford the prestige, if not return false;
if( $playerData->currency_a < $prestigeReward->cost_currency_a ||
$playerData->currency_b < $prestigeReward->cost_currency_b ||
$playerData->currency_c < $prestigeReward->cost_currency_c)
{
$log->warning("user doesn't have enough currency");
return false;
}
return true;
}
}