العودة إلى المشاريع

إعادة بناء Lilies بلغة Java

Lilies خادم Minecraft قائم على المصانع ونظام المكانة. كُتبت النسخة الأولى بلغة Skript ووصلت إلى 90 لاعبا متصلا في آن واحد. من أجل الموسم الأول، أقوم بنقل كل نظام إلى مجموعة إضافات Java معيارية، ميزة تلو الأخرى.

الدور
المالك والمطور الوحيد
التقنيات المستخدمة
Java 21, Paper 1.21.11, Gradle, SQLite, PacketEvents
الحالة
الموسم الأول قيد التطوير
قائمة تبويب Lilies تُظهر 90 لاعبا متصلا

لماذا أعيد كتابة شيء كان يعمل

سمحت لي Skript بالإطلاق بسرعة. وبنهاية الموسم الأول كان الخادم يعمل على نحو 57 ملف سكربت، أي نحو 816 كيلوبايت من الشيفرة، واستوعب 90 لاعبا في آن واحد. لكنها كانت تحمل قيودا لم أستطع إصلاحها من داخل Skript: لا أنواع بيانات حقيقية، ولا اختبارات، ومتغيرات عامة مشتركة لكل شيء، وكل نظام يتدخل في كل نظام آخر.

قبل نقل أي شيء، دققت الشيفرة القديمة سطرا سطرا. وبلغ السجل 1,038 صفا. وكان أسوأ ما وُجد هو أن الناقل يدفع من حلقتين منفصلتين، بحيث كان بعض اللاعبين يكسبون نحو عشرة أضعاف ما كان الاقتصاد متوازنا من أجله. وكانت هناك أيضا حالات تكرار عناصر. وأصبح كل صف إما إصلاحا في الشيفرة الجديدة أو اختبارا يثبت أن الخلل لن يعود.

شكل النظام

البناء الجديد إضافة أساسية واحدة وملف jar لكل ميزة. تملك الإضافة الأساسية ما تحتاجه كل ميزة، وكل ميزة إضافة صغيرة مستقلة يمكن بناؤها واختبارها وإيقافها بمفردها.

يحمّل خادم Paper الإضافة LiliesCore، التي تحمّل ملف jar لكل ميزة خادم PaperMinecraft 1.21.11 LiliesCoreالمُحمِّل، البيانات، الإعدادات ملفات jar الاقتصاديةالمولدات، الناقلات، الأفران ملفات jar الاجتماعيةالعصابات، التبادل التجاري، الصناديق ملف jar الفعاليات14 لعبة مصغرة
  • تحتوي lilies-api على الواجهات فقط. وتتواصل الميزات فيما بينها عبر ServicesManager الخاص بـ Bukkit استنادا إلى تلك الواجهات، لا بالتدخل في شيفرة بعضها البعض.
  • يجد LiliesCore ملفات jar في مجلد الميزات الخاص به ويحمّلها عبر مدير الإضافات الخاص بـ Paper، بترتيب الاعتماديات.
  • تضم ملفات jar للميزات نحو 30 وحدة في المجموع. وتأتي كل واحدة بإعداداتها ورسائلها وعناصرها وقوائمها الخاصة.

كل شيء ملف إعدادات

تعيش الأسعار، ومعدلات الإسقاط، وتخطيطات القوائم، وكل سطر نص في الدردشة داخل ملفات YAML، مجلد واحد لكل وحدة. ويمكن لفريق الإدارة تشغيل /lilies reload لكل شيء أو لوحدة واحدة، وتُفحص القيم الجديدة قبل أن تحل محل القديمة، بحيث يترك أي خطأ إملائي الإعدادات الحالية كما هي. ويمكن تغيير القيم الصغيرة داخل اللعبة عبر /lilies set دون فتح أي ملف.

سريع حتى مع خادم ممتلئ

  • SQLite بوضع WAL مع خيط كتابة غير متزامن واحد، بحيث لا ينتظر خيط اللعبة الرئيسي القرص أبدا. وتُخزَّن ملفات تعريف اللاعبين مؤقتا في الذاكرة.
  • الهولوغرامات والعناصر المتحركة عروض تعتمد على الحزم فقط يحسبها العميل بالاستيفاء، بدل كائنات تُنقَل آنيا في كل تِك.
  • مجدوِل واحد مشترك يعمل كل ثانية بدل مؤقت لكل نظام.

اختبار حِمل بـ 50 لاعبا محاكى يحصد كل منهم 20 محصولا في الثانية يكلف 0.37 ميلي ثانية لكل تِك. ويملك الخادم 50 ميلي ثانية لكل تِك لينفقها، وحافظ على 20 TPS ثابتة.

اختبارات كشفت أخطاء حقيقية

ضمت مجموعة الاختبارات 501 اختبارا بعد الانتهاء من الأساس، و780 بنهاية مرحلة حلقة الأموال. وأكثر اختبار كان مفيدا لم يكن اختبار وحدة على الإطلاق. فاختبار الإقلاع يشغّل خادما حقيقيا بكل ملفات jar محمّلة، وقد كشف خللا لم تستطع اختبارات الوحدة رؤيته.

عندما ينقر لاعب بزر الفأرة الأيمن على الهواء، يُطلق Paper حدث التفاعل مُعلَّما بالفعل بأنه ملغى. وكانت سبعة معالِجات مضبوطة على تجاهل الأحداث الملغاة، فتجاهلت تلك الميزات بهدوء كل نقرة على الهواء. وبنى كل تمثيل وهمي في اختبارات الوحدة الحدث دون إلغاء، فنجحت كلها. أما اختبار الإقلاع فاستخدم الخادم الحقيقي وفشل على الفور.

فعاليات دون فقدان عناصر

تشغّل وحدة الفعاليات 14 لعبة مصغرة. والانضمام إلى إحداها يأخذ لقطة من مخزون اللاعب وحالته. وكل طريقة للخروج من فعالية، سواء بالفوز أو الخسارة أو المغادرة، تستعيد تلك اللقطة أولا. ولا تُصرف الجوائز إلا بعد حفظ الاستعادة، بحيث لا يستطيع أي عطل في المنتصف أن يمنح جائزة ويمسح مخزونا، أو العكس.

ما تعلمته من ذلك

  • التدقيق قبل النقل يعني أن الشيفرة الجديدة أصلحت الأخطاء القديمة بدل أن تنسخها.
  • التمثيلات الوهمية توافق افتراضاتك. أما الاختبار مقابل الخادم الحقيقي فهو الذي يعترض عليها.
  • وضع كل رقم في الإعدادات يعني أن موازنة الاقتصاد لم تعد بحاجة إلى مطور.