Sto lavorando a un framework di gioco che consenta agli utenti di utilizzare più modifiche / plug-in per aggiungere funzionalità aggiuntive al gioco.
Per il resto del post, utilizzerò le seguenti definizioni:
mod
: codice che richiede modifiche sia al client che al server. Ad esempio, aggiungendo un nuovo pacchetto al protocollo.
plugin
: codice che modifica la funzionalità esistente senza richiedere una modifica sull'altro lato. Ad esempio, aggiungendo un'interfaccia di gestione remota al server o consentendo al client controlli più dettagliati rispetto alla qualità audio e audio.
Questa domanda si riferisce a entrambi questi aspetti, tuttavia mi concentrerò su mods
in quanto sembrano darmi i maggiori problemi.
Diciamo che fornisco una classe giocatore predefinita chiamata Player
che modella il personaggio di un giocatore. Diciamo che, per questo particolare server, l'operatore del server vuole includere il 2% dimods
,% diFoo
e% diBar
, entrambi scritti da persone diverse.
Sia Foo
che Bar
devono aggiungere funzionalità aggiuntive alla classe Player
. Foo
ha bisogno di un metodo doFoo
e Bar
ha bisogno di un metodo doBar
. Entrambe le implementazioni effettive sono incluse in qualche modo dagli sviluppatori di mod (probabilmente in una classe diversa).
Una soluzione che ho preso in considerazione è l'utilizzo di Reflection e la modifica della classe in fase di runtime, estendendo specifiche interfacce mod. Qualcosa come
public interface FooPlayer {
void doFoo();
}
public interface BarPlayer {
void doBar();
}
public class FooPlayerImplementation implements FooPlayer {
public void doFoo() {
// ...
}
}
public class BarPlayerImplementation implements BarPlayer {
public void doBar() {
// ...
}
}
public class FooLoader {
public void onLoad() {
SomeManager.findPlayerClass()
.implementInterface(FooPlayer.class, FooPlayerImplementation.class);
}
}
public class BarLoader {
public void onLoad() {
SomeManager.findPlayerClass()
.implementInterface(BarPlayer.class, BarPlayerImplementation.class);
}
}
Dove in fase di esecuzione, inietterebbe la classe Player
con le implementazioni da Foo
e Bar
, e renderà implementare FooPlayer
e BarPlayer
. Ma poi abbiamo dei problemi in cui due diverse mod aggiungono la stessa firma del metodo nella loro interfaccia (che potrebbe essere risolta anteponendo il nome della classe al metodo, ma poi scendiamo in una buia tana molto scura).
Un'altra cosa a cui ho pensato brevemente è stata solo un'eccitazione folle, quindi gli sviluppatori non hanno bisogno di fare qualcosa del genere, ma questo apre una altrettanto worm, oltre a non fornire la quantità di controllo di cui uno sviluppatore potrebbe aver bisogno.
Ma vorrei REALMENTE come evitare di riflettere se possibile.
Ho visto AspectJ e la programmazione orientata all'aspetto, e sembra che possa funzionare, ma non ho alcuna esperienza da raccontare.
Le domande che ho sono:
- C'è un modo per ottenere questo tipo di funzionalità in modo OOP?
- C'è un modo per farlo con la libreria Java SE standard?
- Potrebbe farlo questo AOP?
Considerazioni : se uno di questi è sbagliato o mal guidato, faccelo sapere.
- Non penso che l'ereditarietà funzioni perché potrebbero esserci più mod che vogliono estendere la funzionalità di
Player
, e tuttoPlayer
s sarebbe soggetto a tutto ilmods
. Non ci potrebbe essere unFooPlayer
e unFooBarPlayer
allo stesso tempo. Sen
mod estende la funzionalità Player, che il Player deve avere componentin
. - Il pattern decoratore non funzionerà davvero, penso perché l'intervento manuale sarebbe richiesto dall'operatore (che può o non può sapere qualcosa sulla programmazione) per tessere insieme le implementazioni.
Qualcosa di simile
public class FooBarStaminaMagickaPlayer implements Player, Foo, Bar, Stamina, Magicka
- Se possibile, vorrei evitare che ogni sviluppatore mod abbia una mappatura all'interno del proprio codice per tenere traccia delle cose.
Ad esempio, qualcosa di simile
public class StaminaMapper {
private final Map<Player, Stamina> playerStaminaMap;
}