Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

buildscript {
ext {
kotlinVersion="1.8.10"
kotlinVersion="1.8.20"
coroutineVersion="1.6.4"
ktxVersion="1.11.0-rc1"
jacksonVersion="2.14.2"
junitVersion="5.9.2"
slf4jVersion="2.0.6"
slf4jVersion="2.0.7"
semver4jVersion="3.1.0"
log4jVersion="2.20.0"
gdxVersion="1.11.0"
mavenResolverVersion="1.9.5"
mavenResolverVersion="1.9.7"
mockitoKotlinVersion="4.1.0"
eclipseCollectionsVersion="11.1.0"
fledUtilsVersion="0.1.9-SNAPSHOT"
fledUtilsVersion="0.1.10-SNAPSHOT"
fledEcsVersion="0.1.9-SNAPSHOT"
fledObjectUpdaterVersion="0.1.9-SNAPSHOT"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package fledware.definitions

import fledware.utilities.ConcurrentHierarchyMap
import fledware.utilities.HierarchyMap
import java.util.concurrent.ConcurrentHashMap
import kotlin.reflect.KClass


interface DefinitionWithType<T : Any> {
val klass: KClass<out T>
}

data class DefinitionWithTypeHolder(
val indexes: MutableMap<String, HierarchyMap<*>> = ConcurrentHashMap()
)

fun <T : Any> DefinitionRegistry<out DefinitionWithType<T>>.typeIndex(): HierarchyMap<T> {
val holder = (this as DefinitionRegistryManaged).manager.contexts
.getOrPut(DefinitionWithTypeHolder::class) { DefinitionWithTypeHolder() }
@Suppress("UNCHECKED_CAST")
return holder.indexes.computeIfAbsent(this.name) {
val index = ConcurrentHierarchyMap()
this@typeIndex.definitions.values.forEach { index.add(it.klass) }
index
} as HierarchyMap<T>
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ interface DefinitionsManager {
val classLoader: ClassLoader

/**
* all registries indexed by lifecycle name.
*
* If a Lifecycle does not create a registry, then it will not be here.
* all registries indexed by registry name.
*/
val registries: Map<String, DefinitionRegistry<out Any>>

/**
* all instantiator factories instantiator name.
*/
val instantiatorFactories: Map<String, InstantiatorFactory<out Any>>

/**
* user contexts that can be used to share data.
*/
Expand All @@ -29,16 +32,49 @@ interface DefinitionsManager {
*/
val packages: List<ModPackageDetails>

/**
* get a registry for a given definition type.
*
* @param name the name for the registry
* @throws IllegalArgumentException if the registry doesn't exist
*/
fun registry(name: String): DefinitionRegistry<out Any>

/**
*
*/
fun tearDown()
}

/**
* finds the registry with the given name.
*
* @param name the name for the registry
* @throws IllegalArgumentException if the registry doesn't exist
*/
fun DefinitionsManager.findRegistry(name: String): DefinitionRegistry<out Any> {
return registries[name]
?: throw IllegalStateException("unable to find registry: $name")
}

/**
* finds the registry with the given name and casts it to the
* expected registry type.
*
* @param name the name for the registry
* @param T the type to cast the registry to
* @throws IllegalArgumentException if the registry doesn't exist
* @throws ClassCastException if the registry can't be cast
*/
@Suppress("UNCHECKED_CAST")
fun <T : Any> DefinitionsManager.findRegistryOf(name: String): DefinitionRegistry<T> {
return findRegistry(name) as DefinitionRegistry<T>
}

/**
*
*/
fun DefinitionsManager.findInstantiatorFactory(name: String): InstantiatorFactory<out Any> {
return instantiatorFactories[name]
?: throw IllegalStateException("unable to find instantiator factory: $name")
}

/**
*
*/
@Suppress("UNCHECKED_CAST")
fun <I : Any, F : InstantiatorFactory<I>> DefinitionsManager.findInstantiatorFactoryOf(name: String): F {
return findInstantiatorFactory(name) as F
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package fledware.definitions

import kotlin.reflect.KClass

/**
* an instantiator for a specific definition.
*
* This is up to the implementors to define how something
* is actually created. It would be difficult to create a
* common way to create a complex object that would work
* well, be performant, and easy to use by the games that are
* actually defining entities.
*
* This part of the system can be completely left out, but
* there are some nice built-ins that can probably be used
* by things that do need to create instances.
*
* For simple objects that are self-contained, it might be
* better to put the creator right on the definition itself.
* But for object creation that is complex, or need to be cached,
* or depends on other definitions, it is probably better
* to add a little more architecture around the creation.
*
* @param I the type being instantiated
*/
interface Instantiator<I : Any> {
/**
* the name of the [InstantiatorFactory] that created this
*/
val factoryName: String

/**
* the name of this [Instantiator]
*/
val instantiatorName: String

/**
* the type that is instantiated
*/
val instantiating: KClass<I>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package fledware.definitions

interface InstantiatorFactory<I : Any> {
/**
* the name of this factory
*/
val factoryName: String

/**
* All instantiators that have been created.
*/
val instantiators: Map<String, Instantiator<I>>

/**
* gets an instantiator if it is already created. else,
* it will create the cache the instantiator.
*/
fun getOrCreate(name: String): Instantiator<I>
}

/**
*
*/
interface InstantiatorFactoryManaged<I : Any> : InstantiatorFactory<I> {
/**
* The [DefinitionsManager] this registry is managed by
*/
val manager: DefinitionsManager

/**
* Called by the owning manager after all the registries have been created.
*/
fun init(manager: DefinitionsManager)

/**
* Called to signal this registry needs to clean itself of anything
* that needs to be removed from memory.
*/
fun tearDown()
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import fledware.definitions.builder.mod.ModPackageEntry
import fledware.definitions.builder.mod.SimpleModPackageEntry
import fledware.definitions.exceptions.UnknownDefinitionException
import fledware.definitions.exceptions.UnknownHandlerException
import kotlin.reflect.KClass

/**
* the name of the group for [DefinitionRegistryBuilder]
Expand All @@ -21,13 +22,22 @@ val BuilderState.definitionRegistryBuilders: Map<String, DefinitionRegistryBuild

/**
* finds a specific [DefinitionRegistryBuilder] within the
* [definitionRegistryBuilderGroupName] state.
* [definitionRegistryBuilderGroupName] group.
*/
fun BuilderState.findRegistry(name: String): DefinitionRegistryBuilder<Any, Any> {
return definitionRegistryBuilders[name]
?: throw UnknownHandlerException("unable to find DefinitionRegistryBuilder: $name")
}

/**
* finds a specific [DefinitionRegistryBuilder] within the
* [definitionRegistryBuilderGroupName] group and casts it to the given types.
*/
@Suppress("UNCHECKED_CAST")
fun <R : Any, D : Any> BuilderState.findRegistryOf(name: String): DefinitionRegistryBuilder<R, D> {
return findRegistry(name) as DefinitionRegistryBuilder<R, D>
}

/**
* TODO: the mutators of entries need to be rethought
* apply/mutate doesn't make sense for all registries. The best would be to
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package fledware.definitions.builder

import fledware.definitions.InstantiatorFactory
import fledware.definitions.InstantiatorFactoryManaged
import kotlin.collections.Map
import kotlin.collections.MutableMap
import kotlin.collections.mutableMapOf
import kotlin.collections.set

val instantiatorFactoryHolderGroupName = InstantiatorFactoryHolder::class.simpleName!!

class InstantiatorFactoryHolder : AbstractBuilderHandler() {
override val group: String
get() = instantiatorFactoryHolderGroupName
override val name: String
get() = instantiatorFactoryHolderGroupName

val instantiators: Map<String, InstantiatorFactoryManaged<Any>> = mutableMapOf()
}

val BuilderState.instantiatorFactoryHolder: InstantiatorFactoryHolder
get() = this.findHandlerGroupAsSingletonOf(instantiatorFactoryHolderGroupName)

val BuilderState.instantiatorFactories: Map<String, InstantiatorFactoryManaged<Any>>
get() = this.instantiatorFactoryHolder.instantiators

fun BuilderState.putInstantiatorFactory(factory: InstantiatorFactory<out Any>) {
@Suppress("UNCHECKED_CAST")
(instantiatorFactories as MutableMap)[factory.factoryName] =
factory as InstantiatorFactoryManaged<Any>
}

fun BuilderState.removeInstantiatorFactory(factory: InstantiatorFactory<Any>) {
(instantiatorFactories as MutableMap).remove(factory.factoryName)
}

fun BuilderState.removeInstantiatorFactory(factory: String) {
(instantiatorFactories as MutableMap).remove(factory)
}

fun DefinitionsBuilderFactory.withInstantiatorFactory(
factory: InstantiatorFactory<out Any>
) : DefinitionsBuilderFactory {
this.putInstantiatorFactory(factory)
return this
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ open class AddBuilderHandlerHandler
override val name = "AddBuilderHandler"
override val processor: String = builderModEntryProcessorName

override fun processMaybe(modPackageContext: ModPackageContext, anyEntry: ModPackageEntry): Boolean {
override fun processMaybe(context: ModPackageContext, anyEntry: ModPackageEntry): Boolean {
val (entry, _) = anyEntry.findAnnotatedClassOrNull(AddBuilderHandler::class) ?: return false
if (!entry.klass.isSubclassOf(BuilderHandler::class))
throw IllegalArgumentException("classes annotated with @AddBuilderHandler" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class AddObjectUpdaterDirectiveHandler
override val name: String = "AddObjectUpdaterDirective"
override val processor: String = builderModEntryProcessorName

override fun processMaybe(modPackageContext: ModPackageContext, anyEntry: ModPackageEntry): Boolean {
override fun processMaybe(context: ModPackageContext, anyEntry: ModPackageEntry): Boolean {
val (entry, annotation) = anyEntry.findAnnotatedClassOrNull(AddObjectUpdaterDirective::class) ?: return false
if (!entry.klass.isSubclassOf(DirectiveHandler::class))
throw IllegalArgumentException(
Expand All @@ -71,7 +71,7 @@ class AddObjectUpdaterDirectiveHandler
ex
)
}
val updater = modPackageContext.builderState.objectUpdater
val updater = context.builderState.objectUpdater
when (handler) {
is SelectDirective -> (updater.selects as MutableMap)[handler.name] = handler
is OperationDirective -> (updater.operations as MutableMap)[handler.name] = handler
Expand Down Expand Up @@ -104,12 +104,12 @@ open class ObjectUpdaterHandler(
override val processor: String = definitionModEntryProcessorName
private val parseType = object : TypeReference<List<ObjectUpdaterMutation>>() {}

override fun processMaybe(modPackageContext: ModPackageContext, anyEntry: ModPackageEntry): Boolean {
override fun processMaybe(context: ModPackageContext, anyEntry: ModPackageEntry): Boolean {
val entry = anyEntry.findResourceOrNull(gatherRegex) ?: return false
val mutations = modPackageContext.readEntry(entry.path, parseType)
val objectUpdater = modPackageContext.builderState.objectUpdater
val mutations = context.readEntry(entry.path, parseType)
val objectUpdater = context.builderState.objectUpdater
mutations.forEach { mutation ->
val registry = modPackageContext.builderState.findRegistry(mutation.registry)
val registry = context.builderState.findRegistry(mutation.registry)
registry.mutate(mutation.definition, entry) {
val target = objectUpdater.start(it)
objectUpdater.executeCount(target, mutation.command)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ fun <T : Any> ModPackageContext.readEntry(entry: String, klass: KClass<T>): T {
}
}

/**
* reads an entry to the [T] type.
*/
fun <T : Any> ModPackageContext.readEntry(entry: String, klass: Class<T>): T {
modPackage.read(entry) {
return builderState
.figureSerializer(entry)
.readAsType(it, klass)
}
}

/**
* reads an entry to the [T] type.
*/
Expand All @@ -66,7 +77,7 @@ fun <T : Any> ModPackageContext.readEntry(entry: String, typeRef: TypeReference<

/**
* Finds an entry that starts with [entryWithoutExtension], and checks for
* each known format from [BuilderState.serialization].
* each known format from [DefinitionsBuilderState.serializers].
*
* This will return the full entry with the extension included.
*/
Expand All @@ -79,7 +90,7 @@ fun ModPackageContext.findEntry(entryWithoutExtension: String): String {

/**
* Finds an entry that starts with [entryWithoutExtension], and checks for
* each known format from [BuilderContext.serialization].
* each known format from [DefinitionsBuilderState.serializers].
*
* This will return the full entry with the extension included, or null if
* no entry with any known format is found.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class AnnotatedClassEntryFactory : AbstractBuilderHandler(),
override val order: Int = 20

override fun attemptRead(modPackage: ModPackage, entry: String): List<ModPackageEntry> {
if (entry.endsWith("Kt.class"))
return emptyList()
if (!entry.endsWith(".class"))
return emptyList()
val klass = modPackage.loadClass(entry).kotlin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import java.io.InputStream


class DirectoryModPackage(
override val root: File,
override val spec: String
override val spec: String,
override val root: File
) : AbstractModPackage() {
override val type: String = "directory"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ class DirectoryModPackageFactory : AbstractModPackageFactory() {
override fun actualAttemptFactory(spec: String, file: File): ModPackage? {
if (!file.isDirectory)
return null
return DirectoryModPackage(file, spec)
return DirectoryModPackage(spec, file)
}
}
Loading
Loading