Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split content into modules #584

Closed
GregHib opened this issue Jan 17, 2025 · 5 comments
Closed

Split content into modules #584

GregHib opened this issue Jan 17, 2025 · 5 comments
Labels
content enhancement New feature or request system

Comments

@GregHib
Copy link
Owner

GregHib commented Jan 17, 2025

With the amount of content being added it's probably a good idea to start splitting into smaller modules. This will have the benefit of faster compilation times and forced isolation between content.
Could be a pain to unpick.

Organisation makes sense to do geographically, Regions/Locations > Kingdoms/States > Cities/Towns:

  • Misthalin
  • Karamja
  • Asgarnia
  • Kharidian Desert
  • Fremennik Province
  • Kandarin
  • Morytania
  • Tirannwn
  • Wilderness
  • Realms/Misc

It might start getting to the point where the configuration files also need to be split up. The first to do would be the spawn files into separate regions.

@GregHib GregHib added content enhancement New feature or request system labels Jan 17, 2025
@GregHib GregHib added this to Void Jan 17, 2025
@github-project-automation github-project-automation bot moved this to To do in Void Jan 17, 2025
@GregHib
Copy link
Owner Author

GregHib commented Jan 25, 2025

After completing most of the work I'm having second thoughts.

Pros:

  • Modularity is good for code as it keeps things separate.
  • Faster build times due to incremental builds (only rebuilds modules that have been modified

Cons:

  • Barrier to write content and tests as you need to know which modules you need to depend on before being able to refer to the content in them.
  • Slower clean build time +10%
  • x2 Slower script loading time in IDE
  • Large build jar +5mb
  • build folders populate everywhere

@GregHib
Copy link
Owner Author

GregHib commented Jan 25, 2025

Kotlin conventions actually suggest not having world.gregs.voidps. as a package.

Package naming rules also suggest avoiding multi-word package but to name them camel case if needed. so treeGnomeStronghold

@GregHib
Copy link
Owner Author

GregHib commented Jan 25, 2025

I decided to scrap the nested modules in favour of using packages. I think I will try splitting out the main class into a module again (assuming it doesn't come with tradeoffs) and possibly also the bot stuff into it's own module too.

Spoilers: it came with tradeoffs. Alright screw modules then.

@GregHib GregHib moved this from To do to In progress in Void Jan 26, 2025
@GregHib
Copy link
Owner Author

GregHib commented Jan 26, 2025

It might be worth splitting the engine up into modules at some point in the future but for now it's not worth doing. Content was a hassle to split and then it wasn't worth it in the end anyway due to how much slower everything was. With only 460 scripts at the moment and the recent speed improvements it's not currently an issue, might be worth re-evaluating when we get closer to 2k scripts.

@GregHib GregHib closed this as completed Jan 26, 2025
@github-project-automation github-project-automation bot moved this from In progress to Done in Void Jan 26, 2025
@GregHib
Copy link
Owner Author

GregHib commented Jan 26, 2025

I'll post the method I used for modules here for future reference just in case.

This settings.gradle.kts code essentially meant that any directory in game with a .gradle.kts file would get turned into a module.

includeProjects(project(":game"))

fun includeProjects(pluginProject: ProjectDescriptor) {
    val projectPath = pluginProject.projectDir.toPath()
    Files.walk(projectPath).forEach {
        if (!Files.isDirectory(it) || it.name == "src" || it.name == "build") {
            return@forEach
        }
        searchProject(pluginProject.name, projectPath, it)
    }
}

fun searchProject(parentName: String, root: Path, currentPath: Path) {
    val hasBuildFile = Files.exists(currentPath.resolve("build.gradle.kts"))
    if (!hasBuildFile) {
        return
    }
    val relativePath = root.relativize(currentPath)
    val projectName = relativePath.toString().replace(File.separator, ":")
    include("$parentName:$projectName")
}

This code in game's build.gradle.kts meant that game became dependency on all sub-modules, and all sub-modules had all the same external dependencies

val commonDeps = project.configurations.getByName("implementation").dependencies
val testDeps = project.configurations.getByName("testImplementation").dependencies

subprojects {
    dependencies {
        for (dep in commonDeps) {
            implementation(dep)
        }
        for (dep in testDeps) {
            testImplementation(dep)
        }
    }

    tasks.test.get().workingDir = rootProject.projectDir
}

dependencies {
    for (project in subprojects) {
        api(project)
    }
}

sourceSets {
    test {
        kotlin {
            for (subproject in subprojects) {
                for (dir in subproject.sourceSets.test.get().kotlin.srcDirs) {
                    srcDirs += dir
                }
            }
        }
    }
}

The main class was in a server module with an api(project(":game")) dependency on :game so that it wasn't minimized by shadow jar because that caused issues for some reason.
Shadow jar also needed a minimize exclusion exclude(dependency("org.jetbrains.kotlin:kotlin-script-runtime:.*")) for kotlin script runtime for some reason.

Both of these issues were concerned with how scripts were build and why that's for some reason different when in a different module from the main class. The consequence of the lack of minimization was an explosion in jar size. 50MB instead of 28MB.

Module build.gradle.kts were straight forward just the local dependencies between one another

dependencies {
    implementation(project(":game:entity:player:dialogue"))
    implementation(project(":game:api"))

    testImplementation(project(":game:api:testing"))
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
content enhancement New feature or request system
Projects
Status: Done
Development

No branches or pull requests

1 participant