Skip to content

Commit

Permalink
NPC chat system cleanup (#2465)
Browse files Browse the repository at this point in the history
* Only parse MM once in `talkToBystanders`

* Initial move

* Cleanup + Update logic

* Update + cleanup `DenizenSpeechContext`

* Avoid recreating the tag context + stary newline
  • Loading branch information
tal5 committed Apr 23, 2023
1 parent 403e0fe commit 32be8ce
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 204 deletions.

This file was deleted.

Expand Up @@ -5,14 +5,12 @@

public class DenizenSpeechContext extends SpeechContext {

private ScriptEntry scriptEntry;
private boolean bystandersEnabled;
private double chatRange;
private final ScriptEntry scriptEntry;
private final double chatRange;

public DenizenSpeechContext(String message, ScriptEntry scriptEntry, double chatRange) {
setMessage(message);
super(message);
this.scriptEntry = scriptEntry;
this.bystandersEnabled = chatRange >= 0;
this.chatRange = chatRange;
}

Expand All @@ -21,7 +19,7 @@ public ScriptEntry getScriptEntry() {
}

public boolean isBystandersEnabled() {
return bystandersEnabled;
return chatRange >= 0;
}

public double getChatRange() {
Expand Down

This file was deleted.

@@ -1,21 +1,30 @@
package com.denizenscript.denizen.scripts.commands.player;

import com.denizenscript.denizen.npc.speech.DenizenSpeechContext;
import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizen.objects.NPCTag;
import com.denizenscript.denizen.objects.PlayerTag;
import com.denizenscript.denizen.tags.BukkitTagContext;
import com.denizenscript.denizen.utilities.PaperAPITools;
import com.denizenscript.denizen.utilities.Settings;
import com.denizenscript.denizen.utilities.Utilities;
import com.denizenscript.denizencore.exceptions.InvalidArgumentsRuntimeException;
import com.denizenscript.denizencore.scripts.commands.generator.*;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizen.utilities.Settings;
import com.denizenscript.denizen.npc.speech.DenizenSpeechContext;
import com.denizenscript.denizen.npc.speech.DenizenSpeechController;
import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.scripts.ScriptEntry;
import com.denizenscript.denizencore.scripts.commands.AbstractCommand;
import com.denizenscript.denizencore.scripts.commands.generator.*;
import com.denizenscript.denizencore.scripts.queues.ScriptQueue;
import com.denizenscript.denizencore.tags.TagContext;
import com.denizenscript.denizencore.tags.TagManager;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import net.citizensnpcs.api.ai.speech.Talkable;
import net.citizensnpcs.api.ai.speech.TalkableEntity;
import net.citizensnpcs.api.ai.speech.event.NPCSpeechEvent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;

import java.util.Collections;
import java.util.List;
import java.util.*;

public class ChatCommand extends AbstractCommand {

Expand Down Expand Up @@ -117,11 +126,95 @@ public static void autoExecute(ScriptEntry scriptEntry,
Entity entity = talker.getBukkitEntity();
if (entity != null) {
context.setTalker(entity);
new DenizenSpeechController(entity).speak(context);
speak(context);
}
else {
Debug.echoDebug(scriptEntry, "Chat Talker is not spawned! Cannot talk.");
}
}
}

public static void speak(DenizenSpeechContext speechContext) {
Entity talker = speechContext.getTalker().getEntity();
if (EntityTag.isCitizensNPC(talker)) {
NPCSpeechEvent event = new NPCSpeechEvent(speechContext);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
}
ScriptQueue queue = speechContext.getScriptEntry().getResidingQueue();
ObjectTag defTalker = queue.getDefinitionObject("talker");
ObjectTag defMessage = queue.getDefinitionObject("message");
queue.addDefinition("talker", new EntityTag(talker));
queue.addDefinition("message", new ElementTag(speechContext.getMessage(), true));
talk(speechContext, queue);
if (defMessage != null) {
queue.addDefinition("message", defMessage);
}
if (defTalker != null) {
queue.addDefinition("talker", defTalker);
}
}

private static void talk(DenizenSpeechContext speechContext, ScriptQueue queue) {
TagContext tagContext = new BukkitTagContext(speechContext.getScriptEntry());
if (!speechContext.hasRecipients()) {
String text = TagManager.tag(Settings.chatNoTargetFormat(), tagContext);
talkToBystanders(text, speechContext);
return;
}
String text = PaperAPITools.instance.convertTextToMiniMessage(TagManager.tag(Settings.chatToTargetFormat(), tagContext), true);
for (Talkable entity : speechContext) {
entity.talkTo(speechContext, text);
}
if (!speechContext.isBystandersEnabled()) {
return;
}
if (speechContext.size() == 1) {
ObjectTag defTarget = queue.getDefinitionObject("target");
queue.addDefinition("target", new EntityTag(speechContext.iterator().next().getEntity()));
talkToBystanders(TagManager.tag(Settings.chatWithTargetToBystandersFormat(), tagContext), speechContext);
if (defTarget != null) {
queue.addDefinition("target", defTarget);
}
return;
}
String[] format = Settings.chatMultipleTargetsFormat().split("%target%");
if (format.length <= 1) {
Debug.echoError("Invalid 'Commands.Chat.Options.Multiple targets format' in config.yml! Must have at least 1 %target%");
}
StringBuilder parsed = new StringBuilder();
int i = 0;
for (Talkable target : speechContext) {
parsed.append(format[i]);
if (i == format.length - 1) {
break;
}
parsed.append(new EntityTag(target.getEntity()).getName());
i++;
}
String targets = TagManager.tag(parsed.toString(), tagContext);
ObjectTag defTargets = queue.getDefinitionObject("targets");
queue.addDefinition("targets", new ElementTag(targets, true));
String bystanderText = TagManager.tag(Settings.chatWithTargetsToBystandersFormat(), tagContext);
talkToBystanders(bystanderText, speechContext);
if (defTargets != null) {
queue.addDefinition("targets", defTargets);
}
}

private static void talkToBystanders(String text, DenizenSpeechContext speechContext) {
Set<UUID> recipients = new HashSet<>(speechContext.size());
for (Talkable recipient : speechContext) {
recipients.add(recipient.getEntity().getUniqueId());
}
String parsedText = PaperAPITools.instance.convertTextToMiniMessage(text, true);
double range = speechContext.getChatRange();
for (Entity bystander : range == 0d ? Bukkit.getOnlinePlayers() : speechContext.getTalker().getEntity().getNearbyEntities(range, range, range)) {
if (!recipients.contains(bystander.getUniqueId())) {
new TalkableEntity(bystander).talkNear(speechContext, parsedText);
}
}
}
}

0 comments on commit 32be8ce

Please sign in to comment.