Estou procurando idéias sobre como fazer o seguinte: Quero escrever um "mundo" simples em Java. Um que eu poderia iniciar e, em seguida, adicionar novos objetos posteriormente para simular / observar comportamentos diferentes entre os objetos existentes. O plano é codificar os objetos mais novos depois de observar os antigos por um tempo e depois carregá-los / soltá-los no mundo existente. O problema é que eu nunca mais quero parar ou reiniciar o mundo depois que ele começar, quero que ele funcione por algumas semanas, mas eu preciso da capacidade de soltar objetos e refazer / reescrever / excluir / criar / mutar ao longo do tempo sem precisar de uma reinicialização. O mundo poderia ser tão simples quanto uma matriz 100 x 100 de locais X / Y, com uma possível GUI de mapa lado a lado para representar visualmente o mundo. Eu sei que preciso de algum tipo de processo de timer para monitorar objetos e dar a cada um uma 'chance de agir'
Exemplo: codifico World.java na segunda-feira e deixo em execução. Então, na terça-feira, escrevo uma nova classe chamada Rock.java (que não se move). Em seguida, carrego / solto (de alguma forma?) Neste mundo já em execução (que apenas o coloca em algum lugar aleatório na matriz mundial e nunca se move). Então, na quarta-feira, crio uma nova classe chamada Cat.java e a solto no mundo, novamente colocada aleatoriamente, mas esse novo objeto pode se mover pelo mundo (em alguma unidade de tempo); então, na quinta-feira, escrevo uma classe chamada Dog. java que também se move, mas pode "agir" em outro objeto se estiver no local vizinho e vice-versa.
Aqui está a coisa. Não sei que tipo de estrutura / design eu precisaria para codificar a classe mundial real para saber como detectar / carregar / rastrear objetos futuros (e atualmente inexistentes).
Alguma idéia de como você faria algo assim usando Java?
Respostas:
O que você está procurando basicamente é um sistema hot-plugável. Você executa um aplicativo principal e adiciona plug-ins em tempo de execução que são integrados no loop de eventos. Primeiro, comece pensando no que seu mundo espera de uma entidade do jogo. Por exemplo (com base na sua descrição):
Obviamente, você pode adicionar outros métodos que considerar necessários. Observe o parâmetro World com os dois métodos relevantes. Isso permite que sua nova entidade considere o mundo ao configurar ou atualizar. Na sua turma de cães, por exemplo, você pode pedir ao mundo todos os gatos da vizinhança. Em seguida, você cria seu mundo que funciona com essa interface e um sistema para compilar e carregar dinamicamente o código Java. Um exemplo disso pode ser encontrado aqui .
Chame esse método da GUI mundial para adicionar novas entidades. Dependendo da sua implementação no mundo, uma função init da Entity pode ter esta aparência:
fonte
Fizemos algo parecido em Stendhal para ataques.
Não pretendemos evitar completamente reinicializações. Portanto, as alterações em nossos principais serviços de infraestrutura, como a comunicação cliente / servidor, precisam ser reiniciadas. Mas adicionar entidades, criaturas e NPCs e modificar objetos existentes funciona. (Ah, e, às vezes, corrigindo bugs, a reflexão pode ser usada para manipular até mesmo campos particulares).
Como não queremos apenas um novo objeto com base em novos dados (como outra capa), mas queremos adicionar um novo comportamento, o programa mundial precisa ser capaz de carregar novos arquivos de classe . Nós os chamamos de "scripts", mas são classes Java realmente compiladas. Essas classes implementam a interface Script.java .
Maria.java é um exemplo simples. Ela é um novo NPC que vende bebidas e comida para os jogadores. Também podemos definir objetos muito complexos .
Uma nova classe é carregada desta maneira:
Se você pode garantir nomes exclusivos e nunca desejar descarregar classes, está pronto com as coisas de baixo nível.
Descarregar , no entanto, parece muito importante. Para conseguir isso, você precisa instanciar um novo carregador de classes sempre que quiser injetar um novo código. Para que o GC possa fazer seu trabalho após a última referência a esse código ser limpa.
Temos um comando / unload que chama um método de descarregamento em nossa interface para que os scripts possam fazer a limpeza. O descarregamento real é feito automaticamente pelo GC.
Costumamos criar muitos objetos temporários durante ataques. E queremos que todos eles sejam removidos após o término do ataque. Por exemplo, o Gnomes Raid, que gera vários gnomos perto do administrador invisível, usamos este código: GnomeRaid.java estende CreateRaid.java .
O script pode acessar o mundo diretamente (como mostra o primeiro exemplo) e fazer sua própria limpeza no método unload (). Mas os codificadores Java não são usados para limpar, e isso é irritante. Por isso, criamos uma sandbox que os scripts podem usar. Ao descarregar, todos os objetos adicionados ao mundo através da classe Sandbox são removidos.
fonte
Salve o mundo (sem trocadilhos) e todo o seu estado (posições, velocidades, todas as variáveis).
Esta é uma solução geral, porém, não preciso especificar Java para saber se você pode implementar dinamicamente blocos e classes de código como você espera ...
A opção 2 é vincular uma linguagem de script que pode ser carregada em tempo real.
fonte
Para Java, tudo o que você precisa é de uma plataforma OSGi . Com isso, é trivial a troca de módulos ou aplicativos e até faz gerenciamento remoto ou atualizações parciais.
fonte