summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Marks <nymacro@gmail.com>2005-11-15 11:41:17 +0000
committerAaron Marks <nymacro@gmail.com>2005-11-15 11:41:17 +0000
commit3d5bcc32ea4ac19e8da7bcf4a59443f3a013ba6d (patch)
treeff833024b07a36587d02cc8c10b59cda50229bab
parent9c4f838ef2e9b801a08c3550647aff4efcbb1ebd (diff)
downloadmanaserv-3d5bcc32ea4ac19e8da7bcf4a59443f3a013ba6d.tar.gz
manaserv-3d5bcc32ea4ac19e8da7bcf4a59443f3a013ba6d.tar.xz
manaserv-3d5bcc32ea4ac19e8da7bcf4a59443f3a013ba6d.zip
Updated bindings, game state class and more (see ChangeLog).
-rw-r--r--ChangeLog13
-rw-r--r--TODO6
-rw-r--r--scripts/init.rb59
-rw-r--r--src/accounthandler.cpp6
-rw-r--r--src/bindings.i9
-rw-r--r--src/chathandler.cpp6
-rw-r--r--src/client.cpp11
-rw-r--r--src/defines.h8
-rw-r--r--src/messagein.cpp2
-rw-r--r--src/state.cpp123
-rw-r--r--src/state.h96
11 files changed, 293 insertions, 46 deletions
diff --git a/ChangeLog b/ChangeLog
index 6b78c18..147d9b5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2005-11-15 Aaron Marks <nymacro@gmail.com>
+
+ * src/state.h, src/state.cpp: Updated world representation, added
+ various methods which provide easy access to the game world.
+ * src/defines.h: Added "private message" message.
+ * src/client.cpp, scripts/init.rb: Added experimental remote access
+ to Ruby's functionality.
+
+2005-11-14 Aaron Marks <nymacro@gmail.com>
+
+ * src/bindings.i: Enabled "directors", allowing scripting language
+ to override virtual functions.
+
2005-11-12 Aaron Marks <nymacro@gmail.com>
* src/main.cpp: Added scripting with Ruby support
diff --git a/TODO b/TODO
index 7332d18..49658d6 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,5 @@
$Id$
- * Implement MessageHandler base for scripts which will call script's
- receiveMessage.
- * Enhance SWIG bindings to have support for items, objects etc.
+ * Provide interactive Ruby prompt.
+ * Better handling of std::string with SWIG
+ * Error handling for SWIG bindings (currently any problems will crash the server)
diff --git a/scripts/init.rb b/scripts/init.rb
index 25e8dbc..290598f 100644
--- a/scripts/init.rb
+++ b/scripts/init.rb
@@ -1,19 +1,66 @@
-print "Hello there, this is embedded into TMW!\n"
+print "enter init.rb\n"
class EquipHandler < Tmw::MessageHandler
def initialize()
super
end
- # this isn't possible -- does not override parent receiveMessage
def receiveMessage(computer, message)
+ print "Message ID: ", message.getId(), "\n"
item = message.readLong()
slot = message.readByte()
- print "Trying to equip ", item, " at ", slot, "\n"
+ print "Trying to equip ", item, " at ", slot.to_i(), "\n"
+
+ result = Tmw::MessageOut.new()
+ result.writeShort(Tmw::SMSG_EQUIP_RESPONSE)
+ result.writeByte(Tmw::EQUIP_OK)
+ computer.send(result.getPacket())
+ end
+end
+
+# Override default equip message handler
+Tmw::connectionHandler.registerHandler(Tmw::CMSG_EQUIP, EquipHandler.new())
+
+
+# Remote Ruby expression execution
+class RubyHandler < Tmw::MessageHandler
+ def initialize()
+ super
+ print "Ruby message handler activated\n"
+ end
+
+ def receiveMessage(computer, message)
+ src = message.readString()
+ print src, "\n";
+ # doesn't work properly yet (need to have SWIG use std::string nicely)
+ #eval(src, TOPLEVEL_BINDING)
+ end
+end
+
+Tmw::connectionHandler.registerHandler(0x800, RubyHandler.new())
+
+
+# simple enemy
+class SimpleEnemy < Tmw::Being
+ def initialize()
+ super
+ end
+
+ def update()
+ print "Updating!\n"
end
end
-a = EquipHandler.new()
-Tmw::connectionHandler.registerHandler(Tmw::CMSG_EQUIP, a)
+# simple item
+class SimpleItem < Tmw::Item
+ def initialize()
+ super
+ type = 100
+ end
+
+ def use()
+ print "USE THIS THING!!"
+ end
+end
-print "Done init.rb\n"
+print "exit init.rb\n"
diff --git a/src/accounthandler.cpp b/src/accounthandler.cpp
index 2934afd..9127640 100644
--- a/src/accounthandler.cpp
+++ b/src/accounthandler.cpp
@@ -26,6 +26,7 @@
#include "storage.h"
#include "account.h"
#include "messageout.h"
+#include "state.h"
#include <iostream>
using tmwserv::Account;
@@ -153,7 +154,12 @@ void AccountHandler::receiveMessage(NetComputer &computer, MessageIn &message)
break;
}
+ // set character
computer.setCharacter(chars[charNum].get());
+
+ // place in world
+ //tmwserv::State &state = tmwserv::State::instance();
+ //state.beings["start.tmx"].push_back(tmwserv::BeingPtr(computer.getCharacter()));
result.writeByte(SELECT_OK);
}
diff --git a/src/bindings.i b/src/bindings.i
index 7dbbfc9..d420be2 100644
--- a/src/bindings.i
+++ b/src/bindings.i
@@ -19,13 +19,14 @@
*
* $Id$
*/
-%module Tmw
+%module(directors="1") Tmw
%{
#include "defines.h"
#include "messagehandler.h"
#include "packet.h"
#include "messagein.h"
+#include "messageout.h"
#include "netcomputer.h"
#include "connectionhandler.h"
#include "object.h"
@@ -35,10 +36,16 @@
extern ConnectionHandler connectionHandler;
%}
+%feature("director") MessageHandler;
+%feature("director") Object;
+%feature("director") Item;
+%feature("director") Being;
+
%include "defines.h"
%include "messagehandler.h"
%include "packet.h"
%include "messagein.h"
+%include "messageout.h"
%include "netcomputer.h"
%include "connectionhandler.h"
%include "object.h"
diff --git a/src/chathandler.cpp b/src/chathandler.cpp
index 9884861..33f0eb3 100644
--- a/src/chathandler.cpp
+++ b/src/chathandler.cpp
@@ -48,6 +48,12 @@ void ChatHandler::receiveMessage(NetComputer &computer, MessageIn &message)
}
break;
+ case CMSG_PRIVMSG:
+ {
+ std::string user = message.readString();
+ std::string text = message.readString();
+ } break;
+
default:
std::cout << "Invalid message type" << std::endl;
break;
diff --git a/src/client.cpp b/src/client.cpp
index be2424b..e614255 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -55,6 +55,7 @@ int main(int argc, char *argv[])
printf ("5) Character selection\n");
printf ("6) Move character\n");
printf ("7) Equip item\n");
+ printf ("9) Ruby expression\n");
printf ("Choose your option: ");
std::cin >> answer;
@@ -143,6 +144,16 @@ int main(int argc, char *argv[])
msg.writeByte(slot);
} break;
+ case 9:
+ {
+ std::cout << "Expr: ";
+ std::cin >> line;
+ msg.writeShort(0x800);
+ msg.writeString(line);
+
+ responseRequired = false;
+ } break;
+
default:
continue;
}
diff --git a/src/defines.h b/src/defines.h
index 32fb6cf..e49c80d 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -100,14 +100,16 @@ enum {
SMSG_EQUIP_RESPONSE = 0x0302,
// Chat
- SMSG_CHAT = 0x0400,
- SMSG_SYSTEM = 0x0401,
+ SMSG_SYSTEM = 0x0400,
+ SMSG_CHAT = 0x0401,
SMSG_ANNOUNCEMENT = 0x0402,
+ SMSG_PRIVMSG = 0x0403,
CMSG_SAY = 0x0410,
CMSG_ANNOUNCE = 0x0411,
+ CMSG_PRIVMSG = 0x0412,
// Other
- SMSG_LOAD_MAP = 0x0500,
+ SMSG_LOAD_MAP = 0x0500,
// NOTE: We will need more messages for in-game control (eg. moving a client to a new map/position etc.). Currently the protocol only caters for the bare basics.
};
diff --git a/src/messagein.cpp b/src/messagein.cpp
index f5eaefe..8434f30 100644
--- a/src/messagein.cpp
+++ b/src/messagein.cpp
@@ -116,7 +116,7 @@ std::string MessageIn::readString(int length)
mPos += stringLength;
readString = tmpString;
- delete tmpString;
+ delete[] tmpString;
}
return readString;
diff --git a/src/state.cpp b/src/state.cpp
index a169e4c..919f181 100644
--- a/src/state.cpp
+++ b/src/state.cpp
@@ -24,6 +24,7 @@
#include "state.h"
#include <iostream>
#include "messageout.h"
+#include "utils/logger.h"
namespace tmwserv
{
@@ -31,32 +32,32 @@ namespace tmwserv
void State::update(ConnectionHandler &connectionHandler)
{
// update game state (update AI, etc.)
- for (std::map<std::string, Beings>::iterator i = beings.begin();
- i != beings.end();
+ for (std::map<std::string, MapComposite>::iterator i = maps.begin();
+ i != maps.end();
i++) {
- for (Beings::iterator b = i->second.begin();
- b != i->second.end();
+ for (Beings::iterator b = i->second.beings.begin();
+ b != i->second.beings.end();
b++) {
b->get()->update();
}
}
// notify clients about changes in the game world (only on their maps)
- // NOTE: This isn't finished ;)
- for (std::map<std::string, Beings>::iterator i = beings.begin();
- i != beings.end();
+ // NOTE: Should only send differences in the game state.
+ for (std::map<std::string, MapComposite>::iterator i = maps.begin();
+ i != maps.end();
i++) {
//
- for (Beings::iterator b = i->second.begin();
- b != i->second.end();
+ for (Beings::iterator b = i->second.beings.begin();
+ b != i->second.beings.end();
b++) {
// send info about other players
- for (Beings::iterator b2 = i->second.begin();
- b2 != i->second.end();
+ for (Beings::iterator b2 = i->second.beings.begin();
+ b2 != i->second.beings.end();
b2++) {
if (b != b2) {
MessageOut msg;
- msg.writeShort(SMSG_NEW_OBJECT); // of course this wont be send _all_ the time ;)
+ msg.writeShort(SMSG_NEW_BEING); //
msg.writeLong(OBJECT_PLAYER); // type
msg.writeLong((int)b2->get()); // id
msg.writeLong(b2->get()->getX());// x
@@ -67,7 +68,105 @@ void State::update(ConnectionHandler &connectionHandler)
}
}
}
+}
+
+void State::addBeing(Being *being, const std::string &map) {
+ if (!mapExists(map))
+ return;
+
+ if (!beingExists(being))
+ maps[map].beings.push_back(tmwserv::BeingPtr(being));
+}
+
+void State::removeBeing(Being *being) {
+ for (std::map<std::string, MapComposite>::iterator i = maps.begin();
+ i != maps.end();
+ i++) {
+ for (Beings::iterator b = i->second.beings.begin();
+ b != i->second.beings.end();
+ b++) {
+ if (b->get() == being) {
+ i->second.beings.erase(b);
+ return;
+ }
+ }
+ }
+}
+
+bool State::mapExists(const std::string &map) {
+ std::map<std::string, MapComposite>::iterator i = maps.find(map);
+ if (i == maps.end())
+ return false;
+ return true;
+}
+
+bool State::beingExists(Being *being) {
+ for (std::map<std::string, MapComposite>::iterator i = maps.begin();
+ i != maps.end();
+ i++) {
+ for (Beings::iterator b = i->second.beings.begin();
+ b != i->second.beings.end();
+ b++) {
+ if (b->get() == being)
+ return true;
+ }
+ }
+ return false;
+}
+
+void State::loadMap(const std::string &map) {
+ // load map
+ maps[map] = MapComposite();
+}
+void State::addObject(Object *object, const std::string &map) {
+ //
+}
+
+void State::removeObject(Object *object) {
+ //
+}
+
+bool State::objectExists(Object *object) {
+ for (std::map<std::string, MapComposite>::iterator i = maps.begin();
+ i != maps.end();
+ i++) {
+ for (std::vector<Object*>::iterator b = i->second.objects.begin();
+ b != i->second.objects.end();
+ b++) {
+ if (*b == object)
+ return true;
+ }
+ }
+ return false;
+}
+
+const std::string State::findPlayer(Being *being) {
+ for (std::map<std::string, MapComposite>::iterator i = maps.begin();
+ i != maps.end();
+ i++) {
+ for (Beings::iterator b = i->second.beings.begin();
+ b != i->second.beings.end();
+ b++) {
+ if (b->get() == being)
+ return i->first;
+ }
+ }
+ return "";
+}
+
+const std::string State::findObject(Object *object) {
+ for (std::map<std::string, MapComposite>::iterator i = maps.begin();
+ i != maps.end();
+ i++) {
+ for (std::vector<Object*>::iterator b = i->second.objects.begin();
+ b != i->second.objects.end();
+ b++) {
+ if (*b == object)
+ return i->first;
+ }
+ }
+ return "";
}
} // namespace tmwserv
diff --git a/src/state.h b/src/state.h
index 21bb756..4d1c9a3 100644
--- a/src/state.h
+++ b/src/state.h
@@ -36,7 +36,7 @@ namespace tmwserv
/**
* State class contains all information/procedures associated with the game
- * state.
+ * world's state.
*/
class State : public utils::Singleton<State>
{
@@ -45,36 +45,92 @@ class State : public utils::Singleton<State>
State() throw() { }
~State() throw() { }
+ /**
+ * Combined map/entity structure
+ */
+ struct MapComposite {
+ /**
+ * Default constructor
+ */
+ MapComposite() : map(NULL) { }
+
+ /**
+ * Actual map
+ */
+ Map *map;
+
+ /**
+ * Beings located on the map
+ */
+ Beings beings;
+
+ /**
+ * Items located on the map
+ */
+ std::vector<Object*> objects;
+ };
+
+ /**
+ * List of maps
+ */
+ std::map<std::string, MapComposite> maps;
+
public:
+
/**
- * Beings on map
- *
- * The key/value pair conforms to:
- * First - map name
- * Second - list of beings/players on the map
- *
- * NOTE: This could possibly be optimized by making first Being & second string. This will make many operations easier.
+ * Update game state (contains core server logic)
*/
- std::map<std::string, Beings> beings;
+ void update(ConnectionHandler &);
/**
- * Items on map
- *
- * The key/value pair conforms to:
- * First - map name
- * Second - Item ID
+ * Add being to game world at specified map
*/
- std::map<std::string, int> items;
+ void addBeing(Being *being, const std::string &map);
/**
- * Container for loaded maps.
+ * Remove being from game world
*/
- std::map<std::string, Map*> maps;
-
+ void removeBeing(Being *being);
+
/**
- * Update game state (contains core server logic)
+ * Check to see if a map exists in game world
*/
- void update(ConnectionHandler &);
+ bool mapExists(const std::string &map);
+
+ /**
+ * Check if being exists in game world already
+ */
+ bool beingExists(Being *being);
+
+ /**
+ * Load map into game world
+ */
+ void loadMap(const std::string &map);
+
+ /**
+ * Add object to the map
+ */
+ void addObject(Object *object, const std::string &map);
+
+ /**
+ * Remove an object from the map
+ */
+ void removeObject(Object *object);
+
+ /**
+ * Find out whether an object exists in the game world or not
+ */
+ bool objectExists(Object *object);
+
+ /**
+ * Find map player in world is on
+ */
+ const std::string findPlayer(Being *being);
+
+ /**
+ * Find map object in world is on
+ */
+ const std::string findObject(Object *object);
};
} // namespace tmwserv