Ir para conteúdo
  • Cadastre-se

Otimizar o L2jFrozen criando um novo projeto


vaneves

Posts recomendados

Senhores, bom dia,

estou começando a otimizar o L2jFrozen, melhorando o código e deixando-o mais organizado. Há muitos projetos L2j, mas a maioria deles são a junção de vários módulos feitos por pessoas distintas, módulos muito bons, mas a maioria das vezes sem código otimizado ou padronizado.

Sou formado em Sistemas de Informação há 5 anos, trabalho com desenvolvimento há mais 15 anos, trabalho principalmente com desenvolvimento web, com PHP, MySQL/PostgreSQL, Laravel, Angular... mas trabalho muito bem com Java, C#, Python, SQL Server e gosto de brincar com NodeJS e MongoDB. Dentro do desenvolvimento gosto de trabalhar com as melhores práticas, de acordo com o definido pela comunidade da linguagem.

Desafios

Gostaria de convidar, quem tiver interesse e conhecimento, para criarmos um projeto bem organizado de L2j Interlude, tendo como base o L2jFrozen (aberto a sugestões de outro projeto). Como exemplo de coisas a serem feitas, seriam:

1) Revisar as estruturas da tabelas do banco de dados, melhorando a nomenclatura das tabelas e colunas, deixando-as padronizadas. Por exemplo, a tabela characters está no plural, enquanto a castle está no singular. Dentro da tabela characters temos as colunas char_namemaxHppvpkills, poderiam seguir um padrão de name, max_hp e pvp_kills (padrão snake case).

2) Revisão, organização e otimização dos códigos Java.

3) Revisão, organização e otimização das Quests, até mesmo a criação de Quests novas.

4) Revisão, organização e otimização dos HTMLs. Por exemplo, todo HTML que vejo é sem indentação, sem aspas nas propriedades. Isso não é nem de longe uma boa prática. Sei que o HTML deve ter um limite de caracteres, mas no Java a gente remove comentários, espaços duplos, quebra de linha e até aspas.

5) Criação de testes automatizados.

6) Revisão e otimização das consultas SQL e a utilização de ferramentas como Memcached (opcional) para otimizar as buscas ao banco de dados.

7) Ao final, criação de um painel de administração e site.

Vantagens

Por que fazer isso? Você deve está se perguntando.

1) Mais segurança: o código organizado é mais fácil de entender a lógica e ver se ela está correta ou não. Sem falar dos testes automatizados.

2) Facilidade de alteração/contribuição: se é mais fácil de entender, é mais fácil de contribuir.

3) Mais leve, que roda mais player: se é mais leve, roda mais players simultaneamente.

4) Experiência: a experiência de passar por um desafio desses é demais, força você a aprender mais, buscar seu melhor. Sem falar que pode estar ajudando o futuro melhor emulador de L2 Interlude da história.

6) Teste em um servidor real: ao final colocaremos o projeto em teste real, com servidor para milhares de players e com muita diversão.

7) Venda de pacote: já compilado, com instalador, com site, painel de administração, manual, suporte e etc.

 

A proposta está aceita, quem tiver interesse, comentar descrevendo suas habilidades, deixando o link para o seu GitHub.

Deixo aqui o link do meu GitHub, para analisarem projetos que já criei e contribui: https://github.com/vaneves/

Link para o comentário
Compartilhar em outros sites


7 horas atrás, vaneves disse:

 

Acho que seria melhor utilizar aCis e finalizar as implementações que estão incompletas, porém isso exigirá um conhecimento avançado.

Estarei enviando meu número via pm caso você queira me adicionar no whatsapp.

QdeQ9Kp.png

Link para o comentário
Compartilhar em outros sites

18 horas atrás, PeNaChO disse:

Acho que seria melhor utilizar aCis e finalizar as implementações que estão incompletas, porém isso exigirá um conhecimento avançado.

Estarei enviando meu número via pm caso você queira me adicionar no whatsapp.

Vi muitos tópicos perguntando qual a melhor rev, nenhum deles havia uma resposta concreta, por isso de criar esse projeto. Em muitos citavam o aCis, mas no fórum deles não é claro e não o repositório oficial (pelo menos não encontrei). O único que encontrei (SVN) está na revisão 6, sendo que no fórum diz estar na revisão 374.

O link do repositório que encontrei: https://xp-dev.com/svn/aCis_public/

Ainda encontrei esse, mas está fora do ar (erro 404): https://xp-dev.com/svn/aCis_community/

Saberia me dizer qual o repositório oficial e sob qual licença está?

Link para o comentário
Compartilhar em outros sites

4 horas atrás, vaneves disse:

Vi muitos tópicos perguntando qual a melhor rev, nenhum deles havia uma resposta concreta, por isso de criar esse projeto. Em muitos citavam o aCis, mas no fórum deles não é claro e não o repositório oficial (pelo menos não encontrei). O único que encontrei (SVN) está na revisão 6, sendo que no fórum diz estar na revisão 374.

O link do repositório que encontrei: https://xp-dev.com/svn/aCis_public/

Ainda encontrei esse, mas está fora do ar (erro 404): https://xp-dev.com/svn/aCis_community/

Saberia me dizer qual o repositório oficial e sob qual licença está?

A aCis usa um sistema "freemium" você paga 10 euros por ciclo e eles liberam 10 versões abaixo da atual no final de cada ciclo (ex.: ciclo 370 a 380 liberaram a 360, quando estiver na 380 a 390 irão liberar a 370).

Creio que a licença que eles usam seja a GPLv3 .0 a mesma da l2jserver.

QdeQ9Kp.png

Link para o comentário
Compartilhar em outros sites

podrias ayudar a Reynaldo el esta trabajando l2jfrozen 1132 y esta optimizando muchas cosas 

el projecto se llama l2jfrozen 1.5

el projecto soporta MYSQL y MARIADB y se actualizo a java 8

TIMELINE : https://sourceforge.net/p/l2jfrozen/code/commit_browser

SVN: https://svn.code.sf.net/p/l2jfrozen/code/

Editado por Escanor
Link para o comentário
Compartilhar em outros sites

Em 15/09/2018 at 18:35, PeNaChO disse:

A aCis usa um sistema "freemium" você paga 10 euros por ciclo e eles liberam 10 versões abaixo da atual no final de cada ciclo (ex.: ciclo 370 a 380 liberaram a 360, quando estiver na 380 a 390 irão liberar a 370).

Creio que a licença que eles usam seja a GPLv3 .0 a mesma da l2jserver.

Entendi, mas é estranho ser GPLv3 (software livre/opensource) e venderem. Teoricamente GPLv3 teria um repositório com o código. Freemium é software proprietário que você libera o compilado gratuito e cobra por módulos adicionais. O L2jServer é código aberto: https://bitbucket.org/l2jserver/

 

Em 16/09/2018 at 04:45, *=Koofs=* disse:

podrias ayudar a Reynaldo el esta trabajando l2jfrozen 1132 y esta optimizando muchas cosas 

el projecto se llama l2jfrozen 1.5

el projecto soporta MYSQL y MARIADB y se actualizo a java 8

TIMELINE : https://sourceforge.net/p/l2jfrozen/code/commit_browser

SVN: https://svn.code.sf.net/p/l2jfrozen/code/

Cara, gostei muito do seu trabalho. É mais ou menos disso que estou falando, só que mais alem. Uma das coisas principais é ir para uma plataforma de gerenciamento de código melhor, como Git (GitHub, GitLab ou Bitbucket), assim seria mais fácil reportar bugs, é mais fácil de acompanhar as alterações, branchs, merge e etc. Seria mais fácil integrar com outras ferramentas, como Slack, HipChat, Jira e/ou Trello, ferramenta de testes automatizados, como Travis.

Mas está fantástico o projeto. Irei acompanhá-lo enquanto vou pensando mais sobre esse projeto.

 

Link para o comentário
Compartilhar em outros sites

1 hora atrás, KhayrusS disse:

Interessante. Parabéns pela iniciativa. 

Tenho uma pergunta, mais por curiosidade. Quais técnicas e estratégias pretende usar para realizar os testes? 

Boa pergunta. Inicialmente seria interessante trabalhar apenas com testes de unidade, depois de pronto, poderia trabalhar numa ferramenta para fazer teste de carga e estresse.

Na hora de compilar o código é testado apenas a sintaxe, ou seja, se a estrutura Java está correta.

Já o teste de unidade é para analisar a lógica está correta.

O teste de carga e estresse é para testar o volume de dados e os acessos simultâneos. Nesse aqui poderia fazer ferramentas que populam a base de dados (até arquivo .sql mesmo) e criar uma ferramenta que simula acessos (com uma config para habilitar desabilitar) enviando e recebendo informações Opcode. Com isso é possível verificar o quanto o servidor suporta com determinada configuração. Mas, como disse, isso seria numa segunda etapa. 

No teste de unidade, que seria feito primeiro, consiste basicamente em criar (programar em Java) testes, na qual as classes e métodos do servidor são testadas. Você cria a instância da classe, chama o método passando parâmetros e analista o retorno. 

Por exemplo, você tem a seguinte classe:

public class Player implements ICharacter
{
    private double hp = 1000;

    public boolean doAttack(ICharacter target) {
        if (target == null) {
            return false;
        }
        if (target.isDead()) {
            return false;
        }
        // do attack
    }

    public void doKill() {
        this.hp = 0;
    }

    public boolean isDead() {
        return this.hp == 0;
    }
}

Então você tem que testá-la. Para isso você cria outra classe (vai estar no projeto, mas em diretório específico para isso):

public class PlayerTest 
{
    @Test
    public void whenTargetIsValid() throws Exception {
        Player player = new Player();
        Player target = new Player();
        boolean attacked = player.doAttack(target);
        assertEquals(true, attacked);
    }

    @Test
    public void whenTargetIsNullThenReturnFalse() throws Exception {
        Player player = new Player();
        Player target = null;
        boolean attacked = player.doAttack(target);
        assertEquals(false, attacked);
    }

    @Test
    public void whenTarhetIsDeadThenReturnFalse() throws Exception {
        Player player = new Player();
        Player target = new Player();
        target.doKill();
        boolean attacked = player.doAttack(target);
        assertEquals(false, attacked);
    }
}

No exemplo acima eu verifico se a lógica do método doAttack() está agindo de acordo com o esperado. Assim, qualquer alteração que eu fizer, adicionar um módulo, esses testes já vão estar implementados, então eu apenas executo e vejo se ainda comporta como esperado.

Mas esse teste acima é do game server. Poria testar também o data pack, por exemplo os arquivos HTML dos NPCs, na qual poderia percorrer todos e verificar se a sintaxe está correta (já que não compila) e compactado (removendo espaços, quebra de linha e etc, não ultrapassa o limite. Verificar os XMLs também. Esses testes são até mais fáceis do que os de unidade, que são muitos.

Editado por vaneves
Havia feito o método doKill() errado no exemplo
Link para o comentário
Compartilhar em outros sites

Bacana, Cara, gostei. Só uma sugestão:

5 horas atrás, vaneves disse:

Boa pergunta. Inicialmente seria interessante trabalhar apenas com testes de unidade, depois de pronto, poderia trabalhar numa ferramenta para fazer teste de carga e estresse.

Ao invés de fazer os testes de carga e estresse apenas depois que os testes unitários estiverem prontos, poderia fazer meio que comitantemente. Isso porque em algum momento vai se pegar fazendo teste de unidades que não vão agregar tanto valor. Eu inclusive, abordaria uma visão contrária, pois acredito que os testes de desempenho sejam críticos demais para deixar por último. Mas é só minha visão, só estou compartilhando um pouco do que eu penso sobre o assunto. 

Link para o comentário
Compartilhar em outros sites

Adorei a iniciativa, não tenho muita experiência com java, mas estou atualmente trabalhando com Acis 374 que esta muito bugada e estou buscando alternativas. Eu me candidato a participar deste projeto assim que você decidir qual revisão ira usar.

 

Github: https://github.com/kazuyabr

Bitbucket: https://bitbucket.org/kazuyabr/

Link para o comentário
Compartilhar em outros sites

 

Adorei a iniciativa, não tenho muita experiência com java, mas estou atualmente trabalhando com Acis 374 que esta muito bugada e estou buscando alternativas. Eu me candidato a participar deste projeto assim que você decidir qual revisão ira usar.

 

Github: https://github.com/kazuyabr

Bitbucket: https://bitbucket.org/kazuyabr/

Opa, toda ajuda será bem-vinda. Mas não necessariamente precisa saber de Java. Se souber bem lógica de programação, independe da linguagem, vai ser fácil, ainda mais para você que já trabalha com C#. Também tem partes em Python (quests), XML, HTML, SQL, Shell, Batch e até CSV no data pack. Coisas como organizar o código HTML (indentação, quebra de linha), padronização dos nomes dos arquivos, das pastas (nesses casos tem que atualizar no código, mas é muito fácil, é mais reconhecimento de onde encontrar).

Por enquanto estou analisando o código, vendo que terá que ser retirado, fazendo algumas anotações, testes e tal. Uma coisa que estava analisando são as consultas ao banco de dados. É muito código para fazer uma coisa simples, e, quando não dá certo, tem que gerar log disso verificando a configuração ENABLE_ALL_EXCEPTIONS, mas em alguns lugares não é verificado ou não gera log. Então estou criando uma classe para facilitar isso.

Ao invés de fazer assim:

public class Post
{
  public void insertindb(final CPost cp)
  {
    Connection con = null;
    try
    {
      con = L2DatabaseFactory.getInstance().getConnection(false);
      PreparedStatement statement = con.prepareStatement("INSERT INTO posts (post_id,post_owner_name,post_ownerid,post_date,post_topic_id,post_forum_id,post_txt) values (?,?,?,?,?,?,?)");
      statement.setInt(1, cp.postId);
      statement.setString(2, cp.postOwner);
      statement.setInt(3, cp.postOwnerId);
      statement.setLong(4, cp.postDate);
      statement.setInt(5, cp.postTopicId);
      statement.setInt(6, cp.postForumId);
      statement.setString(7, cp.postTxt);
      statement.execute();
      DatabaseUtils.close(statement);
      statement = null;
    }
    catch (final Exception e)
    {
      if (Config.ENABLE_ALL_EXCEPTIONS)
        e.printStackTrace();
      
      LOGGER.warn("error while saving new Post to db " + e);
    }
    finally
    {
      CloseUtil.close(con);
    }
  }
}

Faria somente assim:

public class Post {
  public boolean save() {
    return QueryBuilder.insert("post")
      .columns("id", "topic_id", "owner_id", "owner_name", "date", "text")
      .execute(this.id, this.topic_id, this.owner_id, this.owner_name, this.date, this.text);
  }
}

Para excluir:

public class Post {
  public boolean delete() {
    return QueryBuilder.delete("post").whereSafe("id").execute(this.id);
  }
}

Eu já criei essa classe (fora do projeto por enquanto), está funcionando perfeitamente, mas estou testando o desempenho. Por baixo está o JDBC. Logo postarei o source aqui. Mas como disse, ainda estou estudado técnica e metologias para utilizarmos. Estou pensando em utilizar o Trello e criar cartões para debater coisas que serão alteradas/removidas e controlar as tarefas.

Editado por vaneves
Otimização do código
Link para o comentário
Compartilhar em outros sites

Acredito que você poderia fazer algo melhor e mais alem, interface gráfica para as configs. Acredito que não seja difícil. Tem muitos que tem dificuldade em achar as  configs. indentar a própria IDE faz. 

Editado por Kabaite

Tudo depende de você mesmo!

Link para o comentário
Compartilhar em outros sites

 

Opa, toda ajuda será bem-vinda. Mas não necessariamente precisa saber de Java. Se souber bem lógica de programação, independe da linguagem, vai ser fácil, ainda mais para você que já trabalha com C#. Também tem partes em Python (quests), XML, HTML, SQL, Shell, Batch e até CSV no data pack. Coisas como organizar o código HTML (indentação, quebra de linha), padronização dos nomes dos arquivos, das pastas (nesses casos tem que atualizar no código, mas é muito fácil, é mais reconhecimento de onde encontrar).

Por enquanto estou analisando o código, vendo que terá que ser retirado, fazendo algumas anotações, testes e tal. Uma coisa que estava analisando são as consultas ao banco de dados. É muito código para fazer uma coisa simples, e, quando não dá certo, tem que gerar log disso verificando a configuração ENABLE_ALL_EXCEPTIONS, mas em alguns lugares não é verificado ou não gera log. Então estou criando uma classe para facilitar isso.

Ao invés de fazer assim:


public class Post
{
  public void insertindb(final CPost cp)
  {
    Connection con = null;
    try
    {
      con = L2DatabaseFactory.getInstance().getConnection(false);
      PreparedStatement statement = con.prepareStatement("INSERT INTO posts (post_id,post_owner_name,post_ownerid,post_date,post_topic_id,post_forum_id,post_txt) values (?,?,?,?,?,?,?)");
      statement.setInt(1, cp.postId);
      statement.setString(2, cp.postOwner);
      statement.setInt(3, cp.postOwnerId);
      statement.setLong(4, cp.postDate);
      statement.setInt(5, cp.postTopicId);
      statement.setInt(6, cp.postForumId);
      statement.setString(7, cp.postTxt);
      statement.execute();
      DatabaseUtils.close(statement);
      statement = null;
    }
    catch (final Exception e)
    {
      if (Config.ENABLE_ALL_EXCEPTIONS)
        e.printStackTrace();
      
      LOGGER.warn("error while saving new Post to db " + e);
    }
    finally
    {
      CloseUtil.close(con);
    }
  }
}

Faria somente assim:


public class Post {
  public boolean save() {
    return QueryBuilder.insert("post")
      .columns("id", "topic_id", "owner_name", "owner_id", "date", "text")
      .param(1, this.id)
      .param(2, this.topic_id)
      .param(3, this.owner_id)
      .param(4, this.owner_name)
      .param(5, this.date)
      .param(6, this.text)
      .execute();
  }
}

Para excluir:


public class Post {
  public boolean delete() {
    return QueryBuilder.delete("post").whereSafe("id").param(1, this.id).execute();
  }
}

Eu já criei essa classe (fora do projeto por enquanto), está funcionando perfeitamente, mas estou testando o desempenho. Por baixo está o JDBC. Logo postarei o source aqui. Mas como disse, ainda estou estudado técnica e metologias para utilizarmos. Estou pensando em utilizar o Trello e criar cartões para debater coisas que serão alteradas/removidas e controlar as tarefas.

nossa realmente facilitaria bastante. uma ideia que eu gostaria de implementar seria criar uma documentação para a revisão para que tambem os novos programadores possam saber o que faz o que dentro da revisão e não fiquem perdidos ao ler tanto código ou procurar na mão uma classe que controle por exemplo o enchant de skills.

Link para o comentário
Compartilhar em outros sites

 

Acredito que você poderia fazer algo melhor e mais alem, interface gráfica para as configs. Acredito que não seja difícil. Tem muitos que tem dificuldade em acha a configs.

para as configs (.properties) eu posso fazer um gerenciador que abre os properties e permite a alteração via GUI. isso realmente não é dificil.

Link para o comentário
Compartilhar em outros sites

 

Acredito que você poderia fazer algo melhor e mais alem, interface gráfica para as configs. Acredito que não seja difícil. Tem muitos que tem dificuldade em achar as  configs. indentar a própria IDE faz. 

Inicialmente a ideia é organizar o L2jFrozen e limpá-lo, deixando somente com o Interlude, sem mods. Ai criar algum mecanismo de adicionar mods facilmente (ao código-fonte antes de compilar). Estava até dando uma olhada no 

O Frozen vem até com NPC de GMShop dentro dele. Totalmente desnecessário, pois uma das coisas mais fácil é criar um NPC Multisell, usando apenas HTML e XML.

No futuro iremos criar eventos (mas não no core do projeto), NPCs, iremos criar um configurador, painel de administração, site... mas tudo a parte.

 

 

para as configs (.properties) eu posso fazer um gerenciador que abre os properties e permite a alteração via GUI. isso realmente não é dificil.

Excelente. Mas primeiro a remoção e organização dos configs. Porque não adianta criar uma interface, pois irá mudar. Atualmente a gente abre um config, vai vendo, ai dentro dele muda o assunto do config. Abre outro arquivo e tem relacionado. Por exemplo:

O arquivo gameserver/config/frozen/frozen.properties tem config permissão de GM e o arquivo gameserver/config/functions/access.properties também.

Link para o comentário
Compartilhar em outros sites

Eai cara tudo jóia?

Antes de qualquer coisa, começa arrancando o javolution dela! Eu cheguei a remover 95% dele, mas abandonei por outros fatores, que me fizeram ver o trabalho que eu teria.

Há dois testes que eu fiz na frozen, um deles foi spawnar uma boa quantia de monstros, o que gera um lag enorme.

O segundo é adicionar uma quantia boa de attack speed em dois personagens, e coloca-los para se atacarem, trava o jogo dos dois em questão de segundos.

Creio que são dois problemas graves no mass pvp, o famoso lag da frozen.

Link para o comentário
Compartilhar em outros sites

 

Eai cara tudo jóia?

Antes de qualquer coisa, começa arrancando o javolution dela! Eu cheguei a remover 95% dele, mas abandonei por outros fatores, que me fizeram ver o trabalho que eu teria.

A remoção dessa biblioteca nem é complicada quando se tem conhecimento do uso de Collections, demora poucas horas para fazer um trampo desse.

Parabéns @vaneves, o fórum está precisando de desenvolvimentos mesmo.

"Tente ser uma pessoa de valor , não de sucesso" - Albert Einstein

 

 

Link para o comentário
Compartilhar em outros sites

 

Inicialmente a ideia é organizar o L2jFrozen e limpá-lo, deixando somente com o Interlude, sem mods. Ai criar algum mecanismo de adicionar mods facilmente (ao código-fonte antes de compilar). Estava até dando uma olhada no 

O Frozen vem até com NPC de GMShop dentro dele. Totalmente desnecessário, pois uma das coisas mais fácil é criar um NPC Multisell, usando apenas HTML e XML.

No futuro iremos criar eventos (mas não no core do projeto), NPCs, iremos criar um configurador, painel de administração, site... mas tudo a parte.

 

Excelente. Mas primeiro a remoção e organização dos configs. Porque não adianta criar uma interface, pois irá mudar. Atualmente a gente abre um config, vai vendo, ai dentro dele muda o assunto do config. Abre outro arquivo e tem relacionado. Por exemplo:

O arquivo gameserver/config/frozen/frozen.properties tem config permissão de GM e o arquivo gameserver/config/functions/access.properties também.

faz sentido. bom a pergunta é já esta usando algum repositório? gostaria de começar a usar uma versão que vc esteja trabalhando seja via github, bitbucket ou qualquer gerenciador de versões.

Link para o comentário
Compartilhar em outros sites

 

Tem muitos que tem dificuldade em achar as  configs. indentar a própria IDE faz. 

A idéia é pensar também em quem quer ajudar o projeto, não somente usá-lo. O código organizado facilita a manutenção. Toda IDE indenda, mas não faz isso sozinho, alguém tem que fazer. Eu mesmo criei um script que faz isso e mais, com menos de 50 linhas. E toda IDE tem o Ctrl F para procurar dentro das configs.

 

Eai cara tudo jóia?

Antes de qualquer coisa, começa arrancando o javolution dela! Eu cheguei a remover 95% dele, mas abandonei por outros fatores, que me fizeram ver o trabalho que eu teria.

É ai que entra a ajuda colaborativa. Um faz 10%, outro faz 20% e por ai vai. Só definir bem os padrões (e documentá-los). Eu mesmo não pretendo trabalhar em 100%  do projeto, acho quenem consigo. As vezes esbarro em algo que tenho que pesquisar muito, mas isso que me dá tesão, algo novo, algo desafiador. 

 

 

Parabéns @vaneves, o fórum está precisando de desenvolvimentos mesmo.

Valeu. Eu havia trabalhado o ano passado em várias correções e melhorias de um projeto L2j ai. É código fechado, mesmo sem ter acesso ao código eu fiz instalador, corrigi informações no sql, criei site php e diversos NPCs. Mas os administradores do fórum do projeto moveram meus tópicos com os códigos/downloads para a area VIP (somente para pagos). Desanimei com o mercenarismo. Ai depois fui atrás de outros projetos (livres) e até agora o miozim é frozen. Mas estou aberto à sugestões. 

Mas apesar de trabalhar no frozen, irei postar muita coisa genérica de L2 e que, as vezes, vai servir para outras coisas (como o QueryBuilder).

Link para o comentário
Compartilhar em outros sites

 

bom a pergunta é já esta usando algum repositório? gostaria de começar a usar uma versão que vc esteja trabalhando seja via github, bitbucket ou qualquer gerenciador de versões.

Acabei de criar um time no GitHub e um projeto. Primeira iremos trabalhar nas ideias (o que será feito, como será feito, qual a prioridade e por quem será feito). O projeto tem as seguintes colunas:

  • Planejamento: aqui serão sugestões, debate e definições.
  • A Fazer: depois de definido o que fazer vem para essa coluna, onde ficará na fila até alguém "pegar"
  • Fazendo: ao pegar e enquanto estiver fazendo, vai estar aqui
  • Feito: quando estiver finalizado

Essas 4 colunas são mínimas, mas pode ter mais, mas vai depender da quantidade de pessoas envolvidas. Tipo, uma coluna onde tu que for feito é revisado por outra pessoa.

O tempo de dedicação ao projeto vai de cada um, pode ser uma vez por semana, uma vez por mês ou até mesmo uma contribuição única. Só não é bom pegar algo para fazer e enrolar. Se não tiver tempo, pode "voltar" o cartão e comunicar a galera.

Iremos abrir um canal de comunicação (Slack ou Gitter), assim não ficamos floodando o fórum aqui. Por enquanto não é flood porque está havendo debates e divulgação, para mais pessoas possam ajudar.  Mesmo que a pessoa não participe diretamente no código, vai poder participar desse canal, a opinião da comunidade é importante. 

https://github.com/orgs/l2dife/projects/1

Link para o comentário
Compartilhar em outros sites

 

Antes de qualquer coisa, começa arrancando o javolution dela!

Hoje cedo fiz uns testes (fora do projeto) com ArrayList, HashSet, HashMap e as classes do javolution FastMap e FastList. Sendo que destas citadas somente a HashMap e FastMap (javolution) trabalham com índices não sequenciais. Já a ArrayList, HashSet e FastList (javolution) trabalham apenas com índices sequenciais. Rapaz, a diferença foi gritante. 

Os testes foram o seguinte, percorrer de 3 à 199.999 (200 mil), preencher uma lista com uma instância de um objeto. O objeto possuía 2  propriedades: id e name. A id era o índice a name era " Texto do exemplo A "+ i ou "B" no outro exemplo. Depois percorria novamente essa lista e coloca o objeto em uma variável utilizando o .get(id).

 --------------------------------
| HashMap       | 0,062 segundos |
| FastMap       | 0,094 segundos |
|--------------------------------|
| HashMap       | 0,067 segundos |
| FastMap       | 0,098 segundos |
|--------------------------------|
| HashMap       | 0,043 segundos |
| FastMap       | 0,062 segundos |
|--------------------------------|
| HashMap       | 0,017 segundos |
| FastMap       | 0,025 segundos |
|--------------------------------|
| HashMap       | 0,052 segundos |
| FastMap       | 0,061 segundos |
|--------------------------------|
| HashMap       | 0,019 segundos |
| FastMap       | 0,056 segundos |
|--------------------------------|
| HashMap       | 0,036 segundos |
| FastMap       | 0,085 segundos |
|--------------------------------|
| HashMap       | 0,017 segundos |
| FastMap       | 0,042 segundos |
|--------------------------------|
| HashMap       | 0,017 segundos |
| FastMap       | 0,040 segundos |
|--------------------------------|
| HashMap       | 0,017 segundos |
| FastMap       | 0,044 segundos |
 --------------------------------

Repeti o teste várias vezes, claro. O resultado foi esse ai, onde o HashMap (nativo o do java) é muito mais rápido.

Depois refiz os testes, só que dessa vez com classes sequenciais e percorrendo de 0 à 19.999 (20 mil). Esse me surpreendeu mais, tanto que repeti várias vezes:

 --------------------------------
| ArrayList     | 0,015 segundos |
| HashSet       | 0,015 segundos |
| FastList      | 1,325 segundos |
|--------------------------------|
| ArrayList     | 0,002 segundos |
| HashSet       | 0,016 segundos |
| FastList      | 1,275 segundos |
|--------------------------------|
| ArrayList     | 0,002 segundos |
| HashSet       | 0,000 segundos |
| FastList      | 0,686 segundos |
|--------------------------------|
| ArrayList     | 0,002 segundos |
| HashSet       | 0,005 segundos |
| FastList      | 0,607 segundos |
|--------------------------------|
| ArrayList     | 0,002 segundos |
| HashSet       | 0,000 segundos |
| FastList      | 0,622 segundos |
|--------------------------------|
| ArrayList     | 0,001 segundos |
| HashSet       | 0,003 segundos |
| FastList      | 0,597 segundos |
|--------------------------------|
| ArrayList     | 0,000 segundos |
| HashSet       | 0,000 segundos |
| FastList      | 0,621 segundos |
|--------------------------------|
| ArrayList     | 0,000 segundos |
| HashSet       | 0,000 segundos |
| FastList      | 0,625 segundos |
|--------------------------------|
| ArrayList     | 0,000 segundos |
| HashSet       | 0,001 segundos |
| FastList      | 0,612 segundos |
|--------------------------------|
| ArrayList     | 0,001 segundos |
| HashSet       | 0,004 segundos |
| FastList      | 0,595 segundos |
 --------------------------------

Com certeza isso é uma das primeiras coisas que trabalharemos. Mas, será feito por partes. Quando necessário buscar um item pelo Id e ele não for sequencial, utilizar a HashMap. Mas quando for apenas listar (sem busca posterior pelo), utilizar o ArrayList ou HashSet. Detalhe que o HashSet não tem .get(), então nos testes usei um foreach para cada vez que eu percorria (20 mil).

Os testes foram feito em um computador Intel i7-4800MQ, 2.7GHx, 16GiB de RAM, Windows 10 x64, utilizando a versão 5.5.1 do Javolution (que vem no Frozen) e JDK 8u144.

Editado por vaneves
Diminui a tabela
Link para o comentário
Compartilhar em outros sites

 

Acabei de criar um time no GitHub e um projeto. Primeira iremos trabalhar nas ideias (o que será feito, como será feito, qual a prioridade e por quem será feito). O projeto tem as seguintes colunas:

  • Planejamento: aqui serão sugestões, debate e definições.
  • A Fazer: depois de definido o que fazer vem para essa coluna, onde ficará na fila até alguém "pegar"
  • Fazendo: ao pegar e enquanto estiver fazendo, vai estar aqui
  • Feito: quando estiver finalizado

Essas 4 colunas são mínimas, mas pode ter mais, mas vai depender da quantidade de pessoas envolvidas. Tipo, uma coluna onde tu que for feito é revisado por outra pessoa.

O tempo de dedicação ao projeto vai de cada um, pode ser uma vez por semana, uma vez por mês ou até mesmo uma contribuição única. Só não é bom pegar algo para fazer e enrolar. Se não tiver tempo, pode "voltar" o cartão e comunicar a galera.

Iremos abrir um canal de comunicação (Slack ou Gitter), assim não ficamos floodando o fórum aqui. Por enquanto não é flood porque está havendo debates e divulgação, para mais pessoas possam ajudar.  Mesmo que a pessoa não participe diretamente no código, vai poder participar desse canal, a opinião da comunidade é importante. 

https://github.com/orgs/l2dife/projects/1

projeto invisivel, não consigo acessa-lo. se for um projeto que esta privativo no github me de permissão de acesso http://github.com/kazuyabr do contrario me auxilie para que eu possa ver e dar um FORK no projeto.

Link para o comentário
Compartilhar em outros sites

 

projeto invisivel, não consigo acessa-lo. se for um projeto que esta privativo no github me de permissão de acesso http://github.com/kazuyabr do contrario me auxilie para que eu possa ver e dar um FORK no projeto.

É um projeto, não um repositório (é tipo kanban) rsrs ainda não criei os repositórios porquê, como eu disse, ainda há o que debater antes de começar a por a mão na massa. Inclusive, eu estava olhando, tem o projeto https://github.com/L2jBrasil/Server-Interlude/. Dependendo de como ele estiver, vou olhar melhor, é mais viável ajudá-lo do que limpar o frozen. É muito parecido com o frozen em alguns aspectos e tem gente trabalhando nele (e precisando de ajuda).

@Tayran.JavaDev sabe nos dizer como está esse projeto? É só otimização ou está incompleto? Eu havia olhado o L2jServer, mas o Interlude está parado e incompleto.

 

Link para o comentário
Compartilhar em outros sites

 

É um projeto, não um repositório (é tipo kanban) rsrs ainda não criei os repositórios porquê, como eu disse, ainda há o que debater antes de começar a por a mão na massa. Inclusive, eu estava olhando, tem o projeto https://github.com/L2jBrasil/Server-Interlude/. Dependendo de como ele estiver, vou olhar melhor, é mais viável ajudá-lo do que limpar o frozen. É muito parecido com o frozen em alguns aspectos e tem gente trabalhando nele (e precisando de ajuda).

@Tayran.JavaDev sabe nos dizer como está esse projeto? É só otimização ou está incompleto? Eu havia olhado o L2jServer, mas o Interlude está parado e incompleto.

 

Que bom que se interessou em ajudar, eu acho muito mais interessante dar continuidade na L2JServer do que pegar L2JFrozen para mexer, e no fim quando chegar em um projeto bom e estável você terá usado como base o que é a base de todas e não tem herança de nenhum outro projeto desses atuais.

Nosso projeto L2JBrasil atualmente encontra-se fechado por que está passando por mudanças e por enquanto não faz sentido publicar uma revisão, em breve estarei postando revisão para teste e continuando o projeto Interlude usando como base a última L2JServer, a gente tava dando continuidade ao projeto de 2011 mas não estava sendo interessante para nós ficar consertando erros que vieram depois da L2JServer, então a continuidade agora é da L2JServer limpa, se você tem interesse em trabalhar com a Base principal que é a L2JServer será interessante nos juntarmos para fazer isso, por que já estamos fazendo.

"Tente ser uma pessoa de valor , não de sucesso" - Albert Einstein

 

 

Link para o comentário
Compartilhar em outros sites

 

Hoje cedo fiz uns testes (fora do projeto) com ArrayList, HashSet, HashMap e as classes do javolution FastMap e FastList. Sendo que destas citadas somente a HashMap e FastMap (javolution) trabalham com índices não sequenciais. Já a ArrayList, HashSet e FastList (javolution) trabalham apenas com índices sequenciais. Rapaz, a diferença foi gritante. 

Os testes foram o seguinte, percorrer de 3 à 199.999 (200 mil), preencher uma lista com uma instância de um objeto. O objeto possuía 2  propriedades: id e name. A id era o índice a name era " Texto do exemplo A "+ i ou "B" no outro exemplo. Depois percorria novamente essa lista e coloca o objeto em uma variável utilizando o .get(id).


 --------------------------------
| HashMap       | 0,062 segundos |
| FastMap       | 0,094 segundos |
|--------------------------------|
| HashMap       | 0,067 segundos |
| FastMap       | 0,098 segundos |
|--------------------------------|
| HashMap       | 0,043 segundos |
| FastMap       | 0,062 segundos |
|--------------------------------|
| HashMap       | 0,017 segundos |
| FastMap       | 0,025 segundos |
|--------------------------------|
| HashMap       | 0,052 segundos |
| FastMap       | 0,061 segundos |
|--------------------------------|
| HashMap       | 0,019 segundos |
| FastMap       | 0,056 segundos |
|--------------------------------|
| HashMap       | 0,036 segundos |
| FastMap       | 0,085 segundos |
|--------------------------------|
| HashMap       | 0,017 segundos |
| FastMap       | 0,042 segundos |
|--------------------------------|
| HashMap       | 0,017 segundos |
| FastMap       | 0,040 segundos |
|--------------------------------|
| HashMap       | 0,017 segundos |
| FastMap       | 0,044 segundos |
 --------------------------------

Repeti o teste várias vezes, claro. O resultado foi esse ai, onde o HashMap (nativo o do java) é muito mais rápido.

Depois refiz os testes, só que dessa vez com classes sequenciais e percorrendo de 0 à 19.999 (20 mil). Esse me surpreendeu mais, tanto que repeti várias vezes:


 --------------------------------
| ArrayList     | 0,015 segundos |
| HashSet       | 0,015 segundos |
| FastList      | 1,325 segundos |
|--------------------------------|
| ArrayList     | 0,002 segundos |
| HashSet       | 0,016 segundos |
| FastList      | 1,275 segundos |
|--------------------------------|
| ArrayList     | 0,002 segundos |
| HashSet       | 0,000 segundos |
| FastList      | 0,686 segundos |
|--------------------------------|
| ArrayList     | 0,002 segundos |
| HashSet       | 0,005 segundos |
| FastList      | 0,607 segundos |
|--------------------------------|
| ArrayList     | 0,002 segundos |
| HashSet       | 0,000 segundos |
| FastList      | 0,622 segundos |
|--------------------------------|
| ArrayList     | 0,001 segundos |
| HashSet       | 0,003 segundos |
| FastList      | 0,597 segundos |
|--------------------------------|
| ArrayList     | 0,000 segundos |
| HashSet       | 0,000 segundos |
| FastList      | 0,621 segundos |
|--------------------------------|
| ArrayList     | 0,000 segundos |
| HashSet       | 0,000 segundos |
| FastList      | 0,625 segundos |
|--------------------------------|
| ArrayList     | 0,000 segundos |
| HashSet       | 0,001 segundos |
| FastList      | 0,612 segundos |
|--------------------------------|
| ArrayList     | 0,001 segundos |
| HashSet       | 0,004 segundos |
| FastList      | 0,595 segundos |
 --------------------------------

Com certeza isso é uma das primeiras coisas que trabalharemos. Mas, será feito por partes. Quando necessário buscar um item pelo Id e ele não for sequencial, utilizar a HashMap. Mas quando for apenas listar (sem busca posterior pelo), utilizar o ArrayList ou HashSet. Detalhe que o HashSet não tem .get(), então nos testes usei um foreach para cada vez que eu percorria (20 mil).

Os testes foram feito em um computador Intel i7-4800MQ, 2.7GHx, 16GiB de RAM, Windows 10 x64, utilizando a versão 5.5.1 do Javolution (que vem no Frozen) e JDK 8u144.

É gritante mesmo a diferença de desempenho, a javolution já foi necessária no passado quando o java não tinha as coleções igual são hoje, hoje em dia elas são inúteis, é esse tipo de coisa que poucos desenvolvedores de L2J conseguem encher e evoluir o código de acordo conforme o java evolui, meu plano é bem parecido com o seu, pretendo atualizar o código aplicando as novidades do Java, por que o Java evolui e o L2J continua mantendo códigos legados.

"Tente ser uma pessoa de valor , não de sucesso" - Albert Einstein

 

 

Link para o comentário
Compartilhar em outros sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Visitante
Responder

×   Você colou conteúdo com formatação.   Remover formatação

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Processando...
  • Registre-se

    Faça parte da maior e  mais antigas comunidades sobre Lineage2 da América Latina.





  • Patrocinadores

  • Quem Está Navegando

    • Nenhum usuário registrado visualizando esta página.
  • Posts

    • Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?    
    • muchas gracias muy lindos NPC 🙂
    • relaxa jovem gafanhoto, testa as quests. e posTa os erros indesejaveis.  
    • Se alguém pudesse me ensinar como codificar as missões, eu ficaria feliz em fazer isso sozinho ou pelo menos ajudar. Eu realmente quero jogar em um servidor onde todas as quests funcionem bem e melhor ainda se você puder fazer quests customizadas!
    • mas no interlude, nem todas as quests de class,  vai mostrar onde tem que ir, ate o reborn nao mostrava quando era interlude, só mostrou depois que eles colocaram client classic pra rodar, e ficou melhor ainda quando virou hellbound em diante, mas ha sim alguma chance de modificar isso direto no script para fazer igualmente, só basta te um pouco de paciencia e persistencia exato
    • 408_PathToElvenwizard dá Orion eu tive que mexer tbm, até modifiquei e consegui deixar ela igual do Classic, com a seta e a marcação no mapa. (não retail IL) Dá pra importar py de várias revs, o foda é que não da regular as quest py através do debug em tempo real, pelo menos eu não consegui rsrs
    • Hasta el momento todas las QUESTS son completables si te guias con un tutorial de youtube. El problema es que tienen bugs de locacion y de subquests que no avanzan o no te marcan correctamente a donde ir en el mapa, cosa que en Retail si se ve como corresponde.
    • estranho, mas pelo menos a galera nunca reclamo das quests quando tinha aberto 5x, geral fez class primeira e segunda job, poucos que compraram a class
    • en RUSaCis-3.5 data pack, las Quests estan en formato .java y son diferentes a como estan redactadas en jOrion y jFrozen 1.5 (ProyectX) package net.sf.l2j.gameserver.scripting.quest; import net.sf.l2j.commons.random.Rnd; import net.sf.l2j.gameserver.enums.Paperdoll; import net.sf.l2j.gameserver.enums.QuestStatus; import net.sf.l2j.gameserver.enums.actors.ClassId; import net.sf.l2j.gameserver.model.actor.Creature; import net.sf.l2j.gameserver.model.actor.Npc; import net.sf.l2j.gameserver.model.actor.Player; import net.sf.l2j.gameserver.network.serverpackets.SocialAction; import net.sf.l2j.gameserver.scripting.QuestState; public class Q224_TestOfSagittarius extends SecondClassQuest { private static final String QUEST_NAME = "Q224_TestOfSagittarius"; // Items private static final int BERNARD_INTRODUCTION = 3294; private static final int HAMIL_LETTER_1 = 3295; private static final int HAMIL_LETTER_2 = 3296; private static final int HAMIL_LETTER_3 = 3297; private static final int HUNTER_RUNE_1 = 3298; private static final int HUNTER_RUNE_2 = 3299; private static final int TALISMAN_OF_KADESH = 3300; private static final int TALISMAN_OF_SNAKE = 3301; private static final int MITHRIL_CLIP = 3302; private static final int STAKATO_CHITIN = 3303; private static final int REINFORCED_BOWSTRING = 3304; private static final int MANASHEN_HORN = 3305; private static final int BLOOD_OF_LIZARDMAN = 3306; private static final int CRESCENT_MOON_BOW = 3028; private static final int WOODEN_ARROW = 17; // Rewards private static final int MARK_OF_SAGITTARIUS = 3293; // NPCs private static final int BERNARD = 30702; private static final int HAMIL = 30626; private static final int SIR_ARON_TANFORD = 30653; private static final int VOKIAN = 30514; private static final int GAUEN = 30717; // Monsters private static final int ANT = 20079; private static final int ANT_CAPTAIN = 20080; private static final int ANT_OVERSEER = 20081; private static final int ANT_RECRUIT = 20082; private static final int ANT_PATROL = 20084; private static final int ANT_GUARD = 20086; private static final int NOBLE_ANT = 20089; private static final int NOBLE_ANT_LEADER = 20090; private static final int BREKA_ORC_SHAMAN = 20269; private static final int BREKA_ORC_OVERLORD = 20270; private static final int MARSH_STAKATO_WORKER = 20230; private static final int MARSH_STAKATO_SOLDIER = 20232; private static final int MARSH_STAKATO_DRONE = 20234; private static final int MARSH_SPIDER = 20233; private static final int ROAD_SCAVENGER = 20551; private static final int MANASHEN_GARGOYLE = 20563; private static final int LETO_LIZARDMAN = 20577; private static final int LETO_LIZARDMAN_ARCHER = 20578; private static final int LETO_LIZARDMAN_SOLDIER = 20579; private static final int LETO_LIZARDMAN_WARRIOR = 20580; private static final int LETO_LIZARDMAN_SHAMAN = 20581; private static final int LETO_LIZARDMAN_OVERLORD = 20582; private static final int SERPENT_DEMON_KADESH = 27090; public Q224_TestOfSagittarius() { super(224, "Test Of Sagittarius"); setItemsIds(BERNARD_INTRODUCTION, HAMIL_LETTER_1, HAMIL_LETTER_2, HAMIL_LETTER_3, HUNTER_RUNE_1, HUNTER_RUNE_2, TALISMAN_OF_KADESH, TALISMAN_OF_SNAKE, MITHRIL_CLIP, STAKATO_CHITIN, REINFORCED_BOWSTRING, MANASHEN_HORN, BLOOD_OF_LIZARDMAN, CRESCENT_MOON_BOW); addQuestStart(BERNARD); addTalkId(BERNARD, HAMIL, SIR_ARON_TANFORD, VOKIAN, GAUEN); addMyDying(ANT, ANT_CAPTAIN, ANT_OVERSEER, ANT_RECRUIT, ANT_PATROL, ANT_GUARD, NOBLE_ANT, NOBLE_ANT_LEADER, BREKA_ORC_SHAMAN, BREKA_ORC_OVERLORD, MARSH_STAKATO_WORKER, MARSH_STAKATO_SOLDIER, MARSH_STAKATO_DRONE, MARSH_SPIDER, ROAD_SCAVENGER, MANASHEN_GARGOYLE, LETO_LIZARDMAN, LETO_LIZARDMAN_ARCHER, LETO_LIZARDMAN_SOLDIER, LETO_LIZARDMAN_WARRIOR, LETO_LIZARDMAN_SHAMAN, LETO_LIZARDMAN_OVERLORD, SERPENT_DEMON_KADESH); } @Override public String onAdvEvent(String event, Npc npc, Player player) { String htmltext = event; QuestState st = player.getQuestList().getQuestState(QUEST_NAME); if (st == null) return htmltext; // BERNARD if (event.equalsIgnoreCase("30702-04.htm")) { st.setState(QuestStatus.STARTED); st.setCond(1); playSound(player, SOUND_ACCEPT); giveItems(player, BERNARD_INTRODUCTION, 1); if (giveDimensionalDiamonds39(player)) htmltext = "30702-04a.htm"; } // HAMIL else if (event.equalsIgnoreCase("30626-03.htm")) { st.setCond(2); playSound(player, SOUND_MIDDLE); takeItems(player, BERNARD_INTRODUCTION, 1); giveItems(player, HAMIL_LETTER_1, 1); } else if (event.equalsIgnoreCase("30626-07.htm")) { st.setCond(5); playSound(player, SOUND_MIDDLE); takeItems(player, HUNTER_RUNE_1, 10); giveItems(player, HAMIL_LETTER_2, 1); } // SIR_ARON_TANFORD else if (event.equalsIgnoreCase("30653-02.htm")) { st.setCond(3); playSound(player, SOUND_MIDDLE); takeItems(player, HAMIL_LETTER_1, 1); } // VOKIAN else if (event.equalsIgnoreCase("30514-02.htm")) { st.setCond(6); playSound(player, SOUND_MIDDLE); takeItems(player, HAMIL_LETTER_2, 1); } return htmltext; } @Override public String onTalk(Npc npc, Player player) { String htmltext = getNoQuestMsg(); QuestState st = player.getQuestList().getQuestState(QUEST_NAME); if (st == null) return htmltext; switch (st.getState()) { case CREATED: if (player.getClassId() != ClassId.ROGUE && player.getClassId() != ClassId.ELVEN_SCOUT && player.getClassId() != ClassId.ASSASSIN) htmltext = "30702-02.htm"; else if (player.getStatus().getLevel() < 39) htmltext = "30702-01.htm"; else htmltext = "30702-03.htm"; break; case STARTED: int cond = st.getCond(); switch (npc.getNpcId()) { case BERNARD: htmltext = "30702-05.htm"; break; case HAMIL: if (cond == 1) htmltext = "30626-01.htm"; else if (cond == 2 || cond == 3) htmltext = "30626-04.htm"; else if (cond == 4) htmltext = "30626-05.htm"; else if (cond > 4 && cond < 8) htmltext = "30626-08.htm"; else if (cond == 8) { htmltext = "30626-09.htm"; st.setCond(9); playSound(player, SOUND_MIDDLE); takeItems(player, HUNTER_RUNE_2, 10); giveItems(player, HAMIL_LETTER_3, 1); } else if (cond > 8 && cond < 12) htmltext = "30626-10.htm"; else if (cond == 12) { htmltext = "30626-11.htm"; st.setCond(13); playSound(player, SOUND_MIDDLE); } else if (cond == 13) htmltext = "30626-12.htm"; else if (cond == 14) { htmltext = "30626-13.htm"; takeItems(player, BLOOD_OF_LIZARDMAN, -1); takeItems(player, CRESCENT_MOON_BOW, 1); takeItems(player, TALISMAN_OF_KADESH, 1); giveItems(player, MARK_OF_SAGITTARIUS, 1); rewardExpAndSp(player, 54726, 20250); player.broadcastPacket(new SocialAction(player, 3)); playSound(player, SOUND_FINISH); st.exitQuest(false); } break; case SIR_ARON_TANFORD: if (cond == 2) htmltext = "30653-01.htm"; else if (cond > 2) htmltext = "30653-03.htm"; break; case VOKIAN: if (cond == 5) htmltext = "30514-01.htm"; else if (cond == 6) htmltext = "30514-03.htm"; else if (cond == 7) { htmltext = "30514-04.htm"; st.setCond(8); playSound(player, SOUND_MIDDLE); takeItems(player, TALISMAN_OF_SNAKE, 1); } else if (cond > 7) htmltext = "30514-05.htm"; break; case GAUEN: if (cond == 9) { htmltext = "30717-01.htm"; st.setCond(10); playSound(player, SOUND_MIDDLE); takeItems(player, HAMIL_LETTER_3, 1); } else if (cond == 10) htmltext = "30717-03.htm"; else if (cond == 11) { htmltext = "30717-02.htm"; st.setCond(12); playSound(player, SOUND_MIDDLE); takeItems(player, MANASHEN_HORN, 1); takeItems(player, MITHRIL_CLIP, 1); takeItems(player, REINFORCED_BOWSTRING, 1); takeItems(player, STAKATO_CHITIN, 1); giveItems(player, CRESCENT_MOON_BOW, 1); giveItems(player, WOODEN_ARROW, 10); } else if (cond > 11) htmltext = "30717-04.htm"; break; } break; case COMPLETED: htmltext = getAlreadyCompletedMsg(); break; } return htmltext; } @Override public void onMyDying(Npc npc, Creature killer) { final Player player = killer.getActingPlayer(); final QuestState st = checkPlayerState(player, npc, QuestStatus.STARTED); if (st == null) return; switch (npc.getNpcId()) { case ANT: case ANT_CAPTAIN: case ANT_OVERSEER: case ANT_RECRUIT: case ANT_PATROL: case ANT_GUARD: case NOBLE_ANT: case NOBLE_ANT_LEADER: if (st.getCond() == 3 && dropItems(player, HUNTER_RUNE_1, 1, 10, 500000)) st.setCond(4); break; case BREKA_ORC_SHAMAN: case BREKA_ORC_OVERLORD: if (st.getCond() == 6 && dropItems(player, HUNTER_RUNE_2, 1, 10, 500000)) { st.setCond(7); giveItems(player, TALISMAN_OF_SNAKE, 1); } break; case MARSH_STAKATO_WORKER: case MARSH_STAKATO_SOLDIER: case MARSH_STAKATO_DRONE: if (st.getCond() == 10 && dropItems(player, STAKATO_CHITIN, 1, 1, 100000) && player.getInventory().hasItems(MANASHEN_HORN, MITHRIL_CLIP, REINFORCED_BOWSTRING)) st.setCond(11); break; case MARSH_SPIDER: if (st.getCond() == 10 && dropItems(player, REINFORCED_BOWSTRING, 1, 1, 100000) && player.getInventory().hasItems(MANASHEN_HORN, MITHRIL_CLIP, STAKATO_CHITIN)) st.setCond(11); break; case ROAD_SCAVENGER: if (st.getCond() == 10 && dropItems(player, MITHRIL_CLIP, 1, 1, 100000) && player.getInventory().hasItems(MANASHEN_HORN, REINFORCED_BOWSTRING, STAKATO_CHITIN)) st.setCond(11); break; case MANASHEN_GARGOYLE: if (st.getCond() == 10 && dropItems(player, MANASHEN_HORN, 1, 1, 100000) && player.getInventory().hasItems(REINFORCED_BOWSTRING, MITHRIL_CLIP, STAKATO_CHITIN)) st.setCond(11); break; case LETO_LIZARDMAN: case LETO_LIZARDMAN_ARCHER: case LETO_LIZARDMAN_SOLDIER: case LETO_LIZARDMAN_WARRIOR: case LETO_LIZARDMAN_SHAMAN: case LETO_LIZARDMAN_OVERLORD: if (st.getCond() == 13) { if (((player.getInventory().getItemCount(BLOOD_OF_LIZARDMAN) - 120) * 5) > Rnd.get(100)) { playSound(player, SOUND_BEFORE_BATTLE); takeItems(player, BLOOD_OF_LIZARDMAN, -1); addSpawn(SERPENT_DEMON_KADESH, player, false, 300000, true); } else dropItemsAlways(player, BLOOD_OF_LIZARDMAN, 1, 0); } break; case SERPENT_DEMON_KADESH: if (st.getCond() == 13) { if (player.getInventory().getItemIdFrom(Paperdoll.RHAND) == CRESCENT_MOON_BOW) { st.setCond(14); playSound(player, SOUND_MIDDLE); giveItems(player, TALISMAN_OF_KADESH, 1); } else addSpawn(SERPENT_DEMON_KADESH, player, false, 300000, true); } break; } } }  
×
×
  • Criar Novo...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.