GenerateChestJsonCommand.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <?php
  2. namespace App\Module\GameItems\Commands;
  3. use App\Module\Game\DCache\ChestJsonConfig;
  4. use App\Module\Game\DCache\ItemJsonConfig;
  5. use App\Module\GameItems\Enums\CHEST_COST_TYPE;
  6. use App\Module\GameItems\Enums\ITEM_TYPE;
  7. use Illuminate\Console\Command;
  8. use App\Module\GameItems\Models\Item;
  9. use Illuminate\Support\Facades\File;
  10. use Illuminate\Support\Facades\Log;
  11. /**
  12. * 生成宝箱JSON数据命令
  13. *
  14. * 该命令用于从数据库中的宝箱相关表生成宝箱JSON数据文件,供客户端使用。
  15. * 生成的JSON文件包含宝箱的基本信息和内容配置,如宝箱ID、可能获得的物品及其概率等。
  16. * 该命令通常在宝箱配置更新后运行,以确保客户端获取最新的宝箱数据。
  17. */
  18. class GenerateChestJsonCommand extends Command
  19. {
  20. /**
  21. * 命令名称和签名
  22. *
  23. * @var string
  24. */
  25. protected $signature = 'gameitems:generate-chest-json';
  26. /**
  27. * 命令描述
  28. *
  29. * @var string
  30. */
  31. protected $description = 'Generate chest.json from Item-chest table';
  32. /**
  33. * 执行命令
  34. */
  35. /**
  36. * 生成宝箱JSON数据
  37. *
  38. * @param bool $saveToFile 是否保存到文件
  39. * @return array|bool 生成的数据或失败标志
  40. */
  41. public static function generateJson(bool $saveToFile = true)
  42. {
  43. try {
  44. // 查询Item表中的宝箱数据
  45. $chests = Item::query()
  46. ->where('type', ITEM_TYPE::CHEST)
  47. ->with([
  48. 'chest_contents' => function ($query) {
  49. $query->select([
  50. 'id', 'chest_id', 'item_id', 'group_id',
  51. 'min_quantity', 'max_quantity', 'weight'
  52. ])
  53. ->where('weight', '>', 0)
  54. ->with([
  55. 'item' => function ($query) {
  56. $query->select(['id', 'name']);
  57. },
  58. 'group' => function ($query) {
  59. $query->select(['id', 'name']);
  60. }
  61. ]);
  62. },
  63. 'chest_costs' => function ($query) {
  64. $query->select([
  65. 'id', 'chest_id', 'cost_type', 'cost_id', 'cost_quantity'
  66. ])
  67. ->where('is_active', true)
  68. ->with([
  69. 'costItem' => function ($query) {
  70. $query->select(['id', 'name']);
  71. }
  72. ]);
  73. }
  74. ])
  75. ->select(['id', 'name', 'item_id','numeric_attributes'])
  76. ->get();
  77. // 处理数据,去除不必要的字段
  78. $processedChests = $chests->map(function ($chest) {
  79. $chestData = [
  80. 'id' => $chest->id,
  81. 'name' => $chest->name,
  82. ];
  83. // 添加宝箱数值属性中的必要字段
  84. if (!empty($chest->numeric_attributes)) {
  85. $numericAttrs = $chest->numeric_attributes;
  86. if (isset($numericAttrs->min_drop_count)) {
  87. $chestData['min_drop_count'] = $numericAttrs->min_drop_count;
  88. }
  89. if (isset($numericAttrs->max_drop_count)) {
  90. $chestData['max_drop_count'] = $numericAttrs->max_drop_count;
  91. }
  92. }
  93. // 处理宝箱内容
  94. $chestData['contents'] = $chest->chest_contents->map(function ($content) {
  95. $contentData = [
  96. 'id' => $content->id,
  97. 'weight' => $content->weight,
  98. 'min_quantity' => $content->min_quantity,
  99. 'max_quantity' => $content->max_quantity,
  100. ];
  101. // 根据是物品还是物品组添加不同的字段
  102. if ($content->item_id && $content->item) {
  103. $contentData['item_id'] = $content->item_id;
  104. $contentData['item_name'] = $content->item->name;
  105. $contentData['type'] = 'item';
  106. } elseif ($content->group_id && $content->group) {
  107. $contentData['group_id'] = $content->group_id;
  108. $contentData['group_name'] = $content->group->name;
  109. $contentData['type'] = 'group';
  110. }
  111. return $contentData;
  112. })->toArray();
  113. // 处理宝箱开启消耗
  114. $chestData['costs'] = $chest->chest_costs->map(function ($cost) {
  115. $costData = [
  116. 'cost_type' => $cost->cost_type,
  117. 'cost_id' => $cost->cost_id,
  118. 'cost_quantity' => $cost->cost_quantity,
  119. ];
  120. // 如果是物品消耗,添加物品名称
  121. if ($cost->cost_type == CHEST_COST_TYPE::ITEM->value && $cost->costItem) {
  122. $costData['item_name'] = $cost->costItem->name;
  123. }
  124. return $costData;
  125. })->toArray();
  126. return $chestData;
  127. })->toArray();
  128. // 准备完整数据,包含生成时间
  129. $data = [
  130. 'generated_at' => now()->toDateTimeString(),
  131. 'chests' => $processedChests
  132. ];
  133. // 如果需要保存到文件
  134. if ($saveToFile) {
  135. self::saveJsonToFile($data);
  136. }
  137. return $data;
  138. } catch (\Exception $e) {
  139. // 不使用Log,直接输出到控制台
  140. echo 'Generate chest.json failed: ' . $e->getMessage() . "\n";
  141. echo $e->getTraceAsString() . "\n";
  142. return false;
  143. }
  144. }
  145. /**
  146. * 将JSON数据保存到文件
  147. *
  148. * @param array $data 要保存的数据
  149. * @return bool 是否保存成功
  150. */
  151. protected static function saveJsonToFile(array $data): bool
  152. {
  153. try {
  154. // 确保目录存在
  155. $directory = 'public/json';
  156. if (!File::exists($directory)) {
  157. File::makeDirectory($directory, 0755, true);
  158. }
  159. // 将数据保存为JSON文件
  160. $jsonContent = json_encode($data, JSON_UNESCAPED_UNICODE);
  161. $filePath = $directory . '/chest.json';
  162. File::put($filePath, $jsonContent);
  163. // 同时生成一个格式化的版本供开发者查看
  164. $prettyJsonContent = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
  165. $prettyFilePath = $directory . '/chest_pretty.json';
  166. File::put($prettyFilePath, $prettyJsonContent);
  167. // 不使用Log,直接输出到控制台
  168. echo 'Chest JSON files saved to: ' . $filePath . ' and ' . $prettyFilePath . "\n";
  169. return true;
  170. } catch (\Exception $e) {
  171. // 不使用Log,直接输出到控制台
  172. echo 'Save chest.json to file failed: ' . $e->getMessage() . "\n";
  173. echo $e->getTraceAsString() . "\n";
  174. return false;
  175. }
  176. }
  177. /**
  178. * 执行命令
  179. *
  180. * @return int
  181. */
  182. public function handle()
  183. {
  184. $this->info('Generating chest JSON data...');
  185. $result = ChestJsonConfig::getData([], true);
  186. if ($result && isset($result['chests'])) {
  187. $chestCount = count($result['chests']);
  188. $contentCount = 0;
  189. $costCount = 0;
  190. foreach ($result['chests'] as $chest) {
  191. $contentCount += count($chest['contents'] ?? []);
  192. $costCount += count($chest['costs'] ?? []);
  193. }
  194. $this->info('Successfully generated chest.json with timestamp');
  195. $this->info("Processed {$chestCount} chests with {$contentCount} content items and {$costCount} cost items");
  196. $this->info('JSON files saved to:');
  197. $this->info('- public/json/chest.json (compact version)');
  198. $this->info('- public/json/chest_pretty.json (formatted version for development)');
  199. return 0; // 成功
  200. } else {
  201. $this->error('Failed to generate chest.json');
  202. return 1; // 失败
  203. }
  204. }
  205. }