Skip to content

Breed#4

Open
danieljharris wants to merge 20 commits intomainfrom
breed
Open

Breed#4
danieljharris wants to merge 20 commits intomainfrom
breed

Conversation

@danieljharris
Copy link
Owner

No description provided.

Copilot AI review requested due to automatic review settings March 1, 2026 23:08
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces animal breeding functionality and consolidates plugin entrypoints under a new LifeCycleMain, alongside updates to devcontainer/server tooling and build dependencies to support asset overrides and new JSON patching utilities.

Changes:

  • Add new AnimalsBreed plugin module (components, systems, registry, command, builder action) and wire it into a new LifeCycleMain plugin entrypoint.
  • Update AnimalsGrow configuration and growth behavior (tamed NPC IDs, config versioning, and spawn position adjustment logic).
  • Revise local dev workflow: server downloader-based setup/start scripts, deployment paths, and build dependency updates.

Reviewed changes

Copilot reviewed 38 out of 42 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
run.sh Adjusts local run flow to use updated server launcher paths.
plugin/src/main/resources/Server/Languages/en-US/server.lang Adds interaction hint string for breeding.
plugin/src/main/kotlin/DrDan/LifeCycle/LifeCycleMain.kt New plugin entrypoint that composes Grow + Breed plugins.
plugin/src/main/kotlin/DrDan/AnimalsGrow/test/TestRunner.kt Tweaks test spawn positions.
plugin/src/main/kotlin/DrDan/AnimalsGrow/grow_ecs/AnimalsGrowSystem.kt Simplifies tick logic (early return) for growth.
plugin/src/main/kotlin/DrDan/AnimalsGrow/config/AnimalsGrowConfig.kt Switches defaults to Tamed_* roles and introduces codec versioning.
plugin/src/main/kotlin/DrDan/AnimalsGrow/AnimalsGrowAction.kt Adds spawn-position adjustment (“fence detection”) when growing.
plugin/src/main/kotlin/DrDan/AnimalsGrow/AnimalsGrow.kt Adjusts config initialization and exposes start(...) overload used by lifecycle wrapper.
plugin/src/main/kotlin/DrDan/AnimalsBreed/sensors/SensorBred.kt Adds a custom sensor that checks “recently bred” state.
plugin/src/main/kotlin/DrDan/AnimalsBreed/resource_creator/ResourceCreator.kt Adds asset extraction + JSON patch/merge utilities and registers an override pack.
plugin/src/main/kotlin/DrDan/AnimalsBreed/registry/AnimalsBreedRegistrySystem.kt Adds ticking system to drive registry matching each tick.
plugin/src/main/kotlin/DrDan/AnimalsBreed/registry/AnimalsBreedRegistry.kt Adds registry and mate-matching logic to trigger breeding actions.
plugin/src/main/kotlin/DrDan/AnimalsBreed/interaction/interaction.kt Adds commented-out interaction scaffolding (currently disabled).
plugin/src/main/kotlin/DrDan/AnimalsBreed/interaction/ExampleInteraction.kt Adds commented-out example builder/action code (currently disabled).
plugin/src/main/kotlin/DrDan/AnimalsBreed/event/AnimalsBreedEvent.kt Adds spawn event hook to attach breed component based on config.
plugin/src/main/kotlin/DrDan/AnimalsBreed/config/BreedEntry.kt Adds config model + codec for breeding groups.
plugin/src/main/kotlin/DrDan/AnimalsBreed/config/BabyForAdultEntry.kt Adds config model + codec for adult→baby mappings.
plugin/src/main/kotlin/DrDan/AnimalsBreed/config/AnimalsBreedConfig.kt Adds default breeding groups/mappings and codec (currently only serializes breedGroup).
plugin/src/main/kotlin/DrDan/AnimalsBreed/command/AnimalsBreedCommand.kt Adds command to put animals “in love” and seed the registry.
plugin/src/main/kotlin/DrDan/AnimalsBreed/builders/BuilderSensorBred.kt Adds builder for the custom sensor.
plugin/src/main/kotlin/DrDan/AnimalsBreed/builders/BuilderActionBreed.kt Adds builder for the custom “Breed” action.
plugin/src/main/kotlin/DrDan/AnimalsBreed/breed_ecs/AnimalsBreedSystem.kt Adds ECS ticking system to manage in-love + cooldown timers.
plugin/src/main/kotlin/DrDan/AnimalsBreed/breed_ecs/AnimalsBreedComponent.kt Adds component storing in-love/cooldown state and breeding group.
plugin/src/main/kotlin/DrDan/AnimalsBreed/actions/ActionBreed.kt Adds action hook intended to initiate breeding.
plugin/src/main/kotlin/DrDan/AnimalsBreed/AnimalsBreedAction.kt Adds the actual breeding behavior (spawn hearts + baby, start cooldown).
plugin/src/main/kotlin/DrDan/AnimalsBreed/AnimalsBreed.kt Adds new plugin wiring: config load, systems/commands registration, asset overrides.
plugin/manifest/constants.bzl Updates plugin manifest constants: version, server version, new Main class, description.
plugin/build.gradle.kts Updates Kotlin version and adds new JSON patch/serialization dependencies; points compileOnly jar to downloader path.
plugin/assets/Server/overrides/feedbagBreed.json Adds overridden NPC interaction instructions to trigger Breed action/hint.
plugin/BUILD.bazel Expands build sources to include new lifecycle + breeding packages and new deps.
maven_deps.json Adds serialization/merge-patch deps and updates json/kotlin dependency groups.
deploy.sh Changes deployment to build/copy //plugin:dist into downloader-based server mods folder.
commandForwarder.sh Points log forwarding at downloader-based server logs and adds startup delay.
cfr.properties Adds CFR path config.
build_defs/hytale/import_bundles/extension.bzl Adjusts server jar resolution to downloader path and renames output symlink.
build.gradle.kts Updates Kotlin plugin version and adjusts flatDir jar path for downloader.
MODULE.template.bazel Updates rules_kotlin version.
.gitignore Ignores downloader directory and archives.
.devcontainer/start_server.sh Major update: downloader-based server dir, staged update handling, optional jvm.options, restart-on-update loop.
.devcontainer/setup_server.sh Switches setup to downloader zip flow and changes artifact locations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +74 to +82
companion object {
@JvmStatic
val CODEC = BuilderCodec.builder(AnimalsBreedConfig::class.java, ::AnimalsBreedConfig)
.append(
KeyedCodec("BreedGroup", ListCodec()),
{ config, value -> config.breedGroup = value },
{ it.breedGroup }
).add()
.build()!!
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AnimalsBreedConfig includes babyForAdult, and AnimalsBreedAction relies on it, but the CODEC only serializes/deserializes breedGroup. That means any changes to babyForAdult won't persist to disk and can't be configured externally. If this is intended to be configurable, add a codec entry for babyForAdult (with an appropriate list codec).

Copilot uses AI. Check for mistakes.
return
}

val myToolbag = rc.extractAsset(Paths.get("Server/overrides/feedbagBreed.json"), lifecycleJar) ?: return
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ResourceCreator.extractAsset(...) returns a non-null String, so using the Elvis operator (?: return) here will not compile. If the intent is to abort when the asset isn't found, either change extractAsset to return String? or check for isBlank()/isEmpty() and return early based on that.

Suggested change
val myToolbag = rc.extractAsset(Paths.get("Server/overrides/feedbagBreed.json"), lifecycleJar) ?: return
val myToolbag = rc.extractAsset(Paths.get("Server/overrides/feedbagBreed.json"), lifecycleJar)

Copilot uses AI. Check for mistakes.
Comment on lines +21 to +33
override fun execute(ref: Ref<EntityStore>, role: Role, sensorInfo: InfoProvider?, dt: Double, store: Store<EntityStore>): Boolean {
// Ensure the entity has an AnimalsBreedComponent; if not, add a default one
val existing = store.getComponent(ref, AnimalsBreed.getComponentType()) as? AnimalsBreedComponent
if (existing == null) {
val worldTimeResource = store.getResource(WorldTimeResource.getResourceType()) ?: return true
val comp = AnimalsBreedComponent(worldTimeResource.gameTime, arrayOf())
try {
store.addComponent(ref, AnimalsBreed.getComponentType(), comp)
} catch (e: Exception) {
}
}

return true
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This action currently only ensures an AnimalsBreedComponent exists, but it never (1) starts/refreshes the in-love timer/cooldown state nor (2) adds the entity to AnimalsBreedRegistry. As a result, triggering the "Breed" action via the overridden interaction won't lead to any matching/breeding behavior. Consider updating this to set the component to in-love at the current game time (and respect bred cooldown), then register the ref in the registry so AnimalsBreedRegistrySystem can pair it.

Copilot uses AI. Check for mistakes.
Comment on lines +26 to +33
override fun matches(ref: Ref<EntityStore>, role: Role, dt: Double, store: Store<EntityStore>): Boolean {
val breedComponent = store.getComponent(ref, AnimalsBreed.getComponentType()) as? AnimalsBreedComponent
if (breedComponent == null) {
LOGGER.atSevere().log("Sensor Bred failed to get Breed Component")
return false
} else {
LOGGER.atInfo().log("Sensor Bred successfully got Breed Component")
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

matches() logs at SEVERE when the component is missing and at INFO when it is present. Sensors run frequently, so this will spam logs and can impact performance; missing components can also be a normal state. Suggest removing these logs or downgrading to debug/trace behind a flag.

Copilot uses AI. Check for mistakes.
Comment on lines +13 to +15
# If server jar already exists, assume setup completed and exit
if [ -f "/workspace/hytale-downloader/Server/HytaleServer.jar" ]; then
echo "Server already set up (HytaleServer.jar found)."
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The early-exit check only looks for HytaleServer.jar, but the launcher also requires Assets.zip. If Assets.zip is missing/corrupt, this script will still skip setup and the server start will fail later. Consider validating both artifacts (and possibly their sizes/checksums) before exiting successfully.

Suggested change
# If server jar already exists, assume setup completed and exit
if [ -f "/workspace/hytale-downloader/Server/HytaleServer.jar" ]; then
echo "Server already set up (HytaleServer.jar found)."
# If required server artifacts already exist, assume setup completed and exit
if [ -s "/workspace/hytale-downloader/Server/HytaleServer.jar" ] && [ -s "/workspace/hytale-downloader/Server/Assets.zip" ]; then
echo "Server already set up (HytaleServer.jar and Assets.zip found)."

Copilot uses AI. Check for mistakes.
Comment on lines +38 to 40
echo "Inflating $DOWNLOADER_ZIP into $OUTPUT_DIR"
unzip -o "$DOWNLOADER_ZIP" -d "$OUTPUT_DIR" || true

Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unzip ... || true will hide extraction failures and still print "Deployment setup complete!" even if nothing was inflated. This makes setup flaky and hard to diagnose; consider letting unzip failures fail the script and/or explicitly verifying that Server/HytaleServer.jar and Assets.zip exist after extraction (and erroring out if not).

Copilot uses AI. Check for mistakes.
Comment on lines +65 to +76
// Check baby mapping adults
val isMappedAdult = babyMappings.any { it.adult == npcName }

if (matchingGroup != null || isMappedAdult) {
if (matchingGroup?.breedingGroup.isNullOrEmpty()) {
LOGGER.at(java.util.logging.Level.WARNING).log("Skipping $npcName since it has no valid breeding group")
return
}

val worldTimeResource = store.getResource(WorldTimeResource.getResourceType())
val comp = AnimalsBreedComponent(worldTimeResource.gameTime, matchingGroup!!.breedingGroup!!)

Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isMappedAdult doesn't work as written: when matchingGroup is null but isMappedAdult is true, the matchingGroup?.breedingGroup.isNullOrEmpty() check will return true and this method will return early, so mapped-only adults never get a component. Either remove isMappedAdult or derive a valid breeding group for that case. Also, store.getResource(WorldTimeResource.getResourceType()) appears to be nullable elsewhere; accessing .gameTime without a null-check can crash.

Copilot uses AI. Check for mistakes.
print("DEBUG: Found server jar at {}. Using it.".format(server_jar))
ctx.symlink(server_jar, "HytaleServer.jar")
else:
ctx.fail("HytaleServer.jar not found in .local-assets or workspace; run the setup script to download it into /workspace/server")
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The failure message references downloading into /workspace/server, but this rule now looks for the jar under hytale-downloader/Server/HytaleServer.jar. Updating the error message to match the actual expected location will make setup/debugging much clearer.

Suggested change
ctx.fail("HytaleServer.jar not found in .local-assets or workspace; run the setup script to download it into /workspace/server")
ctx.fail("HytaleServer.jar not found in .local-assets or workspace; run the setup script to download it into hytale-downloader/Server/HytaleServer.jar")

Copilot uses AI. Check for mistakes.
Comment on lines +27 to +28
val AnimalsGrowPlugin: AnimalsGrow = AnimalsGrow(init)
val AnimalsBreedPlugin: AnimalsBreed = AnimalsBreed(init)
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These properties are named with UpperCamelCase, which is inconsistent with Kotlin/property naming conventions used elsewhere in the repo. Renaming to lowerCamelCase (e.g., animalsGrowPlugin, animalsBreedPlugin) will improve readability and avoid lint/style issues.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants