From c9242463d26ca01fab93b3247e64246c97253882 Mon Sep 17 00:00:00 2001 From: Jayly <65847850+JaylyDev@users.noreply.github.com> Date: Sun, 2 Jun 2024 14:57:35 +0100 Subject: [PATCH] dummy sensor rewrite to scripting --- assets/behavior_pack/entities/dummy.json | 41 ------------ assets/behavior_pack/entities/terminator.json | 22 ------- package-lock.json | 3 +- src/death-message/rawTextGenerator.ts | 2 +- src/dummyEntity/navigationDetect.ts | 38 +++++++++++ src/dummyEntity/spreadDummies.ts | 66 +++++++++++++++++++ src/index.ts | 1 + src/terminator/initialization.ts | 22 +++++-- src/terminator/terminator.ts | 1 + 9 files changed, 124 insertions(+), 72 deletions(-) create mode 100644 src/dummyEntity/navigationDetect.ts create mode 100644 src/dummyEntity/spreadDummies.ts diff --git a/assets/behavior_pack/entities/dummy.json b/assets/behavior_pack/entities/dummy.json index 2460905..f1a322a 100644 --- a/assets/behavior_pack/entities/dummy.json +++ b/assets/behavior_pack/entities/dummy.json @@ -73,34 +73,6 @@ "fire_affected_by_griefing": false, "max_resistance": 3.40282e38 } - }, - "dummy:detect_terminator": { - "minecraft:entity_sensor": { - "subsensors": [ - { - "event_filters": { - "all_of": [ - { - "test": "is_family", - "subject": "other", - "operator": "equals", - "value": "terminator" - } - ] - }, - "minimum_count": 1, - "maximum_count": 32767, - "range": [10, 10], - "require_all": true, - "event": "dummy:request_despawn" - } - ] - } - }, - "dummy:despawn": { - "minecraft:instant_despawn": { - "remove_child_entities": true - } } }, "components": { @@ -158,9 +130,6 @@ "dummy:request_pathfind": { "set_property": { "dummy:task_type": 2 - }, - "add": { - "component_groups": ["dummy:detect_terminator"] } }, "dummy:request_spawning_alex": { @@ -172,16 +141,6 @@ "set_property": { "dummy:task_type": 4 } - }, - "dummy:request_despawn": { - "add": { - "component_groups": ["dummy:despawn"] - }, - "queue_command": { - "command": [ - "tellraw @a[tag=dev] {\"rawtext\":[{\"text\": \"[\"},{\"selector\": \"@s\"}, {\"text\": \"] dummy:request_despawn\"}]}" - ] - } } } } diff --git a/assets/behavior_pack/entities/terminator.json b/assets/behavior_pack/entities/terminator.json index a54d71b..73d7428 100644 --- a/assets/behavior_pack/entities/terminator.json +++ b/assets/behavior_pack/entities/terminator.json @@ -638,28 +638,6 @@ "priority": 1, "track_target": true, "speed_multiplier": 1.0 - }, - "minecraft:entity_sensor": { - "subsensors": [ - { - "event_filters": { - "all_of": [ - { "test": "is_family", "subject": "other", "value": "dummy" }, - { - "test": "int_property", - "subject": "other", - "domain": "dummy:task_type", - "value": 2 - } - ] - }, - "minimum_count": 1, - "maximum_count": 32767, - "range": [10, 10], - "require_all": true, - "event": "terminator:remove_escape" - } - ] } }, "terminator:find_end_portal": { diff --git a/package-lock.json b/package-lock.json index e076db2..236de50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -531,7 +531,8 @@ "node_modules/@minecraft/common": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@minecraft/common/-/common-1.2.0.tgz", - "integrity": "sha512-JdmEq4P3Z/FtoBzhLijFgMSVFnFRrUoLwY8DHHrgtFo0mfLTOLTB1RErYjLMsA6b7BGVNxkX/pfFRiH7QZ0XwQ==" + "integrity": "sha512-JdmEq4P3Z/FtoBzhLijFgMSVFnFRrUoLwY8DHHrgtFo0mfLTOLTB1RErYjLMsA6b7BGVNxkX/pfFRiH7QZ0XwQ==", + "license": "MIT" }, "node_modules/@minecraft/math": { "version": "1.3.5", diff --git a/src/death-message/rawTextGenerator.ts b/src/death-message/rawTextGenerator.ts index 1422e64..7f8dd77 100644 --- a/src/death-message/rawTextGenerator.ts +++ b/src/death-message/rawTextGenerator.ts @@ -29,7 +29,7 @@ function rawMessageTranslator( } const ids: RawMessage[] = [deadEntityRawMessage]; - if (damagingEntity && damagingEntity.nameTag) + if (damagingEntity?.isValid() && damagingEntity.nameTag) ids.push({ text: damagingEntity.nameTag, }); diff --git a/src/dummyEntity/navigationDetect.ts b/src/dummyEntity/navigationDetect.ts new file mode 100644 index 0000000..808e2e5 --- /dev/null +++ b/src/dummyEntity/navigationDetect.ts @@ -0,0 +1,38 @@ +import { Entity, system, world } from "@minecraft/server"; +import { terminatorDie } from "../terminator-events/onTerminatorDie"; + +const overworld = world.getDimension("overworld"); + +system.runInterval(() => { + for (const dummyEntity of overworld.getEntities({ type: "entity:dummy" })) { + const navigator = dummyEntity.getDynamicProperty("terminator:navigator") as + | string + | undefined; + if (!navigator) continue; + + // Check if the navigator still exists, and whether they are within 5 blocks + const terminator: Entity | undefined = world.getEntity(navigator); + if ( + terminator && + terminator.matches({ + location: dummyEntity.location, + minDistance: 0, + maxDistance: 8, + }) + ) { + dummyEntity.remove(); + terminator.triggerEvent("terminator:remove_escape"); + } + } +}); + +// remove dummy when terminator dies +terminatorDie.subscribe(({ deadEntity }) => { + const dummyEntity = overworld + .getEntities({ type: "entity:dummy" }) + .find( + (entity) => + entity.getDynamicProperty("terminator:navigator") === deadEntity.id + ); + dummyEntity?.remove(); +}); diff --git a/src/dummyEntity/spreadDummies.ts b/src/dummyEntity/spreadDummies.ts new file mode 100644 index 0000000..2f73dc7 --- /dev/null +++ b/src/dummyEntity/spreadDummies.ts @@ -0,0 +1,66 @@ +import { VECTOR3_DOWN, Vector3Utils } from "@minecraft/math"; +import { Dimension, Vector3 } from "@minecraft/server"; + +interface LocationXZ { + x: number; + z: number; +} + +// reference +// function normalDistribution(x: number, mean: number, stdev: number): number { +// if (stdev <= 0) { +// throw new Error("Standard deviation must be positive"); +// } +// const exponent = -Math.pow(x - mean, 2) / (2 * Math.pow(stdev, 2)); +// const coefficient = 1 / (stdev * Math.sqrt(2 * Math.PI)); +// const probability = coefficient * Math.exp(exponent); +// return probability; +// } + +// https://minecraft.wiki/w/Commands/spreadplayers#Usage +function inverseNormalDistribution( + prob: number, + mean: number, + stdev: number +): number { + const coefficient = 1 / (stdev * Math.sqrt(2 * Math.PI)); + const exponent = Math.log(prob / coefficient); + const x = Math.sqrt(-(exponent * (2 * Math.pow(stdev, 2)))) + mean; + return x; +} + +/** + * @returns y coordinate + */ +function findLocationHeight( + location: LocationXZ, + dimension: Dimension +): number { + const heightRange = dimension.heightRange; + let found = false; + let attempts = 5; + while (!found && attempts > 0) { + // random y between min and max height range + const y = + inverseNormalDistribution(Math.random(), 0, 0.15) * + (heightRange.max - heightRange.min - 2); + const blockLocation: Vector3 = { x: location.x, y, z: location.z }; + const ray = dimension.getBlockFromRay(blockLocation, VECTOR3_DOWN); + if (ray && Vector3Utils.distance(ray.block.location, blockLocation) > 2) { + found = true; + return ray.block.location.y + 1; + } else attempts--; + } + return heightRange.max - 1; +} + +/** + * Find a y level that has multiple air blocks + */ +export function getSpreadLocation( + location: LocationXZ, + dimension: Dimension +): Vector3 { + const y = findLocationHeight(location, dimension); + return { x: location.x, y, z: location.z }; +} diff --git a/src/index.ts b/src/index.ts index aa90431..55d8ef8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,6 +11,7 @@ import "./terminator/suffocation"; import "./terminator/rangedAttack"; import "./commands/index"; import "./guide/index"; +import "./dummyEntity/navigationDetect"; // Debug Features if (debugEnabled) { diff --git a/src/terminator/initialization.ts b/src/terminator/initialization.ts index 0dcad9b..2cf9624 100644 --- a/src/terminator/initialization.ts +++ b/src/terminator/initialization.ts @@ -8,6 +8,9 @@ import { import { terminatorSpawn } from "../terminator-events/onTerminatorSpawn"; import { MinecraftEffectTypes } from "@minecraft/vanilla-data"; import { MinecraftColor } from "../minecraft-color"; +import { TerminatorEntity } from "./terminator"; +import { getSpreadLocation } from "../dummyEntity/spreadDummies"; +import { debugEnabled } from "../config"; // naming tag terminatorSpawn.subscribe(({ entity }) => { @@ -29,7 +32,7 @@ terminatorSpawn.subscribe(({ entity }) => { if (terminatorsWithSameName.length > 0) entity.nameTag = `${nameTag} (${terminatorsWithSameName.length})`; } - + // broadcast to world const rawtext: RawText = { rawtext: [ @@ -77,14 +80,19 @@ terminatorSpawn.subscribe(({ entity }) => { } ); - const dummyEntity = entity.dimension.spawnEntity( - "entity:dummy", - entity.location + // Trigger terminator to pathfind to a random location within 32-48 block radius + const terminator = new TerminatorEntity(entity); + const locationOffsetXZ = { + x: Math.floor(Math.random() * 32 - 17 + terminator.location.x), + z: Math.floor(Math.random() * 32 - 17 + terminator.location.z), + }; + const locationOffset = getSpreadLocation( + locationOffsetXZ, + entity.dimension ); - dummyEntity.runCommand("spreadplayers ~ ~ 32 48 @s"); - dummyEntity.triggerEvent("dummy:request_pathfind"); + if (debugEnabled) terminator.chat(`I'm going to ${locationOffset.x}, ${locationOffset.y}, ${locationOffset.z}!`); + terminator.navigateToLocation(locationOffset); - entity.triggerEvent("terminator:escape"); triggered = true; } }); diff --git a/src/terminator/terminator.ts b/src/terminator/terminator.ts index b85730d..ee15517 100644 --- a/src/terminator/terminator.ts +++ b/src/terminator/terminator.ts @@ -378,6 +378,7 @@ export class TerminatorEntity implements Entity { navigateToLocation(location: Vector3): void { const dummyEntity = this.dimension.spawnEntity("entity:dummy", location); dummyEntity.triggerEvent("dummy:request_pathfind"); + dummyEntity.setDynamicProperty("terminator:navigator", this.id); this.triggerEvent("terminator:escape"); } }