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

Dragon tags & mechs #2620

Open
wants to merge 10 commits into
base: dev
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package com.denizenscript.denizen.paper.properties;

import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizen.objects.LocationTag;
import com.denizenscript.denizen.objects.WorldTag;
import com.denizenscript.denizen.utilities.BukkitImplDeprecations;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
import org.bukkit.boss.DragonBattle;

public class PaperWorldExtensions {

Expand All @@ -23,6 +29,81 @@ public static void register() {
return new ElementTag(world.getWorld().getNoTickViewDistance());
});

if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) {

// <--[tag]
mcmonkey4eva marked this conversation as resolved.
Show resolved Hide resolved
// @attribute <WorldTag.gateway_count>
// @returns ElementTag(Number)
// @description
// Returns the number of end gateway portals.
// Only works in end worlds.
Copy link
Member

Choose a reason for hiding this comment

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

Minor nitpick, but in sounds more like the player being in an end world while the script is running or something - maybe on, for, if the world is an end world, etc.?

// -->
WorldTag.tagProcessor.registerTag(ElementTag.class, "gateway_count", (attribute, object) -> {
DragonBattle battle = object.getWorld().getEnderDragonBattle();
if (battle == null) {
attribute.echoError("Provided world is not an end world!");
return null;
}
return new ElementTag(battle.getGatewayCount());
});

// <--[tag]
// @attribute <WorldTag.healing_crystals>
// @returns ListTag(EntityTag)
// @description
// Returns a ListTag of the healing crystals located on top of the obsidian towers.
Copy link
Member

Choose a reason for hiding this comment

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

I'd mention ender/end crystals as a search aid or in the description somewhere, healing crystals is technically right but most people probably won't know them by that name.

// Only works in end worlds.
// -->
WorldTag.tagProcessor.registerTag(ListTag.class, "healing_crystals", (attribute, object) -> {
DragonBattle battle = object.getWorld().getEnderDragonBattle();
if (battle == null) {
attribute.echoError("Provided world is not an end world!");
return null;
}
return new ListTag(battle.getHealingCrystals(), EntityTag::new);
});

// <--[tag]
// @attribute <WorldTag.healing_crystals>
Copy link
Member

Choose a reason for hiding this comment

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

Wrong tag name

// @returns ListTag(EntityTag)
// @description
// Returns a ListTag of the respawn crystals located at the end exit portal.
// Only works in end worlds.
// -->
WorldTag.tagProcessor.registerTag(ListTag.class, "respawn_crystals", (attribute, object) -> {
DragonBattle battle = object.getWorld().getEnderDragonBattle();
if (battle == null) {
attribute.echoError("Provided world is not an end world!");
return null;
}
return new ListTag(battle.getRespawnCrystals(), EntityTag::new);
});

// <--[mechanism]
// @object WorldTag
// @name spawn_gateway
// @input LocationTag
// @Plugin Paper
// @group paper
// @description
// If no location is specified, tries to spawn a new end gateway using default game mechanics. Otherwise, spawns a new end gateway portal at the specified location.
Copy link
Member

Choose a reason for hiding this comment

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

Nitpick, but meta is usually the other way around (spawns gateway at specified location, specify no input to spawn vanilla one)

// Only works in end worlds.
// -->
WorldTag.tagProcessor.registerMechanism("spawn_gateway", false, (object, mechanism) -> {
DragonBattle battle = object.getWorld().getEnderDragonBattle();
if (battle == null) {
mechanism.echoError("Cannot spawn gateway in non-end world!");
return;
mcmonkey4eva marked this conversation as resolved.
Show resolved Hide resolved
}
if (!mechanism.hasValue()) {
battle.spawnNewGateway();
}
else if (mechanism.requireObject(LocationTag.class)) {
battle.spawnNewGateway(mechanism.getValue().asType(LocationTag.class, mechanism.context));
Copy link
Member

Choose a reason for hiding this comment

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

There should be a #valueAsType iirc?

}
});
}

// <--[mechanism]
// @object WorldTag
// @name view_distance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.denizenscript.denizen.events.BukkitScriptEvent;
import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.nms.abstracts.BiomeNMS;
import com.denizenscript.denizen.utilities.flags.WorldFlagHandler;
import com.denizenscript.denizencore.flags.AbstractFlagTracker;
Expand Down Expand Up @@ -837,6 +838,7 @@ else if (time >= 12500) {
registerTag(LocationTag.class, "dragon_portal_location", (attribute, object) -> {
DragonBattle battle = object.getWorld().getEnderDragonBattle();
if (battle == null) {
attribute.echoError("Provided world is not an end world!");
return null;
}
if (battle.getEndPortalLocation() == null) {
Expand Down Expand Up @@ -1006,6 +1008,92 @@ else if (time >= 12500) {
registerTag(ElementTag.class, "is_night", (attribute, world) -> {
return new ElementTag(NMSHandler.worldHelper.isNight(world.getWorld()));
});

// <--[tag]
// @attribute <WorldTag.first_dragon_killed>
// @returns ElementTag(Boolean)
// @description
// Returns whether the ender dragon has been killed in this world before.
// Only works in end worlds.
// -->
registerTag(ElementTag.class, "first_dragon_killed", (attribute, object) -> {
DragonBattle battle = object.getWorld().getEnderDragonBattle();
if (battle == null) {
attribute.echoError("Provided world is not an end world!");
return null;
}
return new ElementTag(battle.hasBeenPreviouslyKilled());
});

// <--[mechanism]
// @object WorldTag
// @name respawn_dragon
// @description
// Initiates the respawn sequence of the ender dragon as if a player placed 4 end crystals on the portal.
// Only works in end worlds.
// -->
tagProcessor.registerMechanism("respawn_dragon", false, (object, mechanism) -> {
DragonBattle battle = object.getWorld().getEnderDragonBattle();
if (battle == null) {
mechanism.echoError("Provided world is not an end world!");
return;
}
battle.initiateRespawn();
});

// <--[mechanism]
// @object WorldTag
// @name reset_crystals
// @description
// Resets the end crystals located on the obsidian pillars in this world.
// Only works in end worlds.
// -->
tagProcessor.registerMechanism("reset_crystals", false, (object, mechanism) -> {
DragonBattle battle = object.getWorld().getEnderDragonBattle();
if (battle == null) {
mechanism.echoError("Provided world is not an end world!");
return;
mcmonkey4eva marked this conversation as resolved.
Show resolved Hide resolved
}
battle.resetCrystals();
});

// <--[mechanism]
// @object WorldTag
// @name respawn_phase
// @input ElementTag
// @description
// Set the current respawn phase of the ender dragon. Valid phases can be found at <@link url https://jd.papermc.io/paper/1.20/org/bukkit/boss/DragonBattle.RespawnPhase.html>
Copy link
Member

Choose a reason for hiding this comment

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

Link doesn't seem to work?

// Only works in end worlds.
// -->
tagProcessor.registerMechanism("respawn_phase", false, ElementTag.class, (object, mechanism, input) -> {
DragonBattle battle = object.getWorld().getEnderDragonBattle();
if (battle == null) {
mechanism.echoError("Provided world is not an end world!");
return;
}
battle.setRespawnPhase(input.asEnum(DragonBattle.RespawnPhase.class));
});
Copy link
Member

Choose a reason for hiding this comment

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

Needs Mechanism#requireEnum


if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) {

// <--[mechanism]
// @object WorldTag
// @name respawn_phase
Copy link
Member

Choose a reason for hiding this comment

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

Wrong name

// @input ElementTag(Boolean)
// @description
// Set whether the first ender dragon was killed already.
// Only works in end worlds.
Copy link
Member

Choose a reason for hiding this comment

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

Might be nice to document exactly what this does - does it reset the end and respawn the dragon? is it just a value that doesn't really affect anything?

// -->
tagProcessor.registerMechanism("first_dragon_killed", false, ElementTag.class, (object, mechanism, input) -> {
DragonBattle battle = object.getWorld().getEnderDragonBattle();
if (battle == null) {
mechanism.echoError("Provided world is not an end world!");
return;
}
battle.setPreviouslyKilled(input.asBoolean());
});
Copy link
Member

Choose a reason for hiding this comment

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

Needs Mechanism#requireBoolean

}

}

public static ObjectTagProcessor<WorldTag> tagProcessor = new ObjectTagProcessor<>();
Expand Down