Ir para conteúdo
  • Cadastre-se
Grundor

L2JPHP: "One library to rule them all"

Grundor

Este é um trabalho em progresso (WIP: Work in progress).

Isso significa que esse projeto não está pronto para uso ou implementação.

Message added by Grundor

Posts recomendados

bhBwp7U.jpg

 

Olá Papangos e Papangas desse meu Brasil baronil!

 

Vos trago não um servidor de L2 baseado em PHP,  não um site completo cheio de fruru, mas uma biblioteca que vai revolucionar o desenvolvimento web para L2J.

 

Introdução


Muitos projetos paralelos foram desenvolvidos no decorrer dos anos, e o L2J hoje está ramificado em diversas distribuições, cada uma delas com banco de dados diferentes,  seja por nome de tabela, campos, etc. Nunca se foi estabelecido um padrão para que todos os bancos respeitassem uma nomeclatura específica, por vezes foram desenvolvidos por desenvolvedores amadores, que apesar de habilitosos , nunca estudaram e não conhecem boas práticas ou seguem algum tipo de padrão.   

Isso dificulta o desenvolvimento de aplicações comatíveis com tantas revisões(L2jserver, l2jbrasil, dream, sunrise, frozen, etc)  e versões do jogo diferentes(Interlude, Gracia, Classic, etc). 

O Grande desafio disso tudo é,  Como criar aplicações web, em php, que sejam compatíveis com o maior número de revisões possível?

 A resposta para isso é a Harmonização de Dados.

Citar

A Harmonização de Dados é o conceito de que você pode criar aplicações que interpretam diversas fontes de dados diferentes e que atuam com um único padrão de entrada e saída.

E a melhor forma de fazer isso é trabalhar na camada de Model, que passa para os controlers um único formato conhecido de dados. Parece complexo, mas não é tanto assim 🙂

 

Como funciona?

Primeiro temos que definir um conjunto de constantes:

<?php

//PROJECT DEFAULTS
define('L2JBR_DIST', "L2JSERVER"); //Qual a distribuição?
define('L2JBR_L2VERSION', "Interlude"); //Qual a versão do jogo?

define('L2JBR_SALT', 'change_it_for_something_else'); //Será usado para métodos de segurança no futuro.



//DATABASE
define('L2JBR_DB_DRIVER', "mysql");
define('L2JBR_DB_HOST', "localhost");
define('L2JBR_DB_PORT', 3306);
define('L2JBR_DB_NAME', "l2jdb");
define('L2JBR_DB_USER', "root");
define('L2JBR_DB_PWD', "");

Ao configurar a aplicação será necessário dizer para qual versão os Models derão utilizados. O modelo padrão é o L2JSERVER, por ser o projeto base para 99% dos outros projetos, e Interlude que é a versão mais difundida o que já aumenta a compatibilidade inicial da biblioteca.

Mas ai tá, vc deve estar se perguntando "tá, mas como tudo acontece?",  veja o exemplo à seguir com o Model "Characters" responsável pela manipulação dos dados de um personagem:

<?php

$CharactersModel = \L2jBrasil\L2JPHP\ModelFactory::build('Players/Characters');

$CharactersModel->get('ID'); //Retorna o usuário pelo ID
$CharactersModel->update('ID', ["name"=> "Grundor"]); //Atualiza o Nome do personagem
$CharactersModel->ban('ID'); //Bane o personagem pelo ID
$CharactersModel->all(['name','level'],false,10,'level'); //Retorna os 10 personagens com maior level.

//Exemplo Avançado:
$CharactersModel->select(['character.id','account.name'])
    ->join(\L2jBrasil\L2JPHP\ModelFactory::build('Players/Account'))
    ->orderby('level')
    ->limit(100)
    ->query()
    ->FetchAll();

 

 

O segredo está nessa classe "ModelFactory". O método build retorna a instância do model requisitado, nesse caso, no namespace Player/Character.  Mas como ele faz isso?

Ele monta dinâmicamente a instância da classe com base na configuração da DIST e da  L2JBR_L2VERSION  e irá lançar uma exceção caso não exista, 

Então no exemplo acima a chamada do "Build" faria o mesmo que:

 

<?php

$CharactersModel = \L2jBrasil\L2JPHP\Models\Dist\Interlude\L2JSERVER\Players\Characters();
//...

Que pode ser usado diretamente também, sem problemas, já que são todas classes idependentes e instanciáveis.
 

Todo model terá as operações de CRUD(Create, Read, Update e Delete na língua Inglesa)  e "listagem(all)". Além disso, os models implementam interfaces, essas interfaces vão garantir que todo model , por exemplo "Characters", de todas as versões, possuam os mesmos métodos mais padrões (ban, move, changeProfession, changeLevel, cleanPK, etc), além disso será permitido de forma dinâmica.

Para que seja possível manter a compatibilidade, está sendo desenvolvido uma classe que irá montar as condições "where"  (segundo parâmetro do método all (listagem) ) para que a conversão dos nomes das colunas também seja aplicado dinâmicamente.

Como posso ajudar?

Há diversas revisões, todas elas precisarão e poderão ser implementadas, você poderá escrever models compatíveis com as revisões para que seja utilizado expandindo a compatibilidade das aplicações desenvolvidas utilizando esse framework. Detalhes para contribuição serão atualizados no futuro próximo.

Informações técnicas

 

 

 

  • Gostei 7
  • Amei 3

Compartilhar este post


Link para o post
Compartilhar em outros sites

Precisando de Dedicado ou VPS?

Conheça a L2JCenter

Show!

Esse projeto vai agilizar muito o desenvolvimento e o melhor de tudo, vai padronizar os projetos, a galera vai entender melhor o código por se acostumar com ele, menos dúvidas e mais projetos;

Linda iniciativa!

  • Gostei 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Caraca,

Posso ser novo na área porem peguei o espirito da coisa, isso ajuda demais, há casos como JSunrise, que stats, e items são com xml, já em outras versões são diretamente na DB, acaba que o determinado script php não funciona e o responsável tem que adaptar isso.

  • Gostei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
11 minutos atrás, TurtleLess disse:

Caraca,

Posso ser novo na área porem peguei o espirito da coisa, isso ajuda demais, há casos como JSunrise, que stats, e items são com xml, já em outras versões são diretamente na DB, acaba que o determinado script php não funciona e o responsável tem que adaptar isso.

Então, isso ajudaria pois o acesso pode ser dado diretamente via XML ao invés do SQL, aplicando a regra de negócio diretamente no model.

À principio a intenção é implementar o máximo de métodos com base em L2jServer e depois ir implementando os métodos para as outras revs e versões

A idéia é ,  "faça isso" seja "faça isso" em todas as versões, o máximo compatível possível é claro.

 

  • Gostei 3

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ótimo share!

Uma dúvida/sugestão: o ban em personagens (dei uma olhada no código e vi que não foi implementado ainda) poderia ser da mesma forma que o banimento de contas, não? Pq também tem uma columa "access_level" na tabela "characters"... Caso isso não seja eficaz, um simples "delete" recursivo através do ID (remove atalhos, skills, itens, macros etc) poderia resolver também, não?

--

Entrei de férias da faculdade semana passada e agora posso voltar a me envolver com L2J novamente. Vou contribuir com o que puder nesse meio tempo.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu não testei ainda, mas tenho uma pergunta...

Muitas revisões novas usam o banco de dados para gravar configurações e gameplay (items de usuário e etc) sendo assim todos os items, NPC e demais informações que são comuns a todos estão em arquivos XML, eu fiz um site recentemente aonde eu linkei os arquivos XML do server e usava DOM para puxar as informações transformando em JSON "on-the-fly" mas é trabalhoso e abre brecha de segurança pra exploit.

Esse projeto tem uma API interna pra puxar informação desses arquivos XML? se não, seria uma sugestão para implementar futuramente, se já tem esqueçam 😛 

Compartilhar este post


Link para o post
Compartilhar em outros sites
Em 21/07/2018 at 13:11, Enkel disse:

Ótimo share!

Uma dúvida/sugestão: o ban em personagens (dei uma olhada no código e vi que não foi implementado ainda) poderia ser da mesma forma que o banimento de contas, não? Pq também tem uma columa "access_level" na tabela "characters"... Caso isso não seja eficaz, um simples "delete" recursivo através do ID (remove atalhos, skills, itens, macros etc) poderia resolver também, não?

--

Entrei de férias da faculdade semana passada e agora posso voltar a me envolver com L2J novamente. Vou contribuir com o que puder nesse meio tempo.

Na verdade estou só divulgando o começo do projeto, ainda não está em release, é um WIP(work-in-progress), a demonstração do código do model Character é apenas uma POC (Proof of Concept), a ideia é que exista um método ban, o que o método ban faz para cada revisão é customisável. O importante nesse caso é que o ban seja executado da mesma forma, passando o mesmo parâmetro. Quando não houver a possibilidade se implementar com apenas um parametro um array será usado e cada model decidirá a regra de negócio a ser implementad.

Seria ótimo ter ajuda, principalmente , no primeiro roadmap (não publicado) que pretende cobrir a gestão total de contas, personagens e items. Inclua dentro de personagem os ranks padrões de pvp, pk, level, adena, etc.

Como falei o projeto base será o L2jServer interlude, ele será o norte para a implementação de outras versões.

 

Em 21/07/2018 at 14:07, Seifer Almasy® disse:

Eu não testei ainda, mas tenho uma pergunta...

Muitas revisões novas usam o banco de dados para gravar configurações e gameplay (items de usuário e etc) sendo assim todos os items, NPC e demais informações que são comuns a todos estão em arquivos XML, eu fiz um site recentemente aonde eu linkei os arquivos XML do server e usava DOM para puxar as informações transformando em JSON "on-the-fly" mas é trabalhoso e abre brecha de segurança pra exploit.

Esse projeto tem uma API interna pra puxar informação desses arquivos XML? se não, seria uma sugestão para implementar futuramente, se já tem esqueçam 😛 

 

Sim, já trabalhei com ótimas classes de leitura e manipulação de XML, ainda não está no roadmap a inclusão de uma versão que use XML, como disse acima é intenção fazer a cobertura de pelo menos accounts, characters e items (inventorio e warehouse).

 

O Objetivo principal é que essa lib seja a base de outros projetos como o https://github.com/L2jBrasil/vote-for-reward que comecei porém parei devido a barreira das revisões. 
O mais importante à se destacar nesse projeto é que o escopo dele é apenas de manipulação de dados no mais baixo nível das aplicações que utilizarem ele garantindo ao desenvolvedor uma API de models que seja suficiente para desenvolver aplicações mais complexas sem se preocupar com essa parte, focando na funcionalidade em sí.

 

Editado por Wallace Carvalho
  • Gostei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Uma configuração com os nomes de tableas usados, em teses, não resolveria uma boa parte do problema?

Algo tipo:

$account = 'accounts';

$characters = 'characters';

$items = 'items';

Como a estrutura é bastante comum de uma versão pra outra (ao menos o básico é, o que costuma mudar é access_level pra accessLevel, e sinceramente não sei qual das duas é o padrão atual) uma sessão de configuração do script aonde se colocasse os dados de forma manual, ao meu ver, seria uma solução bem mais prática do ponto de vista técnico.

Ou, existe algum modo de listar as tabelas de um banco de dados e procurar por elas (via PHP) guardando o retorno num array e comparando os possíveis nomes de tabela dos databases das diferentes versões de L2j que existem...? (Se existe como fazer isso desconheço, senão já teria usado nos meus sites)

 

Compartilhar este post


Link para o post
Compartilhar em outros sites
21 horas atrás, Seifer Almasy® disse:

Uma configuração com os nomes de tableas usados, em teses, não resolveria uma boa parte do problema?

Algo tipo:

$account = 'accounts';

$characters = 'characters';

$items = 'items';

Como a estrutura é bastante comum de uma versão pra outra (ao menos o básico é, o que costuma mudar é access_level pra accessLevel, e sinceramente não sei qual das duas é o padrão atual) uma sessão de configuração do script aonde se colocasse os dados de forma manual, ao meu ver, seria uma solução bem mais prática do ponto de vista técnico.

Ou, existe algum modo de listar as tabelas de um banco de dados e procurar por elas (via PHP) guardando o retorno num array e comparando os possíveis nomes de tabela dos databases das diferentes versões de L2j que existem...? (Se existe como fazer isso desconheço, senão já teria usado nos meus sites)

 

 


2 Problemas nisso:

- O projeto é PHP de alto nível , orientação objeto, blueprints e boas práticas, alinhado com novos paterns e tentando compatibilizar com php 7, já que o php 5 já é considerado deprecated. Usando variáveis para customizar as diferenças vc não está permitindo a criação de múltiplas e diversificadas aplicações, basicamente uma couxa de retálios.

- Compatibilidade limitada, sem possibilidade de colaboração da comunidade, explico:

Fazendo dessa forma, vc  sempre considera que todos os projetos tenham uma única tabela "characters" com colunas que podem variar de a para b, a proposta do projeto é abastrair a  camada de acesso aos dados.

Como prova de conceito eu declarei o método "ban", o que é necessário para fazer o BAN em cada revisão ou versão eu não sei, mas eu padronizei a entrada do método que é o identificador de characters. 

Isso significa que idependente do projeto aplicado, o método ban recebe sempre a mesma entrada e terá também a mesma saida, isso é a garantia da interoperabilidade com multiplas formas.

 

 

Outro exemplo que eu posso aplicar é o Iventorio, imagine que num projeto foi otimizado para que os itens fiquem em tabelas distintas e é necessário um JOIN para regatar os itens do usuário, suponhamos que tem uma tabela para consumíveis, armors, weapons e questitens.  Eu preciso retornar o iventário do usuário, num eu preciso fazer um join, noutro é um select simples.  Só um array de variáveis resolveria? 

A complexidade impediria que algo assim fosse feito.

 

A proposta é que aplicações sejam construidas e que sejam capazes de executar exatamente a mesma coisa idependente da revisão ou da versão com o mínimo de configuração, que no caso do projeto 2 linhas basta:

 

<?php

define('L2JBR_DIST', "L2JSERVER"); //Qual a distribuição?
define('L2JBR_L2VERSION', "Interlude"); //Qual a versão do jogo?

 

 

 

  • Gostei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora

  • Mudanças no Login

    Preste atenção às mudanças no método de login.

    Com a migração para nomes de usuário IPB4 não existe mais.

    Você deve usar seu nome de exibição ou email em vez de nome de usuário.




     



×