mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
Ender Dragon spawn egg: vanilla random order and the dragon's own random
EntityType.create draws the wrapped spawn yaw and Mob.finalizeSpawn the follow-range triangle and the left-handed roll from the level random; the dragon seeds its own random (Entity.random), not from the level one. test_spawn_egg_fluid_parity gains the dragon egg used on a block. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
aa19826c39
commit
d7e7b92735
2 files changed
+20
-11
No files matched your search
@@ -4177,18 +4177,25 @@ impl Game<'_> {
|
||||
true
|
||||
}
|
||||
|
||||
/// Create an Ender Dragon for a scripted spawn such as a spawn egg or a
|
||||
/// dispenser. Unlike the End fight's dragon, this one is not assigned to
|
||||
/// the fight UUID and can therefore be summoned in any dimension.
|
||||
/// `EntityType.create` for an Ender Dragon from a spawn egg, by hand or from a dispenser
|
||||
/// (`SpawnEggItem.spawnMob`, `SpawnEggItemBehavior`). Unlike the End fight's dragon, this
|
||||
/// one is not the fight's (`EnderDragon.aiStep` adopts it only when its UUID is the fight's),
|
||||
/// so it can be spawned in any dimension. Horizon keeps one dragon per level, as `/summon`
|
||||
/// and loading do: with one already there, nothing spawns and the egg stays.
|
||||
pub(super) fn spawn_dragon_spawned(&mut self, at: [f64; 3]) -> Option<u32> {
|
||||
// Horizon currently keeps one simulated dragon per level, matching
|
||||
// the existing `/summon`/save representation.
|
||||
if self.dragon.is_some() {
|
||||
return None;
|
||||
}
|
||||
let position = Vec3::new(at[0], at[1], at[2]);
|
||||
let yaw = self.world.random.next_float() * 360.0;
|
||||
let seed = self.world.random.next_long();
|
||||
// EntityType.create: `snapTo(.., Mth.wrapDegrees(level.getRandom().nextFloat() * 360))`.
|
||||
let yaw = horizon_client::camera::wrap_degrees(self.world.random.next_float() * 360.0);
|
||||
// Mob.finalizeSpawn (EnderDragon keeps it): the follow range's
|
||||
// `random.triangle(0, 0.11485)`, then `setLeftHanded(nextFloat() < 0.05)`, from the
|
||||
// level's random. Neither changes how the dragon flies.
|
||||
let _ = self.world.random.triangle(0.0, 0.114_850_000_000_000_01);
|
||||
let _ = self.world.random.next_float();
|
||||
// The dragon's own random (`Entity.random`), not the level's.
|
||||
let seed = super::dispenser::entity_random().next_long();
|
||||
let mut dragon = Dragon::new(position, yaw, seed);
|
||||
dragon.id = self.next_entity + 1;
|
||||
self.next_entity += 9;
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
Fluid cases send UseItem into a deep pool; a UseItemOn control has a mob
|
||||
under the last look direction. Compare spawn, egg count and used stat. Covers
|
||||
lava/water sources, flowing lava, a solid obstruction, waterlogged blocks,
|
||||
creative, adventure (with/without can_place_on) and peaceful monster eggs.
|
||||
creative, adventure (with/without can_place_on) and peaceful monster eggs, and the
|
||||
Ender Dragon's egg on a block (Horizon simulates the dragon apart from other mobs).
|
||||
"""
|
||||
import json
|
||||
try:
|
||||
@@ -24,6 +25,7 @@ CASES = [
|
||||
('adventure-allowed', 'lava', 'strider', 'adventure',
|
||||
'[minecraft:can_place_on={blocks:"minecraft:lava"}]', True),
|
||||
('peaceful', 'lava', 'zombie', 'survival', '', False),
|
||||
('block-use-dragon', 'stone', 'ender_dragon', 'survival', '', True),
|
||||
]
|
||||
SCRIPT = [("setup", ["chat on", "cmd Alice gamerule spawn_mobs false"])]
|
||||
previous_mode = "creative"
|
||||
@@ -37,15 +39,15 @@ for name, block, mob, mode, component, spawn in CASES:
|
||||
'cmd Alice fill -2 74 -2 6 80 6 minecraft:stone',
|
||||
'cmd Alice fill -2 81 -2 6 85 6 minecraft:air',
|
||||
f'cmd Alice fill 0 75 0 4 80 4 minecraft:{block}',
|
||||
f'cmd Alice tp @s 2.5 81 -0.5 0 {0 if name == "block-use" else 50}',
|
||||
*(['cmd Alice summon minecraft:strider 2.5 81 1.5 {NoAI:1b}'] if name == 'block-use' else []),
|
||||
f'cmd Alice tp @s 2.5 81 -0.5 0 {0 if name.startswith("block-use") else 50}',
|
||||
*(['cmd Alice summon minecraft:strider 2.5 81 1.5 {NoAI:1b}'] if name.startswith('block-use') else []),
|
||||
f'cmd Alice give @s {egg}{component} 8',
|
||||
'cmd Alice scoreboard objectives remove eggs',
|
||||
f'cmd Alice scoreboard objectives add eggs minecraft.used:minecraft.{mob}_spawn_egg',
|
||||
*([f'cmd Alice gamemode {mode}'] if mode != 'creative' else []),
|
||||
]
|
||||
previous_mode = mode
|
||||
SCRIPT += [(name + '-setup', setup), (name + '-use', ['use-on Alice 4 80 -1' if name == 'block-use' else 'use Alice 50']),
|
||||
SCRIPT += [(name + '-setup', setup), (name + '-use', ['use-on Alice 4 80 -1' if name.startswith('block-use') else 'use Alice 50']),
|
||||
(name + '-check', [
|
||||
f'cmd Alice execute {"if" if spawn else "unless"} entity @e[type=minecraft:{mob}]',
|
||||
f'cmd Alice clear @s {egg} 0',
|
||||
|
||||
Reference in new issue
Block a user