/*
* This file is part of the OdinMS Maple Story Server Copyright (C) 2008 ~ 2010
* Patrick Huy <patrick.huy@frz.cc> Matthias Butz <matze@odinms.de> Jan
* Christian Meyer <vimes@odinms.de>
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation. You may not use, modify or distribute this
* program under any other version of the GNU Affero General Public License.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package javastory.scripting;
import java.util.Map;
import java.util.WeakHashMap;
import javastory.channel.ChannelClient;
import javastory.game.quest.QuestInfoProvider;
import javastory.game.quest.QuestInfoProvider.QuestInfo;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
public final class NpcScriptManager extends AbstractScriptManager {
private final Map<ChannelClient, NpcConversationManager> managers;
private final Map<ChannelClient, Invocable> scripts;
private static final NpcScriptManager instance = new NpcScriptManager();
private NpcScriptManager() {
this.managers = new WeakHashMap<>();
this.scripts = new WeakHashMap<>();
}
public static NpcScriptManager getInstance() {
return instance;
}
public final void start(final ChannelClient c, final int npc) {
try {
if (!(this.managers.containsKey(c) && this.scripts.containsKey(c))) {
final Invocable iv = this.getInvocable("npc/" + npc + ".js", c);
final ScriptEngine scriptengine = (ScriptEngine) iv;
if (iv == null) {
return;
}
final NpcConversationManager cm = new NpcConversationManager(c, npc, -1, (byte) -1);
this.managers.put(c, cm);
scriptengine.put("cm", cm);
c.getPlayer().setConversationState(1);
this.scripts.put(c, iv);
try {
iv.invokeFunction("start");
// Temporary until I've removed all of start
} catch (final NoSuchMethodException nsme) {
iv.invokeFunction("action", (byte) 1, (byte) 0, 0);
}
}
} catch (final ScriptException | NoSuchMethodException e) {
e.printStackTrace();
System.err.println("Error executing NPC script, NPC ID : " + npc + "." + e);
this.dispose(c);
}
}
public final void action(final ChannelClient c, final byte mode, final byte type, final int selection) {
if (mode != -1) {
try {
if (this.managers.get(c).isPendingDisposal()) {
this.dispose(c);
} else {
this.scripts.get(c).invokeFunction("action", mode, type, selection);
}
} catch (final ScriptException | NoSuchMethodException e) {
e.printStackTrace();
System.err.println("Error executing NPC script");
this.dispose(c);
}
}
}
public final void startQuest(final ChannelClient c, final int npc, final int quest) {
if (!QuestInfoProvider.getInfo(quest).canStart(c.getPlayer(), npc)) {
return;
}
try {
if (!(this.managers.containsKey(c) && this.scripts.containsKey(c))) {
final Invocable iv = this.getInvocable("quest/" + quest + ".js", c);
final ScriptEngine scriptengine = (ScriptEngine) iv;
if (iv == null) {
return;
}
final NpcConversationManager cm = new NpcConversationManager(c, npc, quest, (byte) 0);
this.managers.put(c, cm);
scriptengine.put("qm", cm);
c.getPlayer().setConversationState(1);
this.scripts.put(c, iv);
iv.invokeFunction("start", (byte) 1, (byte) 0, 0); // start it
// off as
// something
}
} catch (final Exception e) {
System.err.println("Error executing Quest script. (" + quest + ")" + e);
this.dispose(c);
}
}
public final void startQuest(final ChannelClient c, final byte mode, final byte type, final int selection) {
try {
if (this.managers.get(c).isPendingDisposal()) {
this.dispose(c);
} else {
this.scripts.get(c).invokeFunction("start", mode, type, selection);
}
} catch (ScriptException | NoSuchMethodException e) {
this.dispose(c);
}
}
public final void endQuest(final ChannelClient c, final int npc, final int quest, final boolean customEnd) {
final QuestInfo info = QuestInfoProvider.getInfo(quest);
final boolean canComplete = info.canComplete(c.getPlayer(), npc);
if (!customEnd && canComplete) {
return;
}
try {
if (!(this.managers.containsKey(c) && this.scripts.containsKey(c))) {
final Invocable iv = this.getInvocable("quest/" + quest + ".js", c);
final ScriptEngine scriptengine = (ScriptEngine) iv;
if (iv == null) {
return;
}
final NpcConversationManager cm = new NpcConversationManager(c, npc, quest, (byte) 1);
this.managers.put(c, cm);
scriptengine.put("qm", cm);
c.getPlayer().setConversationState(1);
this.scripts.put(c, iv);
iv.invokeFunction("end", (byte) 1, (byte) 0, 0); // start it off
// as
// something
}
} catch (ScriptException | NoSuchMethodException e) {
System.err.println("Error executing Quest script. (" + quest + ")" + e);
} finally {
this.dispose(c);
}
}
public final void endQuest(final ChannelClient c, final byte mode, final byte type, final int selection) {
try {
if (this.managers.get(c).isPendingDisposal()) {
this.dispose(c);
} else {
this.scripts.get(c).invokeFunction("end", mode, type, selection);
}
} catch (ScriptException | NoSuchMethodException e) {
// System.err.println("Error executing Quest script. (" +
// c.getQM().getQuestId() + ")" + e);
this.dispose(c);
}
}
public final void dispose(final ChannelClient c) {
final NpcConversationManager manager = this.managers.get(c);
if (manager != null) {
this.managers.remove(manager.getClient());
this.scripts.remove(manager.getClient());
if (manager.getType() == -1) {
c.removeScriptEngine("scripts/npc/" + manager.getNpcId() + ".js");
} else {
c.removeScriptEngine("scripts/quest/" + manager.getQuest() + ".js");
}
}
if (c.getPlayer().getConversationState() == 1) {
c.getPlayer().setConversationState(0);
}
}
public final NpcConversationManager getConversationManager(final ChannelClient client) {
return this.managers.get(client);
}
}