Giter Club home page Giter Club logo

hestia's Introduction

Hestia

Open-source Kotlin MMO-RPG game server; emulating Runescape October 2011, client build 667.1

Getting Started

Refer to our Getting started guide.

Built With

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Authors

See also the list of contributors who participated in this project.

License

This project is licensed under the BSD License - see the LICENSE file for details

Acknowledgments

hestia's People

Contributors

greghib avatar

Stargazers

feodott avatar Tyluur avatar S.Nishio avatar  avatar Daniel André da Silva avatar Sergey Mokrushin avatar  avatar narakai avatar Harrison Cole avatar  avatar  avatar branon avatar  avatar  avatar Daan van Yperen avatar Ian William O'Neill avatar

Watchers

James Cloos avatar  avatar Raye W avatar David (Javatar) avatar  avatar

hestia's Issues

Content script dependencies

All non-core content should be contained within Kotlin scripts.

Will the script loading system allow for a dependency on another?
How will script dependencies affect testing?

Kotlin script imports

ScriptConfigurations current specifies correct packages but scripts don't auto-suggest imports recursively. Look into why this is and how it can be improved.

Example:
"kotlinx.*" and typing runBlocking in a script doesn't suggest it as an import because the package is kotlinx.coroutines.runBlocking

AI Traversal

Scenario: Bot in lumbridge has task to mine iron. How does it find a path to the nearest suitable mine?

The entire collision map and target locations are for the most part static so once calculated can be reused.

Tagging

First "the bot" must identify what is a mine. Locate every single rock and weight by proximity to each other.
This will mean bots will choose a cluster of rocks over a single rock of they are the same distance.

Filter

Now take the tagged areas and filter out wrong types.
This will give a list of only iron ore mines.

Path

Collision map with weights based on several factors:

  • Shortcut requirements: Level, coins, unlocks
  • Risk & combat level
    Meaning shortcuts will be used when able and low leveled bots will avoid higher leveled mobs (e.g varrock dark wizards).
    Calculate the path cost to each area

Decide

Combine path costs with proximity costs to get a final best decision which you already have the exact path for. Can potentially be randomised by bot type.

Traverse

Optionally splitting the path into points separated by view distance/max walk distance for realism and checking to use the shortcuts when within radius.

Cache Definitions

Object, Item and Mob definitions will be needed for interactions #69

Requirements will be needed for Equiping and Item containers #76

Animation and graphic definitions will be needed for #65

Lobby reconnect

Client should reconnect to the lobby after game server restart.

Original note:

Add reconnecting after game/lobby server restart: disconnect doesn't remove player instantly - COULD_NOT_COMPLETE_LOGIN

TaskPriority auto screen close suspension

#55

A suspension much like waiting for an open widget to close #56 but instead only if there is a screen open:

  • waits for any open screen to close
  • get the current open screen and uses wait-for-widget suspension #56.

Ideally, this will be injected into the beginning of the Queue on the initiation of QueueTask depending on the (immutable) QueuePriority.

POC

fun hack(queue: Queue) = queue

data class QueueTask private constructor(val priority: QueuePriority, val queue: Queue) {
    constructor(queue: Queue, priority: QueuePriority) : this(priority, if (priority == QueuePriority.Normal) hack {
        waitForScreen()//TODO
        queue()
    } else queue)
}

Stacked player update

Upon login stacked players within view aren't shown until they are updated (move).

Move hits & damage logic out of encode

Especially HitsBlockEncoder.calcMark.
Wait until hitpoints/constitution skill is implemented as changes will be need for health percentage then anyway.

Floor Item System

Item entity with Position

Add/removed from client viewports just like other entities.

Should queues be stored separate or combined?

How often will multiple queues be in use simultaneously?

Dialogues might have another dialogue pushed in-front or behind.

A dialogue might happen during a tick queue, but would normally cancel the tick queue?

Normally only one queue at a time. Are there exceptions?

Migrate misc engine components

Remaining

  • worlds.gregs.hestia.events
  • worlds.gregs.hestia.game.archetypes
  • worlds.gregs.hestia.game.client
  • worlds.gregs.hestia.game.map
  • worlds.gregs.hestia.game.MessageHandlerSystem
  • worlds.gregs.hestia.game.TickTask

Moved to core

Should content scripts be Artemis structured?

If scripts are going to be using suspended functions #31, then the DSL will need to be intermediary between Artemis' loops.

What would happen if an entity was deleted before a coroutine completed?

How best should errors & failures be handled? Functionally?

Region collision reloading

Fix unloaded region collision not reloading (because for collision it's checked different in MapSystem#getClipping than when accessed in ClippingMaskSystem#getClipping ?)

Clear core functionality distinction

Currently, the server's architecture is:

  • hestia-server-core
    • hestia
      • plugins
        • "core" artemis plugins
        • content script "plugins"
      • server (aka "core functionality")
  1. These names are confusing inconsistent and need clarity.
  2. There's no clear line between what is network, engine content, game content.

The list of content to categorise:

  • Maps, Regions & Chunks
  • Entity content (players, mobs, bots, objects, items)
    • Interaction
    • Collision
    • Movement
    • Size
  • Interfaces
    • Dialogues
  • Emotes
  • Commands
  • Cache definitions
  • Tasks
    • Quests
    • Achievements
  • Distractions & Diversions
  • Activities
    • Combat
    • Skills
    • Bosses
  • Economy
    • Shops
  • Community

Migrate updating from engine to core

Includes:

  • worlds.gregs.hestia.api.*
  • worlds.gregs.hestia.events.* (Not all?)
  • worlds.gregs.hestia.game.client.*
  • worlds.gregs.hestia.game.entity.*

Doesn't include:

  • worlds.gregs.hestia.network.update.*

Should be migrated to

  • worlds.gregs.hestia.core.client.update.*

Coroutine suspension types

Currently only dialogue messages and wait X ticks suspensions exist.

Other suspension types:

  • Walk to tile
  • Wait for interface to close
  • Wait for animation/gfx to finish (extends time/ticks)
  • Custom - e.g wait for player to click on a button (when to check?)

Suspend-able TaskScope end()

A suspendable method needed so actions afterwards aren't called accidentally.

queue {
    println("To the thing")
    end()
    println("This is called but shouldn't be")
}

Container Systems

Item is an entity. It can have a Quantity component.

An item could potentially have a Name, Description, Consumable or Equipable component. However this wouldn't make sense as these values are static and would just be duplicating data.

Degredation would make sense, and Type of course. Is that it? Noted perhaps.

Interact with movement suspension

Currently waiting for a position #56 isn't very useful by itself. Need an interact with object, floor item, mob, player, bot action, which will need size cache definitions to calculate positions.

AI Behaviours

How might a task or behaviour for a bot look like in code?

The decision making would most likely be done by a tree structure, for this example let's say that the bot has been woodcutting and just reached level 41 so it's new behaviour is to buy a rune hatchet.

Find & traverse described in #57

queue {
    If has money is in bank
        Find nearest bank
        Traverse to nearest bank
        Open bank
        Withdraw money
    End
    If has money in inventory
        Find nearest hatchet shop
        Traverse to nearest hatchet shop
        Open shop
        Buy hatchet
    End
} 

QueuePriority

Example TaskPriority

Each entity (player/mob/bot) has its own queue.
Queues are used for: dialogues, combat, interfaces, skills (all interaction pretty much)

Type Description Examples
Strong Closes menus immediately death, teleporting
Standard Waits for full-screen menus to finish before continuing interaction movement
Weak Cancelled when player clicks away (or strong tasks) string/integer input dialogue, interfaces (for actions on closing)?

Originally posted by @GregHib in #46 (comment)

Check if standard priority is for full screen only or game screen interfaces too.

Mockito verify suspend function called

verify(mock).suspend()

Minimum reproducible example:

package worlds.gregs.hestia.core.plugins.dialogue.systems

import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Test
import org.mockito.Mockito
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock

internal class SuspendTest {

    interface Suspendable {
        suspend fun suspend()
    }

    fun calledElsewhere(mock: Suspendable) = runBlocking {
        mock.suspend()
    }

    @Test
    fun `Suspend test`() = runBlocking {
        //Given
        val mock = mock(Suspendable::class.java)
        `when`(mock.suspend()).thenReturn(Unit)
        //When
        calledElsewhere(mock)
        //Then
        Mockito.verify(mock).suspend()
    }

}
Argument(s) are different! Wanted:
suspendable.suspend(
    Continuation at worlds.gregs.hestia.core.plugins.dialogue.systems.SuspendTest$Suspend test$1.invokeSuspend(SuspendTest.kt:27)
);
-> at worlds.gregs.hestia.core.plugins.dialogue.systems.SuspendTest$Suspend test$1.invokeSuspend(SuspendTest.kt:27)
Actual invocation has different arguments:
suspendable.suspend(
    Continuation at worlds.gregs.hestia.core.plugins.dialogue.systems.SuspendTest$calledElsewhere$1.invokeSuspend(SuspendTest.kt:16)
);
-> at worlds.gregs.hestia.core.plugins.dialogue.systems.SuspendTest$calledElsewhere$1.invokeSuspend(SuspendTest.kt:16)

Convert final Components to data classes

Before

@PooledWeaver
class Emote() : Component() {

    constructor(id: Int) : this() {
        this.id = id
    }

    var id = -1
}

After

@PooledWeaver
data class Emote(var id: Int) : Component() {
    constructor() : this(-1)
}

Easier to read and provides automatic toStrings

Delayed reset system

Whether it's doors opening/closing, entities respawning, shooting star starting/stopping. Lots of features follow this delayed reactivate/respawn pattern so it makes sense to have a reusable respawning system.

abstract class Respawnable : Component() {
    var ticks = 0
} 
abstract class RespawnSystem(clazz: Class<out Respawnable>) : DelayedIteratingSystem(Aspect.all(clazz)) {
    override fun process(entityId: Int) {
        // TODO - decrease ticks. If ticks <= 0 then disable the component
    } 
} 

If a component is toggled, does inserted/removed get called again?

Rearchitecture

Name Folder Description Examples
Engine engine Essential functions. Layer to the outside world; client or database. Networking, File handling, Game loop, Queues, Event, Plugin & Script management
Core mechanics core The core game mechanics Entities, Movement, Collision, Events, Client Updating, Widget actions, Dialogues
Game content content Gameplay content made of multiple core mechanics. Quests, Combat, Skills, Distractions & Diversions, Shops

Ideal architecture being:

  • content
    • activities
      • diversions
      • skills
      • combat strategies
      • tasks
        • achievements
        • quests
    • eco
      • trading
      • shops
  • core
    • client
      • update
        • block
        • sync
    • entities
      • player
      • mob
      • bot
      • item
      • object
    • combat
    • map
      • region
      • movement
        • collision
    • widgets
      • dialogues
    • tasks
      • deferrals
  • engine
    • data
      • cache
      • storage
    • game
      • artemis
      • loop
      • queue
      • event
      • plugin
      • script
    • network
      • client
        • encoders
        • decoders
      • world
        • encoders
        • decoders

Network handlers should be in engine but this will mean some communication will be needed for e.g player count to send to social-server for worlds, and classes such as SyncStage and UpdateBlock to stay inside the engine.

Originally posted by @GregHib in #32 (comment)

List exactly what needs migrating from engine -> core and core -> plugins beforehand to get a sense of what effect these changes will have.

Slow movement

Sometimes after the first login; movement queue synchronisation is off causing walking to be half speed.

Bot archetype

Bot archetype should extend player? And client should be split from player too (Finish splitting player and client & having player == bot)

Test Coverage

Things that need implementation tests:

  • Client responses
  • Changing plane follow & stalk
  • Crowds
  • Protocol / codecs
  • Path finding strategies

Coroutine suspending

Scripts and the content system backing them should utilise coroutines and suspending methods to keep content clean and legible.

Better input dialogue handling

String & Integer entry (Script 108 & 109)

Should have a proper callback system so there's no way one system can accidentally use the string requested by another system.

Example: string entry request with friends chat settings open

Should Widgets be entities? - Artemis Queues

Can multiple of the same component be added to a single entity?
If so, is that order consistent?

Both Widgets & Dialogues could be a horizontal queue or vertical stack does that make sense as entities though as it's on a per player basis?

Queue naming

Event is already taken by Artemis.
Currently a Queue of SuspendableQueues doesn't sound very eloquent.

Task, Action or ?

Current classes:
SuspendingQueue
QueueTask
QueueQueueTask
QueueTaskEnded
QueuePriority
PriorityQueueSystem
PriorityQueue

Parents
TickQueueSystem
MovementQueueSystem

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.