COPLAY Launcher 1.0.5 — نسخة الـ VPS (13.62.47.233)

====================================
1) ماذا يوجد في هذا المجلد
====================================
Play.exe                 المشغّل (71 ميجابايت، مكتفٍ ذاتيًا — لا يحتاج اللاعب تنصيب .NET)
Assets/                  خلفية الواجهة وشعار COPLAY
Env_DX8/  Env_DX9/       ملفات العميل الجاهزة (Conquer.exe + Server.dat) لكل طريقة رسم
Hook/                    ConquerCipherHook.dll الذي يفتح متاجر points وأفاتار VIP
Source/                  Program.cs + COPLAY.Launcher.csproj (المصدر، لا يُرفع للاعبين)

لا تشغّل Play.exe وحده خارج المجلد؛ مجلدات Env_ و Hook و Assets مطلوبة بجانبه.
لذلك ما يُرفع للموقع هو ملف COPLAY-Launcher-1.0.5.zip (المجلد كامل مضغوط) ويوضع في:
    C:\AppServ\www\download\COPLAY-Launcher-1.0.5.zip

====================================
2) استخدام اللاعب
====================================
1. يَنسخ نسخة اللعبة الكاملة إلى مجلد ثابت منفصل (مثال D:\Games\COPLAY).
   لا يختَر مجلد المرجع F:\surce6609\6609\Conquer Online 3.0 — المشغّل يرفضه.
2. يَفكّ حزمة المشغّل في مجلد واحد ثم يشغّل Play.exe.
3. يحدّد مسار نسخة اللعبة ثم يضغط CHECK UPDATE.
4. عند اكتمال التحديث يظهر START GAME ويختار Auto (DX9 ثم DX8) أو يدويًا.

====================================
3) ما تغيّر في 1.0.1 حتى 1.0.5
====================================
- قناة التحديث أصبحت حزمًا مضغوطة برقم إصدار اللعبة: 1001.zip ثم 1002.zip …
  والإصدار الأساسي للعبة الآن 1000، والإصدار المطلوب يُقرأ من:
  http://13.62.47.233/patches/manifest.json  (السماح أيضًا لـ https على 443؛ لا 8080 ولا 8443).
- الترتيب صار: قراءة manifest ← تنزيل الحزم وتطبيقها ← ثم تجهيز العميل (CLHook.ini و Server.dat و Hook).
  بهذا أي Hook يصل داخل حزمة تحديث يُعالَج بعد فكّه ولا يبقى بروابط قديمة.
- كل حزمة تُتحقق مرتين: الحجم (size) من الـ manifest ثم بصمة SHA-256. لو اختلفت أي منهما تتوقف العملية.
- التنزيل يتم إلى ملف مؤقت ويُفكّ الضغط منه مباشرة (لا يُحمَّل في الذاكرة)، فلا ينهار مع الحزم الكبيرة.
- فرض التحديث: START GAME لا يظهر قبل أن وصلت النسخة المحلية إلى رقم الـ manifest.
  يرفض المشغّل فكّ الضغط إذا كانت اللعبة عاملة من نفس المجلد — يقفل ثم يطلب إغلاقها.
- معالجة روابط متجر الـ Hook صارت على ثلاث نسخ: ConquerCipherHook.dll في جذر نسخة اللعبة، ثم نسختا
  Env_DX8 و Env_DX9. الرابط الطويل يأخذ عنوان الـ VPS، والرابط القديم القصير يُصفَّر (null) فلا يستخدمه الـ Hook.
- ما تغيّر في 1.0.2: كان المشغّل يكتب 1024x768 في ini\GameSetup.Ini، وصار يكتب دقة سطح المكتب
  الحقيقية (أو المقاس المختار من الترس). القياس بعد ذلك أثبت أن العميل نفسه يُعيد كتابة هذا الملف
  إلى 1024x768 بعد أربع ثوانٍ من تشغيله — لذلك لا شيء مما يُكتب قبل التشغيل يتحكّم في حجم العالم.
- ما تغيّر في 1.0.3 (أول محاولة لزاوية الشاشة، وقد استبدلها 1.0.4): المشغّل يراقب نافذة اللعبة، ويعتبر تغيير عنوان
  نافذة الدخول بعد استقرارها هو لحظة دخول العالم (بدون مطابقة نص ثابت لأن صيغة العنوان تختلف بين
  النسخ)، ثم يوسّع نافذة العالم نفسها إلى كامل سطح المكتب بلا إطار — مع أربع محاولات يتأكد فيها
  من مستطيل النافذة. قياسًا: نافذة الدخول تبقى 1024x768 كما هي، والعالم يصبح 0,0 بمقاس 1920x1080.
  وخط الأرقام تغيّر: Georgia يرسم أرقامًا قديمة متفاوتة الارتفاع (3 و4 و5 و7 و9 تنزل تحت السطر)،
  فصار رقم الإصدار ونسبة التنزيل ومقاسات الشاشة في الترس بخط Segoe UI بأرقام منتظمة، والـ Georgia
  بقي للشعار والنصوص.
- ما تغيّر في 1.0.4 (زاوية الشاشة صار لها محرّك مستمر): الاعتماد على تغيّر العنوان وحده لم يمسك
  الجلسة الحقيقية، فصار المشغّل يعتبر النافذة هي العالم بإشارتين أيًّا منهما تكفي — نفس ما كان يفعله
  Play.exe القديم وزائد عليه الشكل: (1) أي نافذة للكلينت موضوعة على زاوية الشاشة (0,0) ومقاسها ليس
  المقاس المطلوب، (2) أو عنوانها يحمل صيغة العالم ("COPLAY -" أو "Ping:") فتُوسَّع حتى لو كانت في المنتصف.
  نافذة الدخول (1024x768 في وسط الشاشة وعنوانها "COPLAY" بدون شرطة) لا تنطبق عليها أي من الإشارتين
  فتبقى كما هي. المراقبة لا تقف بعد أول إصلاح: تفحص كل 0.7 ثانية كل النوافذ الظاهرة للعملية (لا
  MainWindowHandle وحده) وتعيد التوسيع لو رجّع العميل مقاسه، حتى 24 إصلاحًا. قياسًا: الدخول بقي
  1024x768@448,136، وشريط 1024x20 لم يُمَسّ، والزاوية 1024x768@0,0 صارت 1920x1080@0,0 في نحو ثانيتين
  ثم أعاد العميل تصغيرها فصارت كاملة وحدها مرة أخرى.
- ما تغيّر في 1.0.5 (حارس GameSetup.Ini): القياس بالدقيقة بيّن أن العميل يكتب 1024x768 فوق
  ScrWidth/ScrHeight بعد 4.8 ثانية من بدء العملية، أي قبل ما تظهر نافذته، بينما يترك FullScrType=1
  و ScreenModeRecord=2 كما كتبناهما — وهذا حرفيًا ما ظهر في لقطة الشاشة: الملف محتفظ بالرقمين الذين
  كتبناهما ومرتجعًا في المقاس وحده، والعالم يُبنى من المقاس الموجود في الملف لحظة الدخول. صار المشغّل
  عند START GAME يكتب ريزوليشن سطح المكتب الخاص بالعميل في الملف ويحفظه، وكل 0.7 ثانية يعيده إلى
  المقاس الصحيح إذا وجده العميل خالفه — لكن فقط أثناء شاشة الدخول؛ أما بمجرد وجود نافذة العالم فيكفّ
  المشغّل نهائيًا عن لمس الملف، فلا يضيع أي تغيير للريزوليشن من داخل اللعبة ولا يُعدَّل الملف إلا إذا
  تغيّر ريزوليشن العميل.
- سجلّ جديد باسم display.log في جذر مجلد اللعبة: سطر لكل تغيّر في مقاسات النوافذ وسطر لكل إصلاح فيه
  رقم النافذة والمقاس القديم والجديد والعنوان، وسطر "ini|" لكل مرة رُدّ فيها ScrWidth/ScrHeight إلى
  المقاس الصحيح، وسطر "world|" لحظة تسليم الملف للعميل، ويُدوَّر عند 240 سطرًا. لو ظهرت الزاوية عند أي
  لاعب فملفه هذا وحده يكفي للتشخيص من غير جلسة تحقّق جديدة.

====================================
4) أين يحفظ المشغّل حالة الإصدار
====================================
الإصدار عند اللاعب يُقرأ من ملف version.dat الموجود في جذر مجلد اللعبة نفسه — وهو البوابة الوحيدة:
أي حزمة رقمها أصغر من أو يساوي رقم version.dat تُتخطّى، ويكتب المشغّل الرقم بعد كل حزمة ناجحة،
فإعادة الضغط على CHECK UPDATE تكمّل من مكانها بدل ما تبدأ من الصفر. لو الملف ناقص أو غير مفهوم
يرفض المشغّل التحقق ويقول أن الإصدار لا يمكن قراءته.
إعدادات الواجهة في نفس المجلد: Launcher.ini (طريقة الرسم auto/dx9/dx8) و Resolution.ini (مقاس العالم).
رابط الـ manifest ثابت على 13.62.47.233 ولا يُعدَّل من الواجهة — هذه النسخة للـ VPS فقط.

====================================
5) الاتصال والمنافذ
====================================
عنوان السيرفر 13.62.47.233 — منافذ اللعبة 9960 (توثيق) و 5817 (عالم اللعب).
التحديث وملفات المتجر على المنفذ 80 فقط. لا يستخدم المنفذا 8080 ولا 8443.

====================================
6) النسخ الاحتياطية
====================================
قبل أول استبدال لأي ملف عميل أو Hook أو إعدادات داخل النسخة المنفصلة ينشئ المشغّل نسخة احتياطية
باسم <الملف>.coplay-backup. لا يلمس المشغّل شيئًا داخل مجلد المرجع على F:.

====================================
7) نشر حزمة تحديث جديدة (خطوة المدير)
====================================
استخدم 01_Scripts\COPLAY-Publish.ps1 من هذه الحزمة:
    pwsh -File 01_Scripts\COPLAY-Publish.ps1 -Action Build -Version 1001 -Files @('ConquerCipherHook.dll') -ClientRoot 'D:\Games\COPLAY' -Out 'G:\vps sorce\08_Patches'
يبني 1001.zip بالمسارات النسبية الصحيحة ويسجّل الحجم والبصمة داخل manifest.json ويحدّث
gmpointshop.bin و avatarshop.bin. ثم ارفع 08_Patches إلى C:\AppServ\www\patches في الـ VPS.
للتحقق بعد الرفع:
    pwsh -File 01_Scripts\COPLAY-Publish.ps1 -Action Verify

====================================
8) إعادة بناء المشغّل من المصدر
====================================
المشغّل الذي يُرفع للاعبين يُبنى من مشروع VpsLauncher (وليس من Source):
    dotnet publish "C:\Users\pc\Documents\Codex\2026-11-02\new-chat\outputs\COPLAY_Launcher_Editable_Template\VpsLauncher\COPLAY.VpsLauncher.csproj" `
      -c Release -r win-x86 --self-contained true -p:PublishSingleFile=true `
      -p:EnableCompressionInSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true
الناتج Play.exe ملف واحد 74,582,985 بايت. حذف IncludeNativeLibrariesForSelfExtract يُنتج ملفًا يموت قبل
إظهار أي نافذة بخطأ 0xC0000409 (DllNotFoundException داخل HwndSubclass) — قياسًا على نسخ الضغط معًا،
فلا تُسقِطه من الأمر. علم الضغط يغيّر الحجم فقط (بدونه يصبح الملف نحو 161 ميجابايت).
رفع <Version> في csproj هو ما يغيّر رقم الإصدار المعروض — ولازم يُرفع مع أي تعديل في المشغّل،
لأن بوابة التحديث تتجاهل أي إصدار على السيرفر ليس أكبر من إصدار اللاعب فلا يصلح شيئًا.
