Coder Social home page Coder Social logo

apollo's Introduction

Apollo

Apollo is a high-performance, modular RuneScape emulator with a collection of utilities for managing data files and plugins.

Developer information

Most discussion related to the development of Apollo happens on our Discord. If you have a problem and can't get in touch with anyone, create a GitHub issue. If making a pull request, please make sure all tests are still passing after making your changes, and that your code style is consistent with the rest of Apollo.

Getting started

Apollo uses the gradle build tool, so this must be installed in order to build Apollo.

  1. Run gradle build in the Apollo directory to download dependencies and build Apollo.
  2. Place the full cache of the client revision you want to target in data/fs/[revision] - by default Apollo is compatible with the 377 revision, so the cache would be placed in data/fs/377.
  3. Place an rsa.pem file containing the RSA private key to be used by the server in data/. Apollo comes with a generator that will write the pem file to the appropriate location - see org.apollo.util.tools.RsaKeyGenerator. If you use the generator you must replace the public key and modulus used by your client (the tool will print the new values).
  4. If you are targeting a different client revision, run the EquipmentUpdater (in org.apollo.cache.tools), which identifies the appropriate combat skill levels required to wear equipment. Note that you may have to update the tool yourself if the revision contains equipment not found in 377.

Apollo is now ready, and can be started using gradle run. You may wish to change the player serializer defined in login.xml - by default player data is not saved, and all users who log in will have administrator rights.

Contributing

Please see contributing to Apollo.

Acknowledgements

We'd like to thank the list of service providers/development tool vendors below for offering their products to the Apollo project free of charge.


YourKit

YourKit supports open source projects with its full-featured Java Profiler. YourKit, LLC is the creator of YourKit Java Profiler and YourKit .NET Profiler, innovative and intelligent tools for profiling Java and .NET applications.

Travis CI is a Continuous Integration platform that allows for setup of automated testing with minimal configuration.

apollo's People

Contributors

ahmedsakr avatar arham4 avatar arinhouck avatar aymericdu avatar bugcrusher avatar cfoust avatar charlesvaneenoo avatar chivvon avatar cubeee avatar dependabot-preview[bot] avatar garyttierney avatar greghib avatar j-mathias avatar jeremy-excersion avatar kylestev avatar lare96 avatar lmctruck30 avatar major- avatar nikkiii avatar pheq avatar promises avatar rmcmk avatar shubheksha avatar stevesoltys avatar subby avatar tehjayden avatar tlf30 avatar wizardjesse1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

apollo's Issues

Wielding weapon spazzing

When you currently try to equip the same weapon that you're currently wearing like a whip for example it will spaz out the weapon in the inventory for a quick second.

This does not happen with other things like hats,capes,shields, etc... only weapons

Add tests.

How do you plan to make releases without automated tests? This is your chance to change the private server scene for the better so I must insist that you add testing.

Equipping Item's does not work

I've tried several checks in the EquipItemHandler class and it seems like its not even sending it at all not sure if anyone else has had problems with this.

Move revision 317 release into another repository

Apollo adds a lot of unnecessary (and frankly confusing to some) bloat with the current hack-job implementation of multi-revision support. I say hack-job as it is not actual multi-revision support which people think of (running 1 server, connecting to it via multiple revision clients).

Don't get me wrong, Apollo's multi-revision idea is nice,... but it isn't ideal.

There are several alternative solutions that can be brought to the table that will work much nicely.

  • The most simple, drop multi-revision support entirely and emulate one revision
    • Improves code flow and readability
    • No (more) issues when writing content for 377 that (will ultimately have to exist in the 317 revision as well) won't work because of compatibility issues. Even by 'disabling' content for certain revisions that aren't compatible will add an unnecessary layer of complexity to content code -- which we don't want.
    • Limits the scope to where certain bugs/issues may occur (ahem the sync [or not sync] related movement issue)
    • However... we also run into some issues with this design. Designing the server around one revision ultimately makes the core lack certain functions and necessities to let other revisions work (if someone were to convert the stock revision to another)
  • Create multiple revision independent Apollo branches (or versions)
    • Not ideal for developers
  • Or the best solution, in my opinion. Add support for loading 3rd party revisions without the need to hack anything on to the core
    • Abstract the core and provide it with the necessities to support a wide array of potential revisions
    • Similar to the way content and core separation was intended to be done, dragging and dropping revisions in as a dependency or creating some kind of Apollo package manager for releases (for their content and release specific code)

Discuss, ask questions, propose your own solution or otherwise

Update POM

maven-compiler-plugin (3.1)
commons-compress (1.8.1)
netty-all (4.0.20.Final)

Private message issue not sending

Issue in the plugin where message.compressed_message should be changed to message.compressed_chat

------ This will fix it

require 'java'

java_import 'org.apollo.game.message.impl.ForwardPrivateChatMessage'
java_import 'org.apollo.game.model.World'
java_import 'org.apollo.game.model.setting.PrivacyState'

on :message, :private_chat do |ctx, player, message|
friend = $world.get_player(message.username)
friend.send(ForwardPrivateChatMessage.new(player.username, player.privilege_level, message.compressed_chat)) if interaction_permitted(player, friend)
end

Checks if the sender is permitted to interact with the friend they have added:

def interaction_permitted(sender, friend)
if friend == nil || friend.has_ignored(sender.username)
return false
end

return friend.friends_with(sender.username) ? friend.friend_privacy != PrivacyState::OFF : friend.friend_privacy == PrivacyState::ON
end

Odd error with MessageHandlerChainSet, not sure if because Eclipse

public <M extends Message> boolean notify(Player player, M message) {
    Deque<Class<? extends Message>> classes = this.classes.computeIfAbsent(message.getClass(),
            this::getMessageClasses);

    for (Class<? extends Message> type : classes) {
        MessageHandlerChain<? super M> chain = (MessageHandlerChain<? super M>) chains.get(type);

        if (chain != null && !chain.notify(player, message)) {
            return false;
        }
    }

    return true;
}

This line in particular

    Deque<Class<? extends Message>> classes = this.classes.computeIfAbsent(message.getClass(),
            this::getMessageClasses);

What fixes it is

    Deque<Class<? extends Message>> classes = this.classes.computeIfAbsent(message.getClass(),
            it -> getMessageClasses(it));

Which doesn't make sense because they're exactly the same thing

Typo in documentation- Mob.java

Not really an "Issue" but still something that is bothering me, found here:

public final List<Player> getLocalPlayerList() {

[dialogues] NPC head animations

NPC head animations do not work on both 377 and 317. When using the dialogue plugin, only a static image of the NPC head is shown.

Should this be fixed plugin-wise or in core?

Breaking the Chain

Apollo, as you may know, employs a handler chain for most content where a message is propagated downward until it meets its destination handler and the message is handled there. This design has a lot of benefits, like employing methods of validation to stop message propagation. However, in the scripting system it fragments logic between various scripts and even has issues with plugin dependency in situations where handler priority is not properly sorted. For this case I state the usage of items for quests versus other functions where a quest plugin may handle the logic for an item for a quest but in cases where other functionality needs to be deployed there have to be extraneous cases where conditions are placed to specifically state which handler has priority. Also the design does not appropriately manage future content implementations without having to take into account special considerations which reference to the cited example. The design also fails to keep logic centralized and in an essence of the fact of the idea, 'clean'. However I think the plugin system also fails this purpose, even if that purpose isn't intended I feel as if the plugin system fails in assisting the developer an easier way to develop content. Just an opinion though.

When speaking of propagating messages, the efficiency of finding the appropriate message handler for a specific message has as a worst case scenario is O(N). Theoretically when there are hundreds of handlers, or even a few thousand, is not efficient compared to O(1) when using a map collection structure.

For these reasons I think the handler chain should be converted to a one to one representation of a message to message dispatcher, and for each message dispatcher a one to one representation of handler conditions to a handler should be employed. Such in the case of the message dispatcher, similar methods could be deployed to all message sub-types.

The proposal would be wide spread and I don't really expect it to be accepted right away however I feel the benefits outweigh the current implementation. A solution to this would include a logical centralized representation of all content, which the organization of such could be debated. Perhaps by category, or some other means.

Consideration for Packet Normalization

I think one of the clunkier feelings to Apollo when developing for it is the fact that each packet has a one to one class representation of a message (sometimes its one to many since an option field can be attributed say option packets), a one to one class representation of a message to an encoder/decoder, and a one to one class representation of a handler. When it comes down to brass tacks it feels very clunky and in my opinion is one of the greatest design flops with the source.

I'm proposing that with the found knowledge of the real packet ids which is represented in the PacketConstant class in the older Runetek engine that in the session pipeline that all packets be normalized before decoding to cut down on some of this class overhead. The strategy for this would be to rearrange the bytes in logical and homogeneous order of similarly structured packets. For example: ItemOptionOne/ItemOptionTwo

New players should be queued rather than added immediately.

When adding players to the World, they should be added to a queue which is processed every tick, rather than added immediately. This reduces the amount of locking required, and also prevents lots of new players from delaying the server pulse.

NPE when wielding two handed weapons

Although the NullPointerException is caught, there is still an error that gets raised when wielding two handed weapons. The error comes from adding an item to your inventory via the Inventory#add(Item) method. This error is only raised when wielding two handed weapons, such as bows or two handed swords.

My guess at how this happens is when the two handed weapon is being equipped, it's trying to un-equip both the current equipped weapon and shield, and one (or both) are empty slots, thus the return value is null.

The solution I've found to work is just to just change this code (org.apollo.game.model.Inventory.java):

    // ... line 254 below
    public Item add(Item item) {
        int id = item.getId();
        boolean stackable = isStackable(item.getDefinition());
        if (stackable) {
    // ...

to this:

    // ... line 254 below
    public Item add(Item item) {
        if (item == null)
            return null;

        int id = item.getId();
        boolean stackable = isStackable(item.getDefinition());
        if (stackable) {
    // ...

But just to be safe and make sure this isn't the only problem, here's the output:

Stack:

SEVERE: Error handling event.
java.lang.NullPointerException
    at org.apollo.game.model.Inventory.add(Inventory.java:255)
    at org.apollo.game.event.handler.impl.EquipEventHandler.handle(EquipEventHandler.java:128)
    at org.apollo.game.event.handler.impl.EquipEventHandler.handle(EquipEventHandler.java:1)
    at org.apollo.game.event.handler.chain.EventHandlerChain.handle(EventHandlerChain.java:64)
    at org.apollo.net.session.GameSession.handlePendingEvents(GameSession.java:112)
    at org.apollo.game.GameService.pulse(GameService.java:138)
    at org.apollo.game.GamePulseHandler.run(GamePulseHandler.java:35)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

Teleport to a new location wont add you to a sector until you walk

When the entity is teleported he isnt removed from the last sector they where in and they are not added into the new sector until they walk.

Fix:

public void teleport(Position position) {
    if (SectorCoordinates.fromPosition(this.position) != SectorCoordinates.fromPosition(position)) {
        SectorRepository repository = World.getWorld().getSectorRepository();
        Sector newSector = repository.fromPosition(position);
        Sector oldSector = repository.fromPosition(this.position);
        oldSector.removeEntity(this);
        newSector.addEntity(this);
    }
    this.position = position;
    teleporting = true;
    walkingQueue.clear();
    stopAction();
}

Combat

Apollo needs combat support.

Update Pom

Apache Commons is now 1.9 - Fixes

Netty is 4.0.25 - Mainly new features

jRuby is now 1.7.19 - Loads of fixes

Modify region system to prioritize entities

I mentioned this on Skype but I haven't gotten a chance to write an implementation yet. I don't imagine it would be too difficult (could just use a comparator). If done, someone would have to do a benchmark to see if it has any negative effects on performance.

Order of prioritization

  • Entities you are in combat with
  • Players on your friends list (maybe???)
  • Distance of the entities

on :event, :object_action problem

For the FirstObjectActionEvent, this code won't work:

on :event, :object_action do |ctx, player, event|
  if event.option == 1
    player.send_message("You clicked the first action for object #{event.id}.")
  end
end

This does:

on :event, :first_object_action do |ctx, player, event|
  player.send_message("You clicked the first action for object #{event.id}.")
end

Issue with ItemDefinitionDecoder

Currently it look like this
"} else if (opcode == 78 || opcode == 79 || opcode >= 90 || opcode <= 93 || opcode == 95) {"

Needs to be

"} else if (opcode == 78 || opcode == 79 || opcode == 90|| opcode == 91|| opcode == 92 || opcode == 93 || opcode == 95) {"

or

"} else if (opcode == 78 || opcode == 79 || (opcode >= 90 && opcode <= 93) || opcode == 95) {"

Possible player updating issue

This is a copy of the most recent version of apollo and found this issue happen when messing around making trading. This has happened a few times and this is one of the times I have been able to get a screen shot of it happening

http://prntscr.com/6h348a

MobRepository get method gets wrong object in the array

public T get(int index) {
index = index - 1;
if (index < 0 || index >= mobs.length) {
throw new IndexOutOfBoundsException("Mob index is out of bounds.");
}

    return (T) mobs[index];
}

Needs to be change to this because before it would grab the wrong object

Height level out of bounds issue

When you try to go to height level 4 it will not let you go and there are a few castles like rouges castle in the wilderness that does need this fixed if you want to go all the way too the top.

NpcActionVerificationHandler option check will never pass.

NpcActionVerificationHandler contains a check that will never pass, because the interaction count is always set to 5. The Handler must check that the option is valid (i.e. that the option is not set to "null"), which may also require some form of player-local state, as some npcs may have right-click options that are only visible if a specific varp is set.

This is the statement that will always evaluate to true:

    if (message.getOption() >= definition.getInteractions().length) {
        message.terminate();
        return;
    }

Missing XML File

There is a file (data/login.xml) missing in the repository which mean that the server cannot successfully run.

Uninitialized constant in the lookup plugin

Every time I run ::lookup npc <name> or ::lookup object <name> (::lookup item works, oddly enough!) I get an error in the server console:

Jan 20, 2014 1:28:13 AM org.apollo.net.session.GameSession handlePendingEvents
SEVERE: Error handling event.
org.jruby.exceptions.RaiseException: (NameError) uninitialized constant Kernel::NpcDefinition
    at org.jruby.RubyModule.const_missing(org/jruby/RubyModule.java:2684)
    at org.jruby.RubyModule.const_get(org/jruby/RubyModule.java:2599)
    at RUBY.(root)(data\plugins\cmd-lookup\lookup.rb:19)
    at org.jruby.RubyProc.call(org/jruby/RubyProc.java:271)
    at RUBY.execute(data\plugins\bootstrap.rb:44)

Line 19 of lookup.rb:
Kernel.const_get("#{type.capitalize}Definition").definitions.each do |definition|

I've manually tried NpcDefinition and ObjectDefinition to determine if it was a spelling error, and ItemDefinition is the only one that works.

On a side note, I also get

Jan 20, 2014 1:29:47 AM org.apollo.net.session.GameSession handlePendingEvents
SEVERE: Error handling event.
org.jruby.exceptions.JumpException$ReturnJump

from ::lookup if it's ran without any arguments.

EDIT
Fix for the uninitialized constant was adding some java imports to the ruby code.
Fix for the jump exception was changing return to next (though line 25 can't be changed from "return" to "next" or else it will just keep going through the array so you'll still get that outputted after a successful execution of ::lookup)

BankMessageHandler Withdraw Entered Amount not working

Issue in method "withdraw"
"EnterAmountListener listener = new BankDepositEnterAmountListener(player, message.getSlot(), message.getId());"

Change to
"EnterAmountListener listener = new BankWithdrawEnterAmountListener(player, message.getSlot(), message.getId());"

Issue using the wrong listener.

Appearance caching

The server should avoid sending the appearance block if the player has already seen the other player and the other player's appearance hasn't changed since that time.

Attributes system saving all types of attributes

The BinaryPlayerSaver is writing the number of attributes the player has, however only writing the attributes which are of type SERIALIZED. Because of this, there will be a buffer underflow exception if any non-saved attributes are saved.
Additionally, BinaryPlayerSaver should use DataOutputStream's writeUTF method for continuity.

Shops

Apollo currently has no support for npc shops.

This should probably be done in ruby.

r317 and r377

In Release317 it imports a few classes from r377.

register(72, new FirstNpcActionEventDecoder());
register(155, new SecondNpcActionEventDecoder());
register(17, new ThirdNpcActionEventDecoder());

This is probably intentional for a reason, but in all the Apollo code I've seen, I haven't seen anyone use decoders from the other class (not to say it doesn't work -- it probably does)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.