Як реалізувати тестовий світ, що не перезапускається?


23

Я шукаю ідеї, як зробити наступне: Я хочу написати простий "світ" на Java. Один, який я міг би запустити, а потім пізніше додати нові об'єкти, щоб імітувати / спостерігати різну поведінку між існуючими об'єктами. План полягає в тому, щоб кодувати новіші об’єкти після деякого перегляду старих, а потім завантажити / випустити їх у існуючий світ. Проблема полягає в тому, що я не хочу ніколи зупиняти і не перезапускати світ, коли він починається, я хочу, щоб він працював протягом декількох тижнів, але мені потрібна можливість кидати об'єкти і переробляти / переписувати / видаляти / створювати / мутувати їх з часом, не потребуючи перезавантаження. Світ може бути таким же простим, як масив розміром 100 x 100 X / Y, з можливим графічним графічним інтерфейсом для візуального представлення світу. Я знаю, що мені потрібен якийсь процес тиктимери для моніторингу об'єктів та надання кожному «шансу діяти»

Приклад: Я кодую World.java у понеділок і залишаю його працювати. Потім у вівторок я пишу новий клас під назвою Rock.java (який не рухається). Потім я завантажую / скидаю (якось?) У цей вже запущений світ (який просто скидає його десь випадково у світовому масиві і ніколи не рухається). Потім у середу я створюю новий клас під назвою Cat.java і скидаю його у світ, знову розміщуючись випадковим чином, але цей новий об’єкт може рухатися по всьому світу (за деяку одиницю часу), потім у четвер я пишу клас під назвою Собака. java, яка також рухається навколо, але може "діяти" на інший об'єкт, якщо він знаходиться в сусідньому місці і навпаки.

Ось річ. Я не знаю, який тип структури / дизайну мені потрібно було б кодувати фактичний світовий клас, щоб знати, як виявити / завантажити / відстежити майбутні (і наразі неіснуючі) об’єкти.

Будь-які ідеї про те, як ви зробили щось подібне за допомогою Java?


2
Дуже багато звучить як гаряча заміна . Можливо, є про це література, яка може бути корисною. У всякому разі, дуже цікаве запитання. +1…
Конрад Рудольф

Відповіді:


5

Що ви в основному шукаєте, це система з гарячим підключенням. Ви запускаєте основну програму та додаєте додатки під час виконання, які інтегруються у цикл подій. Спочатку почніть думати про те, чого очікує ваш світ від ігрової сутності. Наприклад (на основі вашого опису):

interface Entity {
   void init(World world);
   // Called when loaded for the first time in the world and adds itself
   // to the world (correct position in the array, scheduler for updates)

   void update(World world);
   // Called when scheduler fires (allows the entity to think about its
   // next move)

   Image getImage();
   // Called by the GUI when it is time to draw the entity on the screen
}

Звичайно, ви можете додати інші методи, які вважаєте потрібними. Зверніть увагу на параметр World за допомогою двох відповідних методів. Це дозволяє вашому новому суб'єкту враховувати світ під час налаштування чи оновлення. Наприклад, у вашому класі собак, ви можете поцікавитися світом усіх котів в околицях. Далі ви створюєте свій світ, який працює з цим інтерфейсом, і систему для динамічного збирання та завантаження коду Java. Приклад цього можна знайти тут .

void injectEntity(String filename, World world) {
    // Load the class as described in the mentioned link
    Entity e = (Entity) loadClass(filename);
    e.init(world);
}

Виберіть цей метод у Всесвітньому графічному інтерфейсі для додавання нових об'єктів. Залежно від вашої світової реалізації, функція Entit init може виглядати так:

void init(World world) {
   // Register entity with world for easy access
   world.register(this, "RockImpl A");

   // Place the entity on the world map
   Point initialLocation = Point(10,5);
   world.place(this, initialLocation);

   // Schedule its update method for every 5 seconds
   world.schedule(this, 5);
}

1
Ключові слова для google: "IoC контейнери", "Інверсія управління", "Введення залежності". Це методи для загальних систем гарячого підключення, які дозволяють виявляти та завантажувати компоненти під час виконання.
Nevermind

16

Ми зробили щось подібне в Стендалі для набігів.

Ми не прагнули повністю уникнути перезавантажень. Тому зміни в наших основних інфраструктурних службах, таких як зв'язок клієнт / сервер, потребують перезавантаження. Але додавання сутностей, істот і NPC та зміна існуючих об'єктів справді працює. (О, а іноді виправлення помилок у прямому ефірі, відображення можна використовувати для маніпулювання навіть приватними полями).

Оскільки ми не тільки хочемо нового об’єкта, заснованого на нових даних (як-от інша шкіра), але хочемо додати нову поведінку, світовій програмі потрібно мати можливість завантажувати файли нового класу . Ми їх називаємо "скриптами", але вони є реальними складеними класами Java. Ці класи реалізують інтерфейс Script.java .

Maria.java - простий приклад. Вона - новий NPC, який продає напої та їжу гравцям. Ми також можемо визначити дуже складні об'єкти і там.

Новий клас завантажується таким чином:

// create a new class loader, with the script folder as classpath.
final File file = new File("./data/script");
final ClassLoader loader = new URLClassLoader(new URL[]{file.toURI().toURL()});

// load class through new loader
final Class< ? > aClass = loader.loadClass(classname);
script = (Script) aClass.newInstance();

Якщо ви можете забезпечити унікальні імена і ніколи не хочете розвантажувати класи, ви закінчите роботу з низьким рівнем.

Однак розвантаження здається досить важливим. Для цього вам потрібно інстанціювати завантажувач нового класу, коли ви хочете вставити новий код. Так що GC може виконати свою роботу після очищення останнього посилання на цей код.

У нас є команда / unload, яка викликає метод розвантаження в нашому інтерфейсі, щоб сценарії могли робити очищення. Справжнє вивантаження здійснюється автоматично GC.

Ми часто створюємо безліч тимчасових об’єктів під час рейдів. І ми хочемо, щоб їх усі вилучили після закінчення рейду. Наприклад, Gnomes Raid, який створює ряд гномів біля невидимого адміністратора, ми використовуємо цей код: GnomeRaid.java розширює CreateRaid.java .

Сценарій може отримати доступ до світу безпосередньо (як показує перший приклад) і зробити своє власне очищення методом unload (). Але кодери Java не використовуються для очищення, і це дратує. Тож ми створили пісочницю, яку можуть використовувати сценарії. Під час вивантаження всі об’єкти, додані до світу через клас Sandbox, видаляються.


3

Збережіть світ (каламбур не призначений) та всі його стану (позиції, швидкості, всі змінні).

  • Закрийте програму.
  • Внесіть зміни (забезпечивши сумісність із заощадженнями).
  • Програма перекомпіляції.
  • Перезапустіть програму.
  • Навантажуйте світ і державу.
  • Повторіть

Це загальне рішення, однак я не знаю специфіки Java, щоб знати, чи можна динамічно реалізовувати кодові блоки та класи, як ви сподіваєтесь ...

Варіант 2 - прив’язати мову сценаріїв, яку можна завантажувати на льоту.


+1 для мови сценаріїв. Якщо ви не прив’язані до Java, спробуйте також деякі драйвери MUD на базі LPC та мудровики.
Мартін Сойка

1

Для Java все, що вам потрібно, - це платформа OSGi . З цим дрібницею є модулі або програми із гарячою заміною, і навіть робити віддалене управління або часткове оновлення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.