add cache for json profiles of players
This commit is contained in:
parent
9290f1d2a7
commit
1caae0dd75
38
app/Events/GetPlayerJson.php
Normal file
38
app/Events/GetPlayerJson.php
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use App\Models\Player;
|
||||||
|
use App\Events\Event;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||||
|
|
||||||
|
class GetPlayerJson extends Event
|
||||||
|
{
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
public $player;
|
||||||
|
|
||||||
|
public $api_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(Player $player, $api_type)
|
||||||
|
{
|
||||||
|
$this->player = $player;
|
||||||
|
$this->api_type = $api_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the channels the event should be broadcast on.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function broadcastOn()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
34
app/Events/PlayerProfileUpdated.php
Normal file
34
app/Events/PlayerProfileUpdated.php
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use App\Events\Event;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||||
|
|
||||||
|
class PlayerProfileUpdated extends Event
|
||||||
|
{
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
public $player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(\App\Models\Player $player)
|
||||||
|
{
|
||||||
|
$this->player = $player;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the channels the event should be broadcast on.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function broadcastOn()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -79,7 +79,7 @@ class PlayerController extends BaseController
|
||||||
|
|
||||||
public function show()
|
public function show()
|
||||||
{
|
{
|
||||||
echo json_encode($this->player->model->toArray(), JSON_NUMERIC_CHECK);
|
return json_encode($this->player->model->toArray(), JSON_NUMERIC_CHECK);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rename()
|
public function rename()
|
||||||
|
|
@ -121,9 +121,7 @@ class PlayerController extends BaseController
|
||||||
|
|
||||||
$field_name = "tid_".$texture->type;
|
$field_name = "tid_".$texture->type;
|
||||||
|
|
||||||
$this->player->model->$field_name = $tid;
|
$this->player->setTexture([$field_name => $tid]);
|
||||||
$this->player->model->last_modified = Utils::getTimeFormatted();
|
|
||||||
$this->player->model->save();
|
|
||||||
|
|
||||||
View::json('材质已成功应用至角色 '.$this->player->model->player_name.'', 0);
|
View::json('材质已成功应用至角色 '.$this->player->model->player_name.'', 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,21 +20,20 @@ class TextureController extends BaseController
|
||||||
|
|
||||||
public function json($player_name, $api = "")
|
public function json($player_name, $api = "")
|
||||||
{
|
{
|
||||||
// FUCKING CHINESE PLAYER NAME
|
|
||||||
// I DONT WANT TO IMPLEMENT IT AT ALL
|
|
||||||
$player_name = Option::get('allow_chinese_playername') ? $GLOBALS['player_name'] : $player_name;
|
|
||||||
|
|
||||||
$player = new Player(0, $player_name);
|
$player = new Player(0, $player_name);
|
||||||
|
|
||||||
if ($player->is_banned)
|
if ($player->is_banned)
|
||||||
Http::abort(404, '该角色拥有者已被本站封禁。');
|
Http::abort(404, '该角色拥有者已被本站封禁。');
|
||||||
|
|
||||||
if ($api == "csl") {
|
if ($api == "csl") {
|
||||||
echo $player->getJsonProfile(0);
|
return response($player->getJsonProfile(Player::CSL_API))
|
||||||
|
->header('Content-type', 'application/json');
|
||||||
} else if ($api == "usm") {
|
} else if ($api == "usm") {
|
||||||
echo $player->getJsonProfile(1);
|
return response($player->getJsonProfile(Player::USM_API))
|
||||||
|
->header('Content-type', 'application/json');
|
||||||
} else if ($api == "") {
|
} else if ($api == "") {
|
||||||
echo $player->getJsonProfile(Option::get('api_type'));
|
return response($player->getJsonProfile(Option::get('api_type')))
|
||||||
|
->header('Content-type', 'application/json');
|
||||||
} else {
|
} else {
|
||||||
Http::abort(404, '不支持的 API_TYPE。');
|
Http::abort(404, '不支持的 API_TYPE。');
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +41,7 @@ class TextureController extends BaseController
|
||||||
|
|
||||||
public function jsonWithApi($api, $player_name)
|
public function jsonWithApi($api, $player_name)
|
||||||
{
|
{
|
||||||
$this->json($player_name, $api);
|
return $this->json($player_name, $api);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function texture($hash) {
|
public function texture($hash) {
|
||||||
|
|
|
||||||
38
app/Listeners/CachePlayerJson.php
Normal file
38
app/Listeners/CachePlayerJson.php
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use Storage;
|
||||||
|
use App\Events\GetPlayerJson;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
|
||||||
|
class CachePlayerJson
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create the event listener.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*
|
||||||
|
* @param GetPlayerJson $event
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle(GetPlayerJson $event)
|
||||||
|
{
|
||||||
|
$player = $event->player;
|
||||||
|
$api_type = $event->api_type;
|
||||||
|
|
||||||
|
if (!Storage::disk('cache')->has("json/{$player->pid}-{$api_type}")) {
|
||||||
|
Storage::disk('cache')->put("json/{$player->pid}-{$api_type}", $player->generateJsonProfile($api_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
33
app/Listeners/FreshPlayerJson.php
Normal file
33
app/Listeners/FreshPlayerJson.php
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use Storage;
|
||||||
|
use App\Events\PlayerProfileUpdated;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
|
||||||
|
class FreshPlayerJson
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*
|
||||||
|
* @param PlayerProfileUpdated $event
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle(PlayerProfileUpdated $event)
|
||||||
|
{
|
||||||
|
$player = $event->player;
|
||||||
|
|
||||||
|
$files = [
|
||||||
|
"json/{$player->pid}-0",
|
||||||
|
"json/{$player->pid}-1"
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if (Storage::disk('cache')->has($file)) {
|
||||||
|
Storage::disk('cache')->delete($file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,17 +2,23 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Events\PlayerProfileUpdated;
|
||||||
|
use App\Events\GetPlayerJson;
|
||||||
use App\Exceptions\E;
|
use App\Exceptions\E;
|
||||||
|
use Event;
|
||||||
use Utils;
|
use Utils;
|
||||||
|
|
||||||
class Player
|
class Player
|
||||||
{
|
{
|
||||||
public $pid = "";
|
public $pid = "";
|
||||||
public $player_name = "";
|
public $player_name = "";
|
||||||
|
|
||||||
public $is_banned = false;
|
public $is_banned = false;
|
||||||
|
|
||||||
public $model = null;
|
public $model = null;
|
||||||
|
|
||||||
|
const CSL_API = 0;
|
||||||
|
const USM_API = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct player with pid or playername
|
* Construct player with pid or playername
|
||||||
|
|
@ -70,7 +76,10 @@ class Player
|
||||||
$this->model->tid_cape = isset($tids['tid_cape']) ? $tids['tid_cape'] : $this->model['tid_cape'];
|
$this->model->tid_cape = isset($tids['tid_cape']) ? $tids['tid_cape'] : $this->model['tid_cape'];
|
||||||
|
|
||||||
$this->model->last_modified = Utils::getTimeFormatted();
|
$this->model->last_modified = Utils::getTimeFormatted();
|
||||||
return $this->model->save();
|
|
||||||
|
$this->model->save();
|
||||||
|
|
||||||
|
return Event::fire(new PlayerProfileUpdated($this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clearTexture()
|
public function clearTexture()
|
||||||
|
|
@ -104,11 +113,12 @@ class Player
|
||||||
* @param string $type, 'slim' or 'default'
|
* @param string $type, 'slim' or 'default'
|
||||||
*/
|
*/
|
||||||
public function setPreference($type) {
|
public function setPreference($type) {
|
||||||
|
$this->model->update([
|
||||||
return $this->model->update([
|
|
||||||
'preference' => $type,
|
'preference' => $type,
|
||||||
'last_modified' => Utils::getTimeFormatted()
|
'last_modified' => Utils::getTimeFormatted()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
return Event::fire(new PlayerProfileUpdated($this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPreference() {
|
public function getPreference() {
|
||||||
|
|
@ -116,42 +126,55 @@ class Player
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setOwner($uid) {
|
public function setOwner($uid) {
|
||||||
return $this->model->update(['uid' => $uid]);
|
$this->model->update(['uid' => $uid]);
|
||||||
|
|
||||||
|
return Event::fire(new PlayerProfileUpdated($this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get JSON profile
|
* Get JSON profile
|
||||||
* @param int $api_type, which API to use, 0 for CustomSkinAPI, 1 for UniSkinAPI
|
*
|
||||||
* @return string, user profile in json format
|
* @param int $api_type Which API to use, 0 for CustomSkinAPI, 1 for UniSkinAPI
|
||||||
|
* @return string User profile in json format
|
||||||
*/
|
*/
|
||||||
public function getJsonProfile($api_type) {
|
public function getJsonProfile($api_type) {
|
||||||
header('Content-type: application/json');
|
Event::fire(new GetPlayerJson($this, $api_type));
|
||||||
|
|
||||||
// Support both CustomSkinLoader API & UniSkinAPI
|
// Support both CustomSkinLoader API & UniSkinAPI
|
||||||
if ($api_type == 0 || $api_type == 1) {
|
if ($api_type == self::CSL_API || $api_type == self::USM_API) {
|
||||||
$json[($api_type == 0) ? 'username' : 'player_name'] = $this->player_name;
|
return \Storage::disk('cache')->get("json/{$this->pid}-{$api_type}");
|
||||||
$model = $this->getPreference();
|
|
||||||
$sec_model = ($model == 'default') ? 'slim' : 'default';
|
|
||||||
if ($api_type == 1) {
|
|
||||||
$json['last_update'] = $this->getLastModified();
|
|
||||||
$json['model_preference'] = [$model, $sec_model];
|
|
||||||
}
|
|
||||||
if ($this->getTexture('steve') || $this->getTexture('alex')) {
|
|
||||||
// Skins dict order by preference model
|
|
||||||
$json['skins'][$model] = $this->getTexture($model == "default" ? "steve" : "alex");
|
|
||||||
$json['skins'][$sec_model] = $this->getTexture($sec_model == "default" ? "steve" : "alex");
|
|
||||||
}
|
|
||||||
$json['cape'] = $this->getTexture('cape');
|
|
||||||
} else {
|
} else {
|
||||||
throw new E('不支持的 API_TYPE。', -1, true);
|
throw new E('不支持的 API_TYPE。', -1, true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateJsonProfile($api_type)
|
||||||
|
{
|
||||||
|
$json[($api_type == self::CSL_API) ? 'username' : 'player_name'] = $this->player_name;
|
||||||
|
|
||||||
|
$model = $this->getPreference();
|
||||||
|
$sec_model = ($model == 'default') ? 'slim' : 'default';
|
||||||
|
|
||||||
|
if ($api_type == self::USM_API) {
|
||||||
|
$json['last_update'] = $this->getLastModified();
|
||||||
|
$json['model_preference'] = [$model, $sec_model];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->getTexture('steve') || $this->getTexture('alex')) {
|
||||||
|
// Skins dict order by preference model
|
||||||
|
$json['skins'][$model] = $this->getTexture($model == "default" ? "steve" : "alex");
|
||||||
|
$json['skins'][$sec_model] = $this->getTexture($sec_model == "default" ? "steve" : "alex");
|
||||||
|
}
|
||||||
|
|
||||||
|
$json['cape'] = $this->getTexture('cape');
|
||||||
|
|
||||||
return json_encode($json, JSON_PRETTY_PRINT);
|
return json_encode($json, JSON_PRETTY_PRINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateLastModified() {
|
public function updateLastModified() {
|
||||||
// @see http://stackoverflow.com/questions/2215354/php-date-format-when-inserting-into-datetime-in-mysql
|
// @see http://stackoverflow.com/questions/2215354/php-date-format-when-inserting-into-datetime-in-mysql
|
||||||
return $this->model->update(['last_modified' => Utils::getTimeFormatted()]);
|
$this->model->update(['last_modified' => Utils::getTimeFormatted()]);
|
||||||
|
return Event::fire(new PlayerProfileUpdated($this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,12 @@ class EventServiceProvider extends ServiceProvider
|
||||||
'App\Events\GetAvatarPreview' => [
|
'App\Events\GetAvatarPreview' => [
|
||||||
'App\Listeners\CacheAvatarPreview',
|
'App\Listeners\CacheAvatarPreview',
|
||||||
],
|
],
|
||||||
|
'App\Events\GetPlayerJson' => [
|
||||||
|
'App\Listeners\CachePlayerJson',
|
||||||
|
],
|
||||||
|
'App\Events\PlayerProfileUpdated' => [
|
||||||
|
'App\Listeners\FreshPlayerJson',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
3
storage/cache/json/.gitignore
vendored
Normal file
3
storage/cache/json/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
*
|
||||||
|
!public/
|
||||||
|
!.gitignore
|
||||||
Loading…
Reference in New Issue
Block a user