From 773bacf8205a38eac651f3442cf72bbe37860ccc Mon Sep 17 00:00:00 2001 From: GlassSpirit Date: Sat, 7 Dec 2019 20:40:07 +0300 Subject: [PATCH] Add scripted dialogs, UI for modifying additional npc data and availability level check --- gradle.properties | 4 +- .../glassspirit/cnpcntrpg/Configuration.java | 5 +- .../cnpcntrpg/forge/DataNpcRpg.java | 71 ++++++++++++++ .../cnpcntrpg/mixin/IMixinDataStats.java | 9 ++ .../cnpcntrpg/mixin/IMixinDialog.java | 19 ++++ .../cnpcntrpg/mixin/IMixinDialogOption.java | 9 ++ .../mixin/impl/MixinAvailablilty.java | 26 +++++ .../mixin/{ => impl}/MixinCustomNpcs.java | 2 +- .../mixin/{ => impl}/MixinDataInventory.java | 2 +- .../mixin/{ => impl}/MixinDataStats.java | 7 +- .../cnpcntrpg/mixin/impl/MixinDialog.java | 54 ++++++++++ .../mixin/impl/MixinDialogOption.java | 71 ++++++++++++++ .../{ => impl}/MixinEntityNPCInterface.java | 2 +- .../mixin/impl/MixinNoppesUtilPlayer.java | 98 +++++++++++++++++++ .../mixin/impl/MixinNoppesUtilServer.java | 72 ++++++++++++++ .../mixin/impl/MixinPacketHandlerServer.java | 50 ++++++++++ .../{ => impl}/MixinScriptContainer.java | 2 +- .../cnpcntrpg/sponge/CnpcRpgSponge.java | 5 +- .../cnpcntrpg/sponge/Commands.java | 51 ++++++++++ src/main/resources/mixins.cnpcntrpg.json | 8 +- 20 files changed, 556 insertions(+), 11 deletions(-) create mode 100644 src/main/java/ru/glassspirit/cnpcntrpg/forge/DataNpcRpg.java create mode 100644 src/main/java/ru/glassspirit/cnpcntrpg/mixin/IMixinDataStats.java create mode 100644 src/main/java/ru/glassspirit/cnpcntrpg/mixin/IMixinDialog.java create mode 100644 src/main/java/ru/glassspirit/cnpcntrpg/mixin/IMixinDialogOption.java create mode 100644 src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinAvailablilty.java rename src/main/java/ru/glassspirit/cnpcntrpg/mixin/{ => impl}/MixinCustomNpcs.java (93%) rename src/main/java/ru/glassspirit/cnpcntrpg/mixin/{ => impl}/MixinDataInventory.java (97%) rename src/main/java/ru/glassspirit/cnpcntrpg/mixin/{ => impl}/MixinDataStats.java (83%) create mode 100644 src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDialog.java create mode 100644 src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDialogOption.java rename src/main/java/ru/glassspirit/cnpcntrpg/mixin/{ => impl}/MixinEntityNPCInterface.java (94%) create mode 100644 src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinNoppesUtilPlayer.java create mode 100644 src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinNoppesUtilServer.java create mode 100644 src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinPacketHandlerServer.java rename src/main/java/ru/glassspirit/cnpcntrpg/mixin/{ => impl}/MixinScriptContainer.java (96%) diff --git a/gradle.properties b/gradle.properties index c69f7af..c9b426e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ modGroup=ru.glassspirit -modVersion=1.2 +modVersion=1.3 modBaseName=CNPC-NTRPG forgeVersion=1.12.2-14.23.5.2847 -spongeForgeVersion=1.12.2-2825-7.1.6 +spongeForgeVersion=1.12.2-2838-7.1.7-RC3928 mcpVersion=stable_39 diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/Configuration.java b/src/main/java/ru/glassspirit/cnpcntrpg/Configuration.java index 7043559..71e5ea9 100644 --- a/src/main/java/ru/glassspirit/cnpcntrpg/Configuration.java +++ b/src/main/java/ru/glassspirit/cnpcntrpg/Configuration.java @@ -16,6 +16,9 @@ public class Configuration { public boolean NPC_KILLS_EXP_RPG = true; @Setting(value = "npc_kills_exp_minecraft", comment = "Minecraft experience for killing NPCs") - public boolean NPC_KILLS_EXP_MINECRAFT = true; + public boolean NPC_KILLS_EXP_MINECRAFT = false; + + @Setting(value = "availability_rpg_level", comment = "Use RPG character level for availability checks") + public boolean AVAILABILITY_RPG_LEVEL = true; } diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/forge/DataNpcRpg.java b/src/main/java/ru/glassspirit/cnpcntrpg/forge/DataNpcRpg.java new file mode 100644 index 0000000..2008aa4 --- /dev/null +++ b/src/main/java/ru/glassspirit/cnpcntrpg/forge/DataNpcRpg.java @@ -0,0 +1,71 @@ +package ru.glassspirit.cnpcntrpg.forge; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import noppes.npcs.controllers.ScriptContainer; +import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.entity.data.DataScript; +import ru.glassspirit.cnpcntrpg.mixin.IMixinDataStats; + +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; +import java.util.UUID; + +public class DataNpcRpg extends DataScript { + + public static final Map playersEditingRpgData = new HashMap<>(); + private static final Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + private EntityNPCInterface npc; + + public DataNpcRpg(EntityNPCInterface npc, boolean init) { + super(npc); + this.npc = npc; + if (init) { + setEnabled(true); + initNpcData(); + initProperties(); + } + } + + private void initNpcData() { + ScriptContainer mainContainer = new ScriptContainer(this); + mainContainer.appandConsole("This is RPG data of NPC."); + mainContainer.appandConsole("Do not create new tabs or attach scripts (THIS IS NOT A SCRIPTING GUI!!!)"); + mainContainer.appandConsole("1. First tab is for additional NPC data"); + mainContainer.appandConsole("2. Second tab is for default nt-rpg properties"); + + Map dataMap = new TreeMap<>(); + dataMap.put("Level", ((IMixinDataStats) npc.stats).getLevel()); + + mainContainer.script += gson.toJson(dataMap); + this.getScripts().add(mainContainer); + } + + private void initProperties() { + ScriptContainer container = new ScriptContainer(this); + + container.script += "properties doesn't work yet"; //TODO properties + this.getScripts().add(container); + } + + public void apply() { + applyNpcData(); + applyProperties(); + } + + private void applyNpcData() { + String data = this.getScripts().get(0).script; + Map dataMap = gson.fromJson(data, new TypeToken>() { + }.getType()); + + ((IMixinDataStats) npc.stats).setLevel(((Double) dataMap.get("Level")).intValue()); + } + + private void applyProperties() { + //TODO properties + } + +} diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/IMixinDataStats.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/IMixinDataStats.java new file mode 100644 index 0000000..b5d42e4 --- /dev/null +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/IMixinDataStats.java @@ -0,0 +1,9 @@ +package ru.glassspirit.cnpcntrpg.mixin; + +public interface IMixinDataStats { + + int getLevel(); + + void setLevel(int level); + +} diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/IMixinDialog.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/IMixinDialog.java new file mode 100644 index 0000000..140fbce --- /dev/null +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/IMixinDialog.java @@ -0,0 +1,19 @@ +package ru.glassspirit.cnpcntrpg.mixin; + +import net.minecraft.entity.player.EntityPlayer; +import noppes.npcs.controllers.data.Dialog; +import noppes.npcs.entity.EntityNPCInterface; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public interface IMixinDialog { + + Map playerTemporaryDialogMap = new HashMap<>(); + + boolean isScripted(); + + void processScripts(EntityPlayer player, EntityNPCInterface npc); + +} diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/IMixinDialogOption.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/IMixinDialogOption.java new file mode 100644 index 0000000..9f10f72 --- /dev/null +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/IMixinDialogOption.java @@ -0,0 +1,9 @@ +package ru.glassspirit.cnpcntrpg.mixin; + +public interface IMixinDialogOption { + + void setScript(Object script); + + Object getScript(); + +} diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinAvailablilty.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinAvailablilty.java new file mode 100644 index 0000000..28060c3 --- /dev/null +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinAvailablilty.java @@ -0,0 +1,26 @@ +package ru.glassspirit.cnpcntrpg.mixin.impl; + +import cz.neumimto.rpg.sponge.NtRpgPlugin; +import net.minecraft.entity.player.EntityPlayer; +import noppes.npcs.controllers.data.Availability; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import ru.glassspirit.cnpcntrpg.sponge.CnpcRpgSponge; + +@Mixin(value = Availability.class, remap = false) +public class MixinAvailablilty { + + @Shadow + public int minPlayerLevel; + + @Inject(method = "isAvailable(Lnet/minecraft/entity/player/EntityPlayer;)Z", at = @At("TAIL"), cancellable = true) + private void onIsAvailable(EntityPlayer player, CallbackInfoReturnable ci) { + if (CnpcRpgSponge.configuration.AVAILABILITY_RPG_LEVEL) { + ci.setReturnValue(NtRpgPlugin.GlobalScope.characterService.getCharacter(player.getUniqueID()).getLevel() >= this.minPlayerLevel); + } + } + +} diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinCustomNpcs.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinCustomNpcs.java similarity index 93% rename from src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinCustomNpcs.java rename to src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinCustomNpcs.java index 297507c..2e84cb5 100644 --- a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinCustomNpcs.java +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinCustomNpcs.java @@ -1,4 +1,4 @@ -package ru.glassspirit.cnpcntrpg.mixin; +package ru.glassspirit.cnpcntrpg.mixin.impl; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import noppes.npcs.CustomNpcs; diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinDataInventory.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDataInventory.java similarity index 97% rename from src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinDataInventory.java rename to src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDataInventory.java index 3fab247..712354f 100644 --- a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinDataInventory.java +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDataInventory.java @@ -1,4 +1,4 @@ -package ru.glassspirit.cnpcntrpg.mixin; +package ru.glassspirit.cnpcntrpg.mixin.impl; import net.minecraft.entity.item.EntityItem; import net.minecraft.item.ItemStack; diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinDataStats.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDataStats.java similarity index 83% rename from src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinDataStats.java rename to src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDataStats.java index 8abcfcf..1de16f4 100644 --- a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinDataStats.java +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDataStats.java @@ -1,4 +1,4 @@ -package ru.glassspirit.cnpcntrpg.mixin; +package ru.glassspirit.cnpcntrpg.mixin.impl; import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.entity.data.DataStats; @@ -7,9 +7,10 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import ru.glassspirit.cnpcntrpg.mixin.IMixinDataStats; @Mixin(DataStats.class) -public abstract class MixinDataStats { +public abstract class MixinDataStats implements IMixinDataStats { private int level; @@ -23,10 +24,12 @@ private void injectReadNbt(NBTTagCompound tag, CallbackInfo ci) { this.level = tag.getInteger("Level"); } + @Override public int getLevel() { return level; } + @Override public void setLevel(int l) { if (l > 0) this.level = l; else level = 0; diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDialog.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDialog.java new file mode 100644 index 0000000..b578978 --- /dev/null +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDialog.java @@ -0,0 +1,54 @@ +package ru.glassspirit.cnpcntrpg.mixin.impl; + +import cz.neumimto.rpg.sponge.NtRpgPlugin; +import net.minecraft.entity.player.EntityPlayer; +import noppes.npcs.api.NpcAPI; +import noppes.npcs.controllers.data.Dialog; +import noppes.npcs.entity.EntityNPCInterface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import ru.glassspirit.cnpcntrpg.mixin.IMixinDialog; + +import javax.script.Invocable; +import javax.script.ScriptEngine; + +@Mixin(value = Dialog.class, remap = false) +public class MixinDialog implements IMixinDialog { + + private static String scriptMark = "$$$"; + + @Shadow + public String text; + + @Override + public boolean isScripted() { + return this.text.contains(scriptMark); + } + + @Override + public void processScripts(EntityPlayer player, EntityNPCInterface npc) { + StringBuilder text = new StringBuilder(this.text); + while (isScripted()) { + int startIndex = text.indexOf(scriptMark); + int endIndex = text.indexOf(scriptMark, startIndex + scriptMark.length()); + if (endIndex == -1) break; // Something went wrong! + + String function = text.substring(startIndex + scriptMark.length(), endIndex); + String result = ""; + try { + ScriptEngine engine = NtRpgPlugin.GlobalScope.jsLoader.getEngine(); + Object func = engine.eval(" function(dialog, player, npc) { " + function + " }"); + engine.eval("var runScriptDialog = function(f, dialog, player, npc) {\n" + + " return f(dialog, player, npc);\n" + + "}"); + Invocable i = (Invocable) engine; + Object obj = i.invokeFunction("runScriptDialog", func, this, NpcAPI.Instance().getIEntity(player), NpcAPI.Instance().getIEntity(npc)); + if (obj != null) result = obj.toString(); + } catch (Exception e) { + e.printStackTrace(); + } + text.replace(startIndex, endIndex + scriptMark.length(), result); + } + this.text = text.toString(); + } +} diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDialogOption.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDialogOption.java new file mode 100644 index 0000000..5c457e2 --- /dev/null +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinDialogOption.java @@ -0,0 +1,71 @@ +package ru.glassspirit.cnpcntrpg.mixin.impl; + +import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.controllers.data.DialogOption; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import ru.glassspirit.cnpcntrpg.mixin.IMixinDialogOption; + +@Mixin(value = DialogOption.class, remap = false) +public class MixinDialogOption implements IMixinDialogOption { + + @Shadow + public int optionType; + @Shadow + public String command; + @Shadow + public String title; + @Shadow + public int dialogId; + @Shadow + public int optionColor; + + private Object script; + + @Override + public Object getScript() { + return script; + } + + @Override + public void setScript(Object script) { + this.script = script; + this.optionType = 5; + } + + /** + * @author GlassSpirit 05.12.2019 + * @reason Store script data + */ + @Overwrite + public void readNBT(NBTTagCompound compound) { + if (compound != null) { + this.title = compound.getString("Title"); + this.dialogId = compound.getInteger("Dialog"); + this.optionColor = compound.getInteger("DialogColor"); + this.optionType = compound.getInteger("OptionType"); + this.command = compound.getString("DialogCommand"); + if (this.optionColor == 0) { + this.optionColor = 14737632; + } + this.script = compound.getString("Script"); + } + } + + /** + * @author GlassSpirit 05.12.2019 + * @reason Store script data + */ + @Overwrite + public NBTTagCompound writeNBT() { + NBTTagCompound compound = new NBTTagCompound(); + compound.setString("Title", this.title); + compound.setInteger("OptionType", this.optionType); + compound.setInteger("Dialog", this.dialogId); + compound.setInteger("DialogColor", this.optionColor); + compound.setString("DialogCommand", this.command); + if (this.script != null) compound.setString("Script", this.script.toString()); + return compound; + } +} diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinEntityNPCInterface.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinEntityNPCInterface.java similarity index 94% rename from src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinEntityNPCInterface.java rename to src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinEntityNPCInterface.java index 15f8789..24fb637 100644 --- a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinEntityNPCInterface.java +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinEntityNPCInterface.java @@ -1,4 +1,4 @@ -package ru.glassspirit.cnpcntrpg.mixin; +package ru.glassspirit.cnpcntrpg.mixin.impl; import noppes.npcs.api.event.NpcEvent; import noppes.npcs.entity.EntityNPCInterface; diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinNoppesUtilPlayer.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinNoppesUtilPlayer.java new file mode 100644 index 0000000..5455a2e --- /dev/null +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinNoppesUtilPlayer.java @@ -0,0 +1,98 @@ +package ru.glassspirit.cnpcntrpg.mixin.impl; + +import cz.neumimto.rpg.sponge.NtRpgPlugin; +import net.minecraft.entity.player.EntityPlayerMP; +import noppes.npcs.EventHooks; +import noppes.npcs.NoppesUtilPlayer; +import noppes.npcs.NoppesUtilServer; +import noppes.npcs.api.NpcAPI; +import noppes.npcs.api.constants.OptionType; +import noppes.npcs.api.constants.RoleType; +import noppes.npcs.controllers.DialogController; +import noppes.npcs.controllers.data.Dialog; +import noppes.npcs.controllers.data.DialogOption; +import noppes.npcs.controllers.data.PlayerData; +import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.roles.RoleCompanion; +import noppes.npcs.roles.RoleDialog; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import ru.glassspirit.cnpcntrpg.mixin.IMixinDialog; +import ru.glassspirit.cnpcntrpg.mixin.IMixinDialogOption; + +import javax.script.Invocable; +import javax.script.ScriptEngine; + +@Mixin(value = NoppesUtilPlayer.class, remap = false) +public abstract class MixinNoppesUtilPlayer { + + /** + * @author GlassSpirit 06.12.2019 + * @reason Process scripted options of dialogs and temporary dialogs + */ + @Overwrite + public static void dialogSelected(int diaId, int optionId, EntityPlayerMP player, EntityNPCInterface npc) { + PlayerData data = PlayerData.get(player); + if (data.dialogId == diaId) { + if (data.dialogId < 0 && npc.advanced.role == RoleType.DIALOG) { + String text = ((RoleDialog) npc.roleInterface).optionsTexts.get(optionId); + if (text != null && !text.isEmpty()) { + Dialog d = new Dialog(null); + d.text = text; + NoppesUtilServer.openDialog(player, npc, d); + } + } else { + Dialog dialog = DialogController.instance.dialogs.get(data.dialogId); + if (dialog == null && IMixinDialog.playerTemporaryDialogMap.containsKey(player.getUniqueID())) + dialog = IMixinDialog.playerTemporaryDialogMap.get(player.getUniqueID()); + + if (dialog != null) { + if (!dialog.hasDialogs(player) && !dialog.hasOtherOptions()) { + NoppesUtilPlayer.closeDialog(player, npc, true); + } else { + DialogOption option = dialog.options.get(optionId); + if (option != null && !EventHooks.onNPCDialogOption(npc, player, dialog, option) && (option.optionType != OptionType.DIALOG_OPTION || option.isAvailable(player) && option.hasDialog()) && option.optionType != OptionType.DISABLED && option.optionType != OptionType.QUIT_OPTION) { + if (option.optionType == OptionType.ROLE_OPTION) { + NoppesUtilPlayer.closeDialog(player, npc, true); + if (npc.roleInterface != null) { + if (npc.advanced.role == RoleType.COMPANION) { + ((RoleCompanion) npc.roleInterface).interact(player, true); + } else { + npc.roleInterface.interact(player); + } + } + } else if (option.optionType == OptionType.DIALOG_OPTION) { + NoppesUtilPlayer.closeDialog(player, npc, false); + NoppesUtilServer.openDialog(player, npc, option.getDialog()); + } else if (option.optionType == OptionType.COMMAND_BLOCK) { + NoppesUtilPlayer.closeDialog(player, npc, true); + NoppesUtilServer.runCommand(npc, npc.getName(), option.command, player); + } else if (option.optionType == 5 /* Script option */) { + try { + ScriptEngine engine = NtRpgPlugin.GlobalScope.jsLoader.getEngine(); + IMixinDialogOption optionScripted = (IMixinDialogOption) option; + if (optionScripted.getScript() instanceof String) { + optionScripted.setScript(engine.eval((String) optionScripted.getScript())); + } + engine.eval("var runScriptOptionFunc = function(option, player, npc) {\n" + + " return option.script(player, npc);\n" + + "}"); + Invocable i = (Invocable) engine; + i.invokeFunction("runScriptOptionFunc", option, NpcAPI.Instance().getIEntity(player)); + } catch (Exception e) { + e.printStackTrace(); + } + IMixinDialog.playerTemporaryDialogMap.remove(player.getUniqueID()); + } else { + NoppesUtilPlayer.closeDialog(player, npc, true); + } + + } else { + NoppesUtilPlayer.closeDialog(player, npc, true); + } + } + } + } + } + } +} diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinNoppesUtilServer.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinNoppesUtilServer.java new file mode 100644 index 0000000..8f2562c --- /dev/null +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinNoppesUtilServer.java @@ -0,0 +1,72 @@ +package ru.glassspirit.cnpcntrpg.mixin.impl; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.EventHooks; +import noppes.npcs.NoppesUtilServer; +import noppes.npcs.Server; +import noppes.npcs.constants.EnumPacketClient; +import noppes.npcs.controllers.PlayerDataController; +import noppes.npcs.controllers.PlayerQuestController; +import noppes.npcs.controllers.data.Dialog; +import noppes.npcs.controllers.data.PlayerData; +import noppes.npcs.controllers.data.PlayerDialogData; +import noppes.npcs.entity.EntityDialogNpc; +import noppes.npcs.entity.EntityNPCInterface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import ru.glassspirit.cnpcntrpg.mixin.IMixinDialog; + +@Mixin(value = NoppesUtilServer.class, remap = false) +public abstract class MixinNoppesUtilServer { + + /** + * @author GlassSpirit 05.12.2019 + * @reason If dialog contains scripts, process it and send with NBT + */ + @Overwrite + public static void openDialog(EntityPlayer player, EntityNPCInterface npc, Dialog originalDialog) { + Dialog dialog = originalDialog.copy(player); + PlayerData playerdata = PlayerData.get(player); + if (EventHooks.onNPCDialog(npc, player, dialog)) { + playerdata.dialogId = -1; + } else { + playerdata.dialogId = dialog.id; + if (!(npc instanceof EntityDialogNpc) && dialog.id >= 0) { + IMixinDialog mixinDialog = (IMixinDialog) dialog; + if (mixinDialog.isScripted()) { + dialog.hideNPC = true; + mixinDialog.processScripts(player, npc); + Server.sendData((EntityPlayerMP) player, EnumPacketClient.DIALOG_DUMMY, npc.getName(), dialog.writeToNBT(new NBTTagCompound())); + } else Server.sendData((EntityPlayerMP) player, EnumPacketClient.DIALOG, npc.getEntityId(), dialog.id); + } else { + dialog.hideNPC = true; + IMixinDialog.playerTemporaryDialogMap.put(player.getUniqueID(), dialog); + Server.sendData((EntityPlayerMP) player, EnumPacketClient.DIALOG_DUMMY, npc.getName(), dialog.writeToNBT(new NBTTagCompound())); + } + + dialog.factionOptions.addPoints(player); + if (dialog.hasQuest()) { + PlayerQuestController.addActiveQuest(dialog.getQuest(), player); + } + + if (!dialog.command.isEmpty()) { + NoppesUtilServer.runCommand(npc, npc.getName(), dialog.command, player); + } + + if (dialog.mail.isValid()) { + PlayerDataController.instance.addPlayerMessage(player.getServer(), player.getName(), dialog.mail); + } + + PlayerDialogData data = playerdata.dialogData; + if (!data.dialogsRead.contains(dialog.id) && dialog.id >= 0) { + data.dialogsRead.add(dialog.id); + playerdata.updateClient = true; + } + + NoppesUtilServer.setEditingNpc(player, npc); + } + } + +} diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinPacketHandlerServer.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinPacketHandlerServer.java new file mode 100644 index 0000000..eb294d2 --- /dev/null +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinPacketHandlerServer.java @@ -0,0 +1,50 @@ +package ru.glassspirit.cnpcntrpg.mixin.impl; + +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.PacketHandlerServer; +import noppes.npcs.Server; +import noppes.npcs.constants.EnumPacketClient; +import noppes.npcs.constants.EnumPacketServer; +import noppes.npcs.entity.EntityNPCInterface; +import org.spongepowered.asm.lib.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import ru.glassspirit.cnpcntrpg.forge.DataNpcRpg; + +@Mixin(value = PacketHandlerServer.class, remap = false) +public class MixinPacketHandlerServer { + + @Inject(method = "handlePacket", at = @At(value = "INVOKE", target = "Lnoppes/npcs/entity/data/DataScript;writeToNBT" + + "(Lnet/minecraft/nbt/NBTTagCompound;)Lnet/minecraft/nbt/NBTTagCompound;"), cancellable = true) + private void onScriptDataGet(EnumPacketServer type, ByteBuf buffer, EntityPlayerMP player, EntityNPCInterface npc, CallbackInfo ci) { + if (DataNpcRpg.playersEditingRpgData.containsKey(player.getUniqueID())) { + ci.cancel(); + DataNpcRpg data = new DataNpcRpg(npc, true); + NBTTagCompound compound = data.writeToNBT(new NBTTagCompound()); + + Server.sendData(player, EnumPacketClient.GUI_DATA, compound); + } + } + + @Inject(method = "handlePacket", at = @At(value = "FIELD", target = "Lnoppes/npcs/entity/EntityNPCInterface;" + + "script:Lnoppes/npcs/entity/data/DataScript;", opcode = Opcodes.GETFIELD, ordinal = 0), cancellable = true) + private void onScriptDataSave(EnumPacketServer type, ByteBuf buffer, EntityPlayerMP player, EntityNPCInterface npc, CallbackInfo ci) { + if (DataNpcRpg.playersEditingRpgData.containsKey(player.getUniqueID())) { + ci.cancel(); + DataNpcRpg.playersEditingRpgData.remove(player.getUniqueID()); + + DataNpcRpg data = new DataNpcRpg(npc, false); + try { + data.readFromNBT(Server.readNBT(buffer)); + data.apply(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + +} diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinScriptContainer.java b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinScriptContainer.java similarity index 96% rename from src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinScriptContainer.java rename to src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinScriptContainer.java index befd2d7..949824d 100644 --- a/src/main/java/ru/glassspirit/cnpcntrpg/mixin/MixinScriptContainer.java +++ b/src/main/java/ru/glassspirit/cnpcntrpg/mixin/impl/MixinScriptContainer.java @@ -1,4 +1,4 @@ -package ru.glassspirit.cnpcntrpg.mixin; +package ru.glassspirit.cnpcntrpg.mixin.impl; import cz.neumimto.rpg.sponge.NtRpgPlugin; import noppes.npcs.controllers.ScriptContainer; diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/sponge/CnpcRpgSponge.java b/src/main/java/ru/glassspirit/cnpcntrpg/sponge/CnpcRpgSponge.java index b782079..7b59f01 100644 --- a/src/main/java/ru/glassspirit/cnpcntrpg/sponge/CnpcRpgSponge.java +++ b/src/main/java/ru/glassspirit/cnpcntrpg/sponge/CnpcRpgSponge.java @@ -19,7 +19,7 @@ id = "cnpc-ntrpg", name = "NT-RPG CustomNPCs Bridge", description = "Plugin that connects NT-RPG plugin and CustomNPCs mod and adds some useful stuff", - version = "1.2", + version = "1.3", authors = {"GlassSpirit"}, dependencies = { @Dependency(id = "nt-rpg"), @@ -32,6 +32,8 @@ public class CnpcRpgSponge { public static Configuration configuration; + public static CnpcRpgSponge instance; + @Inject private Logger logger; @@ -41,6 +43,7 @@ public class CnpcRpgSponge { @Listener public void onGameInitialization(GameInitializationEvent event) { + instance = this; configuration = new Configuration(); loadConfig(); } diff --git a/src/main/java/ru/glassspirit/cnpcntrpg/sponge/Commands.java b/src/main/java/ru/glassspirit/cnpcntrpg/sponge/Commands.java index 7f59bda..9b21f55 100644 --- a/src/main/java/ru/glassspirit/cnpcntrpg/sponge/Commands.java +++ b/src/main/java/ru/glassspirit/cnpcntrpg/sponge/Commands.java @@ -1,6 +1,57 @@ package ru.glassspirit.cnpcntrpg.sponge; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.math.RayTraceResult; +import noppes.npcs.CustomNpcsPermissions; +import noppes.npcs.NoppesUtilServer; +import noppes.npcs.Server; +import noppes.npcs.constants.EnumGuiType; +import noppes.npcs.constants.EnumPacketClient; +import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.util.IPermission; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.command.CommandResult; +import org.spongepowered.api.command.spec.CommandSpec; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.text.Text; +import org.spongepowered.common.entity.EntityUtil; +import ru.glassspirit.cnpcntrpg.forge.DataNpcRpg; + public class Commands { + Commands() { + CommandSpec dataCommand = CommandSpec.builder() + .description(Text.of("Command to modify additional data of npc")) + .permission(CustomNpcsPermissions.NPC_GUI.name) + .executor((src, args) -> { + if (!(src instanceof Player)) { + return CommandResult.empty(); + } + EntityPlayerMP player = (EntityPlayerMP) src; + if (!(player.getHeldItemMainhand().getItem() instanceof IPermission)) { + src.sendMessage(Text.of("You must have 'Scripter' item in hand")); + return CommandResult.empty(); + } + + RayTraceResult result = EntityUtil.rayTraceFromEntity(player, 10D, 0, true); + if (result.entityHit instanceof EntityNPCInterface) { + EntityNPCInterface npc = (EntityNPCInterface) result.entityHit; + NoppesUtilServer.setEditingNpc(player, npc); + DataNpcRpg.playersEditingRpgData.put(player.getUniqueID(), npc.getUniqueID()); + Server.sendData(player, EnumPacketClient.GUI, EnumGuiType.Script.ordinal(), 0, 0, 0); + } else { + src.sendMessage(Text.of("No npc found!")); + } + return CommandResult.empty(); + }) + .build(); + + CommandSpec mainCommand = CommandSpec.builder() + .description(Text.of("Main CNPC-RPG command")) + .child(dataCommand, "data") + .build(); + + Sponge.getCommandManager().register(CnpcRpgSponge.instance, mainCommand, "npc"); + } } diff --git a/src/main/resources/mixins.cnpcntrpg.json b/src/main/resources/mixins.cnpcntrpg.json index 4fc83ae..e74f589 100644 --- a/src/main/resources/mixins.cnpcntrpg.json +++ b/src/main/resources/mixins.cnpcntrpg.json @@ -1,14 +1,20 @@ { "required": true, - "package": "ru.glassspirit.cnpcntrpg.mixin", + "package": "ru.glassspirit.cnpcntrpg.mixin.impl", "compatibilityLevel": "JAVA_8", "refmap": "mixins.cnpcntrpg.refmap.json", "target": "@env(DEFAULT)", "mixins": [ + "MixinAvailablilty", "MixinCustomNpcs", "MixinDataInventory", "MixinDataStats", + "MixinDialog", + "MixinDialogOption", "MixinEntityNPCInterface", + "MixinNoppesUtilPlayer", + "MixinNoppesUtilServer", + "MixinPacketHandlerServer", "MixinScriptContainer" ], "minVersion": "0.7.10",