Răsfoiți Sursa

feat: add API endpoint to send items via in-game mail (изменения/добавления от Vieraw)

ilg2005 3 luni în urmă
părinte
comite
94fa9670b2
2 a modificat fișierele cu 213 adăugiri și 0 ștergeri
  1. 212 0
      app/Http/Controllers/CharController.php
  2. 1 0
      routes/api.php

+ 212 - 0
app/Http/Controllers/CharController.php

@@ -9,7 +9,9 @@ use App\Models\Char\CharItem;
 use App\Models\Char\CharFellow;
 use App\Models\Char\CharQuest;
 use App\Models\Char\CharMail;
+use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Validator;
 use App\Models\Char\CharQuest_History;
 
 class CharController extends Controller
@@ -588,4 +590,214 @@ class CharController extends Controller
             'data' => $model->fresh()
         ], 200);
     }
+	
+	public function SendItemViaMail(Request $request)
+    {
+        $validator = Validator::make($request->all(), [
+            'ReceiverID' => 'required|integer|exists:Char.dbo.Table_CharBase,DBKey',
+			'StorageID'   => 'sometimes|integer|exists:Char.dbo.Table_CharBase,DBKey',
+            'RecId'      => 'required|string|max:20',
+            'Amount'     => 'required|integer|min:1|max:9999',
+            'Title'      => 'sometimes|string|nullable|max:33',
+            'Letter'     => 'sometimes|string|nullable|max:512',
+            'Money'      => 'sometimes|integer|min:0',
+        ]);
+
+        if ($validator->fails()) {
+            return response()->json(['code' => -1, 'msg' => $validator->errors()], 400);
+        }
+
+        try {
+            return DB::connection('Char')->transaction(function () use ($request) {
+                
+                $receiverId = $request->input('ReceiverID');
+				$storageId = $request->input('StorageID', $receiverId);
+
+                $receiver = CharBase::where('DBKey', $receiverId)->lockForUpdate()->first();
+
+                if (!$receiver) {
+                    return response()->json(['code' => -2, 'msg' => 'Character not found.'], 404);
+                }
+
+                $recycledMail = CharMail::where('RecverDBKey', $receiver->DBKey)
+                                        ->where('Deleted', 1)
+                                        ->orderBy('Slot')
+                                        ->lockForUpdate()
+                                        ->first();
+
+                $isRecycled = false;
+                if ($recycledMail) {
+                    $nextMailSlot = $recycledMail->Slot;
+                    $mailDBKey = $recycledMail->MailDBKey;
+                    $isRecycled = true;
+                } else {
+                    $maxMailSlot = CharMail::where('RecverDBKey', $receiver->DBKey)
+                                           ->lockForUpdate()
+                                           ->max('Slot');
+                    $nextMailSlot = ($maxMailSlot !== null) ? $maxMailSlot + 1 : 0;
+                    $mailDBKey = null;
+                }
+
+                $itemCount = 1;
+                $itemSlots = [-1, -1, -1, -1, -1];
+                $itemsData = [];
+
+                $maxMailItemSlot = CharItem::where('Owner', $receiver->DBKey)
+                                           ->where('StrRecordKind', 'ml')
+                                           ->lockForUpdate()
+                                           ->max('Slot');
+                $nextItemSlot = ($maxMailItemSlot !== null) ? $maxMailItemSlot + 1 : 0;
+
+				$storage = CharBase::where('DBKey', $storageId)->lockForUpdate()->first();
+				
+				if (!$storage) {
+					return response()->json(['code' => -2, 'msg' => 'Storage character not found.'], 404);
+				}
+
+                for ($i = 0; $i < $itemCount; $i++) {
+                    $storage->ItemSerialOrder += 1;
+                    
+                    $itemSerial = ($storage->ItemSerialOrder * 4294967296) + $storage->DBKey;
+
+                    $itemSlots[$i] = $nextItemSlot;
+
+                    $itemsData[] = array_merge([
+                        "Owner" => $receiver->DBKey,
+                        "Slot" => $nextItemSlot,
+                        "ItemSerial" => $itemSerial,
+                        "KeyValueA" => $itemSerial,
+                        "StrRecordKind" => "ml",
+                        "Account" => 0,
+                        "RecId" => $request->input('RecId'),
+                        "Amount" => $request->input('Amount'),
+                        "ClientSlot" => -1,
+                        "Storage" => "in",
+                        "ItemGrade" => "normal",
+                        "Durability" => 100,
+                        "MailDbKey" => null,
+                        "Deleted" => 0,
+                    ], $request->input('item_overrides', []));
+
+                    $nextItemSlot++;
+                }
+                
+                $storage->save();
+
+                $titleText = $request->input('Title', 'Системное сообщение');
+                $letterText = $request->input('Letter', 'Вам прислан подарок.');
+                $money = $request->input('Money', 0);
+
+                if ($isRecycled) {
+                    $recycledMail->fill([
+                        'Deleted' => 0,
+                        'bRead' => 0,
+                        'MailType' => 'es',
+                        'SentMailDBKey' => 0,
+                        'SenderDBKeyAccount' => -2,
+                        'SenderDBKey' => -2,
+                        'SendName' => 'GM',
+                        'RecvName' => $receiver->Name,
+                        'Title' => $titleText,
+                        'Letter' => $letterText,
+                        'binTitle' => $titleText,
+                        'binLetter' => $letterText,
+                        'CreateDate' => now(),
+                        'ReadDate' => now(),
+                        'Money' => $money,
+                        'AlreadyMoney' => 0,
+                        'ItemCount' => $itemCount,
+                        'ItemSlot0' => -1,
+                        'ItemSlot1' => -1,
+                        'ItemSlot2' => -1,
+                        'ItemSlot3' => -1,
+                        'ItemSlot4' => -1,
+                        'AlreadyItem0' => 0,
+                        'AlreadyItem1' => 0,
+                        'AlreadyItem2' => 0,
+                        'AlreadyItem3' => 0,
+                        'AlreadyItem4' => 0,
+                        'Confirm' => 1,
+                    ]);
+                    $recycledMail->save();
+
+                    CharItem::where('Owner', $receiver->DBKey)
+                            ->where('MailDbKey', $mailDBKey)
+                            ->where('StrRecordKind', 'ml')
+                            ->update([
+                                'Deleted' => 1,
+                                'RecId' => '*',
+                                'ItemSerial' => 0,
+                            ]);
+
+                } else {
+                    $mailData = [
+                        "RecverDBKey" => $receiver->DBKey,
+                        "RecvName" => $receiver->Name,
+                        "Slot" => $nextMailSlot,
+                        "MailType" => "es",
+                        "SentMailDBKey" => 0,
+                        "SenderDBKeyAccount" => -2,
+                        "SenderDBKey" => -2,
+                        "SendName" => "GM",
+                        "ItemCount" => $itemCount,
+                        "ItemSlot0" => -1,
+                        "ItemSlot1" => -1,
+                        "ItemSlot2" => -1,
+                        "ItemSlot3" => -1,
+                        "ItemSlot4" => -1,
+                        "AlreadyItem0" => 0,
+                        "AlreadyItem1" => 0,
+                        "AlreadyItem2" => 0,
+                        "AlreadyItem3" => 0,
+                        "AlreadyItem4" => 0,
+                        "Confirm" => 1,
+                        "Title" => $titleText,
+                        "Letter" => $letterText,
+                        "binTitle" => $titleText,
+                        "binLetter" => $letterText,
+                        "Money" => $money,
+                        "AlreadyMoney" => 0,
+                        "CreateDate" => now(),
+                        "ReadDate" => now(),
+                        "Deleted" => 0,
+                    ];
+
+                    $mail = CharMail::create($mailData);
+                    $mailDBKey = $mail->MailDBKey;
+                }
+
+                foreach ($itemsData as $itemData) {
+                    $itemData['MailDbKey'] = $mailDBKey;
+                    CharItem::create($itemData);
+                }
+
+                if ($itemCount >= 1) {
+                    $mailUpdateData = [];
+                    for ($i = 0; $i < 5; $i++) {
+                        $mailUpdateData["ItemSlot{$i}"] = $itemSlots[$i] ?? -1;
+                    }
+                    
+                    CharMail::where('MailDBKey', $mailDBKey)->update($mailUpdateData);
+                }
+
+                return response()->json([
+                    'code' => 0,
+                    'msg' => 'Item sent successfully.',
+                    'data' => [
+                        'MailDBKey' => $mailDBKey,
+                        'ItemSerial' => (string)$itemsData[0]['ItemSerial'],
+                        'MailSlot' => $nextMailSlot,
+                        'ItemSlot' => $itemSlots[0],
+                        'IsRecycled' => $isRecycled,
+                    ]
+                ], 200);
+            });
+        } catch (\Throwable $e) {
+            Log::error('SendItemViaMail Error: ' . $e->getMessage(), [
+                'trace' => $e->getTraceAsString(),
+                'ReceiverID' => $request->input('ReceiverID'),
+            ]);
+            return response()->json(['code' => -3, 'msg' => 'Error: ' . $e->getMessage()], 500);
+        }
+    }
 }

+ 1 - 0
routes/api.php

@@ -49,6 +49,7 @@ Route::group(['prefix' => 'api'], function () {
     // Получение и обновление письма по char_id и MailDBKey
     Route::get('GetCharMail/{char_id}/{mail_id}', 'CharController@GetCharMail');
     Route::post('UpdateCharMail/{char_id}/{mail_id}', 'CharController@UpdateCharMail');
+    Route::post('SendItemViaMail', 'CharController@SendItemViaMail');
     
     Route::group(['prefix' => 'funcs_adm'], function () {
         Route::get('UpdateCharItemAccount/{CharID?}', 'ADMIN\AdminController@UpdateCharItemAccount');