22 package com.realtime.crossfire.jxclient.scripts;
41 import java.io.BufferedReader;
42 import java.io.IOException;
43 import java.io.InputStream;
44 import java.io.InputStreamReader;
45 import java.io.OutputStreamWriter;
46 import java.io.UnsupportedEncodingException;
47 import java.nio.ByteBuffer;
48 import org.jetbrains.annotations.NotNull;
49 import org.jetbrains.annotations.Nullable;
127 private final InputStream
in;
133 private final OutputStreamWriter
osw;
165 public void connecting() {
170 public void connected() {
175 public void packetReceived(@NotNull
final ByteBuffer packet) {
180 public void packetSent(@NotNull
final byte[] buf,
final int len) {
183 cmd =
new String(buf, 0, len,
"ISO-8859-1");
184 }
catch (
final UnsupportedEncodingException ex) {
185 throw new AssertionError(ex);
191 public void disconnecting(@NotNull
final String reason,
final boolean isError) {
196 public void disconnected(@NotNull
final String reason) {
227 packetWatcher =
new PacketWatcher(crossfireServerConnection,
this);
228 final Runtime rt = Runtime.getRuntime();
229 process = rt.exec(filename);
230 in = process.getInputStream();
232 osw =
new OutputStreamWriter(process.getOutputStream());
257 @Nullable String result =
"unexpected";
260 try (
final InputStreamReader isr =
new InputStreamReader(in)) {
261 try (
final BufferedReader br =
new BufferedReader(isr)) {
263 final String line = br.readLine();
273 final int exitStatus = process.waitFor();
274 result = exitStatus == 0 ? null :
"exit "+exitStatus;
275 }
catch (
final InterruptedException ex) {
276 result = ex.getMessage();
278 }
catch (
final IOException ex) {
279 result = ex.getMessage();
288 scriptProcessListener.scriptTerminated(result);
305 }
catch (
final IOException ex) {
318 if (item.isMagic()) {
321 if (item.isCursed()) {
324 if (item.isDamned()) {
327 if (item.isUnpaid()) {
330 if (item.isLocked()) {
333 if (item.isApplied()) {
339 final int nrof = Math.max(1, item.getNrOf());
340 final String name = nrof <= 1 ? item.getName() : nrof+
" "+item.getName();
341 commandSent(cmd+
" "+item.getTag()+
" "+nrof+
" "+Math.max(0, item.getWeight())+
" "+flags+
" "+item.getType()+
" "+name);
351 final StringBuilder sb =
new StringBuilder(
"request map ");
360 sb.append(
" n y n ");
362 sb.append(
" smooth 0 0 0 heads");
363 for (
int i = 0; i < 3; i++) {
370 for (
int i = 0; i < 3; i++) {
372 if (headSquare == null) {
399 if (params.equals(
"player")) {
401 }
else if (params.equals(
"range")) {
403 }
else if (params.equals(
"weight")) {
405 }
else if (params.equals(
"stat stats")) {
407 }
else if (params.equals(
"stat stats_race")) {
409 }
else if (params.equals(
"stat stats_base")) {
411 }
else if (params.equals(
"stat stats_applied")) {
413 }
else if (params.equals(
"stat cmbt")) {
415 }
else if (params.equals(
"stat hp")) {
417 }
else if (params.equals(
"stat xp")) {
418 final StringBuilder sb =
new StringBuilder(
"request stat xp ");
426 sb.append(
' ').append(skill.
getLevel());
431 }
else if (params.equals(
"stat resists")) {
432 final StringBuilder sb =
new StringBuilder(
"request stat resists");
442 }
else if (params.equals(
"stat paths")) {
444 }
else if (params.equals(
"flags")) {
446 }
else if (params.equals(
"items inv")) {
451 }
else if (params.equals(
"items actv")) {
453 if (item.isApplied()) {
458 }
else if (params.equals(
"items on")) {
463 }
else if (params.equals(
"items cont")) {
465 if (containerTag != 0) {
471 }
else if (params.equals(
"map pos")) {
473 }
else if (params.equals(
"map near")) {
475 final int centerX = mapUpdaterState.
getMapWidth()/2;
477 for (
int y = -1; y <= +1; y++) {
478 for (
int x = -1; x <= +1; x++) {
482 }
else if (params.equals(
"map all")) {
486 for (
int y = 0; y < height; y++) {
487 for (
int x = 0; x < width; x++) {
491 }
else if (params.startsWith(
"map ")) {
492 final String[] tmp = params.split(
" +");
493 if (tmp.length != 3) {
500 x = Integer.parseInt(tmp[1]);
501 }
catch (
final NumberFormatException ignored) {
508 y = Integer.parseInt(tmp[2]);
509 }
catch (
final NumberFormatException ignored) {
515 }
else if (params.equals(
"skills")) {
517 final Object skill = skillSet.
getSkill(i);
523 }
else if (params.equals(
"spells")) {
524 for (
final Spell spell : spellsManager) {
525 commandSent(
"request spells "+spell.getTag()+
" "+spell.getLevel()+
" "+spell.getMana()+
" "+spell.getGrace()+
" "+spell.getSkill()+
" "+spell.getPath()+
" "+spell.getCastingTime()+
" "+spell.getDamage()+
" "+spell.getName());
540 tag = Integer.parseInt(params);
541 }
catch (
final NumberFormatException ignored) {
545 crossfireServerConnection.
sendMark(tag);
553 final String[] tmp = params.split(
" +", 2);
554 if (tmp.length != 2) {
561 val = Integer.parseInt(tmp[0]);
562 tag = Integer.parseInt(tmp[1]);
563 }
catch (
final NumberFormatException ignored) {
567 if (val < 0 || val > 1) {
571 crossfireServerConnection.
sendLock(val != 0, tag);
578 private void cmdIssue(@NotNull
final String params) {
579 final String[] pps = params.split(
" +", 3);
580 if (pps.length != 3) {
587 repeat = Integer.parseInt(pps[0]);
588 tmp = Integer.parseInt(pps[1]);
589 }
catch (
final NumberFormatException ignored) {
593 if (tmp < 0 || tmp > 1) {
597 final boolean mustSend = tmp != 0;
598 final String command = pps[2];
599 commandQueue.
sendNcom(mustSend, repeat, command);
606 private void cmdDraw(@NotNull
final String params) {
607 final String[] pps = params.split(
" +", 2);
608 if (pps.length != 2) {
614 color = Integer.parseInt(pps[0]);
615 }
catch (
final NumberFormatException ignored) {
619 crossfireServerConnection.
drawInfo(pps[1], color);
637 isMonitoring =
false;
647 final String[] tmp = cmdLine.split(
" +", 2);
650 if (tmp.length == 1) {
652 }
else if (tmp[1].indexOf(
' ') != -1) {
664 if (tmp.length == 2) {
672 if (tmp.length != 2) {
674 }
else if (tmp[1].startsWith(
"mark ")) {
676 }
else if (tmp[1].startsWith(
"lock ")) {
684 if (tmp.length == 2) {
692 if (tmp.length == 1) {
695 reportError(
"The 'monitor' command does not take arguments.");
700 if (tmp.length == 1) {
703 reportError(
"The 'unmonitor' command does not take arguments.");
708 reportError(
"unrecognized command from script: "+cmdLine);
726 scriptProcessListeners.
add(scriptProcessListener);
743 if (scriptId < o.getScriptId()) {
746 if (scriptId > o.getScriptId()) {
764 public boolean equals(@Nullable
final Object obj) {
769 final ScriptProcess scriptProcess = (ScriptProcess)obj;
final OutputStreamWriter osw
The OutputStreamWriter associated with process.
boolean checkRun()
Returns whether the character is running.
final int scriptId
The script ID identifying this script instance.
static final int CS_STAT_RACE_CHA
The race's maximum charisma primary stat.
final FloorView floorView
The FloorView to use.
CfMapSquare getHeadMapSquare(final int layer)
Returns the map square of the head of a multi-square object.
void cmdDraw(@NotNull final String params)
Processes a "draw" command from the script process.
int getMapHeight()
Returns the height of the visible map area.
static final int CS_STAT_DEX
The Dexterity Primary stat.
static final int CS_STAT_SPELL_ATTUNE
Attuned spell paths of a spell.
boolean isMonitoring
Whether a "monitor" command is active.
int getMapWidth()
Returns the width of the visible map area.
final InputStream in
The InputStream of process.
void commandSentItem(@NotNull final String cmd, @NotNull final CfItem item)
Sends an item info message to the script process.
Represents a square in a CfMap.
void runScriptCommand(@NotNull final String cmdLine)
Processes a line received from the script process.
List< CfItem > getItemsByLocation(final int location)
Returns a list of items in a given location.
CfMap getMap()
Returns the current map instance.
void sendNcom(final boolean mustSend, @NotNull final String command)
Sends an "ncom" command to the server.
void cmdUnmonitor()
Processes an "unmonitor" command from the script process.
static final int CS_STAT_SPELL_DENY
Denied spell paths of a spell.
Iterable< CfItem > getPlayerInventory()
Returns the player's inventory.
Represents a map (as seen by the client).
A list of event listeners.
int NDI_RED
A message color.
Interface for listeners interested in drawinfo messages received from the Crossfire server...
int getScriptId()
Returns the script ID identifying this script instance.
static final int CS_STAT_APPLIED_CON
The constitution primary stat changes due to gear or skills.
static final int CS_STAT_RESIST_START
Beginning index of the resistances.
String getFilename()
Returns the script's filename.the script's filename
static final int CS_STAT_BASE_POW
The power primary stat without boosts or depletions.
void sendLock(boolean val, int tag)
Sends a "lock" command to the server.
static final int CS_STAT_POW
The Power Primary stat.
void commandSent(@NotNull final String cmd)
Sends a message to the script process.the message to send
int getDarkness()
Returns the darkness value of this square.
static final int CS_STAT_APPLIED_INT
The integer primary stat changes due to gear or skills.
final SkillSet skillSet
The SkillSet for looking up skill names.
long getExperience()
Returns the amount of global experience.
static final int CS_NUM_SKILLS
CS_NUM_SKILLS does not match how many skills there really are - instead, it is used as a range of val...
int getLevel()
Returns the skill level.
Implements the map model which is shown in the map and magic map views.
void destroy()
Releases allocated resources.
static final int CS_STAT_HP
The Hit Points stat.
DefaultScriptProcess(final int scriptId, @NotNull final String filename, @NotNull final CommandQueue commandQueue, @NotNull final CrossfireServerConnection crossfireServerConnection, @NotNull final Stats stats, @NotNull final FloorView floorView, @NotNull final ItemSet itemSet, @NotNull final Iterable< Spell > spellsManager, @NotNull final MapUpdaterState mapUpdaterState, @NotNull final SkillSet skillSet)
Creates a new instance.
static final int CS_STAT_LEVEL
The Global Level stat.
void sendMark(int tag)
Sends a "mark" command to the server.
void addScriptProcessListener(@NotNull final ScriptProcessListener scriptProcessListener)
Adds a ScriptProcessListener to be notified.the listener to add
void removeClientSocketListener(@NotNull ClientSocketListener clientSocketListener)
Removes a ClientSocketListener to notify.
Interface for listeners interested in ScriptProcess related events.
static final int CS_STAT_MAXHP
The Maximum Hit Points stat.
static final int CS_STAT_RACE_WIS
The race's maximum wisdom primary stat.
Manages image information ("faces") needed to display the map view, items, and spell icons...
Default implementation for ScriptProcesses.
Manages all known spells.
static final int CS_STAT_DAM
The Damage stat.
static final int CS_STAT_STR
The Strength Primary stat.
static final int CS_STAT_AC
The Armor Class stat.
static final int CS_STAT_FOOD
The Food stat.
static final int CS_STAT_WIS
The Wisdom Primary stat.
void killScript()
Kills the script process.Does nothing if the process is not running.
static final int CS_STAT_BASE_INT
The integer primary stat without boosts or depletions.
final CommandQueue commandQueue
The CommandQueue for sending commands.
void drawInfo(@NotNull String message, int color)
Pretends that a drawinfo message has been received.
static final int CS_STAT_SP
The Spell Points stat.
void addCommand(@NotNull final String command)
Adds a command to watch for.
final PacketWatcher packetWatcher
The PacketWatcher to process "watch" commands.
One skill of the character.
void addClientSocketListener(@NotNull ClientSocketListener clientSocketListener)
Adds a ClientSocketListener to notify.
static final int CS_STAT_RACE_CON
The race's maximum constitution primary stat.
final ItemSet itemSet
The ItemSet instance to use.
void cmdIssueLock(@NotNull final String params)
Processes a "issue lock" command from the script process.
static final int CS_STAT_WEIGHT_LIM
The Weight Limit stat.
static final int CS_STAT_APPLIED_STR
The strength primary stat changes due to gear or skills.
static final int CS_STAT_BASE_STR
The strength primary stat without boosts or depletions.
static final int CS_STAT_SKILLINFO
CS_STAT_SKILLINFO is used as the starting index point.
long getExperience()
Returns the skill experience.
Describes a Crossfire spell.
static final int CS_STAT_CON
The Constitution Primary stat.
void reportError(@NotNull final String string)
Reports an error while executing client commands.
static final int CS_STAT_RACE_STR
The race's maximum strength primary stat.
boolean killed
Whether this script has been killed.
static final int CS_STAT_APPLIED_DEX
The dexterity primary stat changes due to gear or skills.
void commandSentMap(@NotNull final CfMap map, final int x, final int y)
Sends info about one map cell to the script process.
void removeCommand(@NotNull final String command)
Removes a command to watch for.
String getRange()
Returns the current content of the range stat.
Update a CfMap model from protocol commands.
boolean isFogOfWar()
Determines if the square is not up-to-date.
void add(@NotNull final T listener)
Adds a listener.
Implements the "watch" function for client-sided scripts.
final Iterable< Spell > spellsManager
The SpellsManager instance to use.
int getTag()
Returns the tag.
final Process process
The Process instance for the executed child process.
static final int CS_STAT_RACE_INT
The race's maximum intelligence primary stat.
static final int CS_STAT_MAXGRACE
The Maximum Grace stat.
Skill getSkill(final int id)
Returns the given skill as a Skill object.
Interface for listeners interested in ClientSocket related events.
final EventListenerList2< ScriptProcessListener > scriptProcessListeners
The ScriptProcessListeners to notify.
static final int CS_STAT_RACE_DEX
The race's maximum dexterity primary stat.
int getWeight()
Returns the weight.
static final int CS_STAT_BASE_CON
The constitution primary stat without boosts or depletions.
static final int CS_STAT_CHA
The Charisma Primary stat.
static final Face DEFAULT_FACE
The default face value for newly creates squares.
final ClientSocketListener clientSocketListener
The ClientSocketListener attached to crossfireServerConnection to track commands sent to the server...
final Stats stats
The Stats instance to watch.
int getScriptId()
Returns the script ID identifying this script instance.the script ID
final CrossfireServerConnection crossfireServerConnection
The connection instance.
static final int CS_STAT_APPLIED_CHA
The charisma primary stat changes due to gear or skills.
static final int CS_STAT_SPELL_REPEL
Repelled spell paths of a spell.
static final int CS_STAT_WC
The Weapon Class stat.
final MapUpdaterState mapUpdaterState
The MapUpdaterState instance to use.
CfItem getPlayer()
Returns the player object this client controls.
static final int CS_STAT_BASE_WIS
The wisdom primary stat without boosts or depletions.
int compareTo(@NotNull final ScriptProcess o)
static final int CS_STAT_BASE_DEX
The dexterity primary stat without boosts or depletions.
static final int CS_STAT_RESIST_END
End index of the resistances.
An external command executed as a client-sided script.
Face getFace(final int layer)
Returns the face of a layer.
boolean checkFire()
Returns whether the character is firing.
static final int CS_STAT_RACE_POW
The race's maximum power primary stat.
Adds encoding/decoding of crossfire protocol packets to a ServerConnection.
boolean equals(@Nullable final Object obj)
Model class maintaining the CfItems known to the player.
static final int CS_STAT_INT
The Intelligence Primary stat.
Maintains the pending (ncom) commands sent to the server.
void cmdMonitor()
Processes a "monitor" command from the script process.
static final int CS_STAT_FLAGS
The various flags used in stats.
This is the representation of all the statistics of a player, like its speed or its experience...
static final int CS_STAT_WEAP_SP
The Weapon Speed stat.
void cmdIssue(@NotNull final String params)
Processes a regular "issue" command from the script process.
Maintain the set of skills as sent by the server.
static final int CS_STAT_MAXSP
The Maximum Spell Points stat.
The representation of a Crossfire Item, client-side.
static final int CS_STAT_APPLIED_POW
The power primary stat changes due to gear or skills.
int getFaceNum()
Returns the unique face id.
String getTitle()
Returns the current title.
static final int CS_STAT_SPEED
The Speed stat.
final String filename
The script command including arguments.
int getCurrentFloor()
Returns the current floor location.
static final int CS_STAT_GRACE
The Grace stat.
void cmdRequest(@NotNull final String params)
Processes a "request" command from the script process.
static final int CS_STAT_BASE_CHA
The charisma primary stat without boosts or depletions.
void cmdIssueMark(@NotNull final String params)
Processes a "issue mark" command from the script process.
Provides a view to all items comprising the current floor view.
static final int CS_STAT_APPLIED_WIS
The wisdom primary stat changes due to gear or skills.
int getStat(final int statNo)
Returns the numerical value of the given statistic.