cyphesis/tools/cycmd.cpp

1346 lines
39 KiB
C++
Raw Normal View History

2006-01-19 Al Riddoch <alriddoch@zepler.org> * aiclient/ClientAccount.cpp, aiclient/ClientAccount.h, aiclient/ClientConnection.cpp, aiclient/ClientConnection.h, aiclient/client.cpp, aiclient/client.h, client/BaseClient.cpp, client/BaseClient.h, client/CharacterClient.cpp, client/CharacterClient.h, client/ClientConnection.cpp, client/ClientConnection.h, client/CreatorClient.cpp, client/CreatorClient.h, client/ObserverClient.cpp, client/ObserverClient.h, client/Py_CreatorClient.cpp, client/Py_CreatorClient.h, client/client.cpp, client/define_world.cpp, client/define_world.h, common/Add.h, common/Affect.h, common/AtlasFileLoader.cpp, common/AtlasFileLoader.h, common/Attack.h, common/BaseEntity.cpp, common/BaseEntity.h, common/BaseWorld.cpp, common/BaseWorld.h, common/Burn.h, common/Chop.h, common/Connect.h, common/CustomOp.cpp, common/CustomOp.h, common/CustomOp_impl.h, common/Cut.h, common/Database.cpp, common/Database.h, common/Delve.h, common/Dig.h, common/Eat.h, common/FormattedXMLWriter.cpp, common/FormattedXMLWriter.h, common/Generic.h, common/Load.h, common/Monitor.h, common/Mow.h, common/Nourish.h, common/OOGThing.cpp, common/OOGThing.h, common/Property.cpp, common/Property.h, common/Property_impl.h, common/Save.h, common/Setup.h, common/Tick.h, common/Unseen.h, common/Update.h, common/Use.h, common/Wield.h, common/accountbase.cpp, common/accountbase.h, common/const.cpp, common/const.h, common/custom.cpp, common/debug.h, common/globals.cpp, common/globals.h, common/id.cpp, common/id.h, common/inheritance.cpp, common/inheritance.h, common/inheritance_impl.h, common/log.cpp, common/log.h, common/newid.cpp, common/nls.h, common/op_switch.h, common/operations.cpp, common/operations.h, common/random.h, common/refno.h, common/serialno.cpp, common/serialno.h, common/system.cpp, common/system.h, common/terrain_utils.cpp, common/terrain_utils.h, common/type_utils.h, common/types.h, common/utility.cpp, common/utility.h, modules/DateTime.cpp, modules/DateTime.h, modules/Location.cpp, modules/Location.h, modules/WorldTime.cpp, modules/WorldTime.h, physics/BBox.cpp, physics/BBox.h, physics/Collision.cpp, physics/Collision.h, physics/Quaternion.cpp, physics/Quaternion.h, physics/Vector3D.cpp, physics/Vector3D.h, physics/VectorPol.h, rulesets/Area.cpp, rulesets/Area.h, rulesets/AreaProperty.cpp, rulesets/AreaProperty.h, rulesets/ArithmeticScript.cpp, rulesets/ArithmeticScript.h, rulesets/BaseMind.cpp, rulesets/BaseMind.h, rulesets/CalendarProperty.cpp, rulesets/CalendarProperty.h, rulesets/Character.cpp, rulesets/Character.h, rulesets/Combat.cpp, rulesets/Combat.h, rulesets/Container.cpp, rulesets/Container.h, rulesets/Creator.cpp, rulesets/Creator.h, rulesets/Entity.cpp, rulesets/Entity.h, rulesets/EntityProperties.cpp, rulesets/Entity_getLocation.h, rulesets/Fell.cpp, rulesets/Fell.h, rulesets/Food.cpp, rulesets/Food.h, rulesets/Line.cpp, rulesets/Line.h, rulesets/LineProperty.cpp, rulesets/LineProperty.h, rulesets/MemEntity.cpp, rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/MemMap.h, rulesets/MemMap_methods.h, rulesets/MindFactory.cpp, rulesets/MindFactory.h, rulesets/Missile.h, rulesets/Motion.cpp, rulesets/Motion.h, rulesets/Movement.cpp, rulesets/Movement.h, rulesets/Pedestrian.cpp, rulesets/Pedestrian.h, rulesets/Plant.cpp, rulesets/Plant.h, rulesets/Py_BBox.cpp, rulesets/Py_BBox.h, rulesets/Py_EntityWrapper.h, rulesets/Py_Location.cpp, rulesets/Py_Location.h, rulesets/Py_Map.cpp, rulesets/Py_Map.h, rulesets/Py_Mind.cpp, rulesets/Py_Mind.h, rulesets/Py_Object.cpp, rulesets/Py_Object.h, rulesets/Py_Operation.cpp, rulesets/Py_Operation.h, rulesets/Py_Oplist.cpp, rulesets/Py_Oplist.h, rulesets/Py_Optime.cpp, rulesets/Py_Optime.h, rulesets/Py_Point3D.cpp, rulesets/Py_Point3D.h, rulesets/Py_Property.cpp, rulesets/Py_Property.h, rulesets/Py_Quaternion.cpp, rulesets/Py_Quaternion.h, rulesets/Py_RootEntity.cpp, rulesets/Py_RootEntity.h, rulesets/Py_Statistics.cpp, rulesets/Py_Statistics.h, rulesets/Py_Task.cpp, rulesets/Py_Task.h, rulesets/Py_Thing.cpp, rulesets/Py_Thing.h, rulesets/Py_Vector3D.cpp, rulesets/Py_Vector3D.h, rulesets/Py_World.cpp, rulesets/Py_World.h, rulesets/Py_WorldTime.cpp, rulesets/Py_WorldTime.h, rulesets/PythonArithmeticScript.cpp, rulesets/PythonArithmeticScript.h, rulesets/PythonMindScript.cpp, rulesets/PythonMindScript.h, rulesets/PythonScript.cpp, rulesets/PythonScript.h, rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h, rulesets/PythonWrapper.cpp, rulesets/PythonWrapper.h, rulesets/Python_API.cpp, rulesets/Python_API.h, rulesets/Python_Script_Utils.h, rulesets/Script.cpp, rulesets/Script.h, rulesets/Stackable.cpp, rulesets/Stackable.h, rulesets/Statistics.cpp, rulesets/Statistics.h, rulesets/StatisticsProperty.cpp, rulesets/StatisticsProperty.h, rulesets/Structure.cpp, rulesets/Structure.h, rulesets/Task.cpp, rulesets/Task.h, rulesets/TaskScript.cpp, rulesets/TaskScript.h, rulesets/TerrainProperty.cpp, rulesets/TerrainProperty.h, rulesets/Thing.cpp, rulesets/Thing.h, rulesets/ThingFactory.cpp, rulesets/ThingFactory.h, rulesets/World.cpp, rulesets/World.h, rulesets/attributes.h, server/Account.cpp, server/Account.h, server/Admin.cpp, server/Admin.h, server/ArithmeticFactory.cpp, server/ArithmeticFactory.h, server/CommClient.cpp, server/CommClient.h, server/CommIdleSocket.cpp, server/CommIdleSocket.h, server/CommListener.cpp, server/CommListener.h, server/CommLocalClient.cpp, server/CommLocalClient.h, server/CommMDNSPublisher.cpp, server/CommMDNSPublisher.h, server/CommMaster.cpp, server/CommMaster.h, server/CommMetaClient.cpp, server/CommMetaClient.h, server/CommPSQLSocket.cpp, server/CommPSQLSocket.h, server/CommPeer.cpp, server/CommPeer.h, server/CommPeerListener.cpp, server/CommPeerListener.h, server/CommRemoteClient.cpp, server/CommRemoteClient.h, server/CommServer.cpp, server/CommServer.h, server/CommSlaveClient.cpp, server/CommSlaveClient.h, server/CommSlaveListener.cpp, server/CommSlaveListener.h, server/CommSocket.cpp, server/CommSocket.h, server/CommUnixListener.cpp, server/CommUnixListener.h, server/Connection.cpp, server/Connection.h, server/Connection_methods.h, server/EntityFactory.cpp, server/EntityFactory.h, server/ExternalMind.cpp, server/ExternalMind.h, server/Idle.cpp, server/Idle.h, server/Lobby.cpp, server/Lobby.h, server/Master.cpp, server/Master.h, server/Peer.cpp, server/Peer.h, server/Persistance.cpp, server/Persistance.h, server/PersistantThingFactory.cpp, server/PersistantThingFactory.h, server/PersistantThingFactory_impl.h, server/Persistor.cpp, server/Persistor.h, server/Persistor_impl.h, server/Player.cpp, server/Player.h, server/Restoration.cpp, server/Restoration.h, server/Restorer.cpp, server/Restorer.h, server/Restorer_impl.h, server/ScriptFactory.cpp, server/ScriptFactory.h, server/ServerRouting.cpp, server/ServerRouting.h, server/ServerRouting_methods.h, server/SlaveClientConnection.cpp, server/SlaveClientConnection.h, server/TaskFactory.cpp, server/TaskFactory.h, server/TrustedConnection.cpp, server/TrustedConnection.h, server/WorldRouter.cpp, server/WorldRouter.h, server/server.cpp, server/server.h, server/slave.cpp, tests/Areatest.cpp, tests/BaseEntitytest.cpp, tests/Charactertest.cpp, tests/Containertest.cpp, tests/Creatortest.cpp, tests/EntityExerciser.h, tests/EntityFactorytest.cpp, tests/Entitytest.cpp, tests/Foodtest.cpp, tests/IGEntityExerciser.h, tests/Linetest.cpp, tests/Locationtest.cpp, tests/OOGThingtest.cpp, tests/Planttest.cpp, tests/Propertytest.cpp, tests/Stackabletest.cpp, tests/Structuretest.cpp, tests/Tasktest.cpp, tests/TestWorld.h, tests/Thingtest.cpp, tests/WorldTimetest.cpp, tests/Worldtest.cpp, tests/allOperations.h, tests/collisiontest.cpp, tests/consttest.cpp, tests/distancetest.cpp, tests/emergencetest.cpp, tests/inheritancetest.cpp, tests/logtest.cpp, tests/randomtest.cpp, tests/systemtest.cpp, tests/transformtest.cpp, tests/type_utilstest.cpp, tests/utilitytest.cpp, tools/AdminClient.cpp, tools/AdminClient.h, tools/cyaddrules.cpp, tools/cycmd.cpp, tools/cyconfig.cpp, tools/cyconvertrules.cpp, tools/cyctrl.cpp, tools/cydbload.cpp, tools/cydumprules.cpp, tools/cyisoload.cpp, tools/cyloadrules.cpp, tools/cypasswd.cpp, tools/cywatchdog.cpp: Replace the copyright and license statements with new versions that include disclaimer of warranty, and permit distribution under later versions of the GPL.
2006-01-19 02:17:06 +00:00
// Cyphesis Online RPG Server and AI Engine
// Copyright (C) 2001 Alistair Riddoch
2006-01-19 Al Riddoch <alriddoch@zepler.org> * aiclient/ClientAccount.cpp, aiclient/ClientAccount.h, aiclient/ClientConnection.cpp, aiclient/ClientConnection.h, aiclient/client.cpp, aiclient/client.h, client/BaseClient.cpp, client/BaseClient.h, client/CharacterClient.cpp, client/CharacterClient.h, client/ClientConnection.cpp, client/ClientConnection.h, client/CreatorClient.cpp, client/CreatorClient.h, client/ObserverClient.cpp, client/ObserverClient.h, client/Py_CreatorClient.cpp, client/Py_CreatorClient.h, client/client.cpp, client/define_world.cpp, client/define_world.h, common/Add.h, common/Affect.h, common/AtlasFileLoader.cpp, common/AtlasFileLoader.h, common/Attack.h, common/BaseEntity.cpp, common/BaseEntity.h, common/BaseWorld.cpp, common/BaseWorld.h, common/Burn.h, common/Chop.h, common/Connect.h, common/CustomOp.cpp, common/CustomOp.h, common/CustomOp_impl.h, common/Cut.h, common/Database.cpp, common/Database.h, common/Delve.h, common/Dig.h, common/Eat.h, common/FormattedXMLWriter.cpp, common/FormattedXMLWriter.h, common/Generic.h, common/Load.h, common/Monitor.h, common/Mow.h, common/Nourish.h, common/OOGThing.cpp, common/OOGThing.h, common/Property.cpp, common/Property.h, common/Property_impl.h, common/Save.h, common/Setup.h, common/Tick.h, common/Unseen.h, common/Update.h, common/Use.h, common/Wield.h, common/accountbase.cpp, common/accountbase.h, common/const.cpp, common/const.h, common/custom.cpp, common/debug.h, common/globals.cpp, common/globals.h, common/id.cpp, common/id.h, common/inheritance.cpp, common/inheritance.h, common/inheritance_impl.h, common/log.cpp, common/log.h, common/newid.cpp, common/nls.h, common/op_switch.h, common/operations.cpp, common/operations.h, common/random.h, common/refno.h, common/serialno.cpp, common/serialno.h, common/system.cpp, common/system.h, common/terrain_utils.cpp, common/terrain_utils.h, common/type_utils.h, common/types.h, common/utility.cpp, common/utility.h, modules/DateTime.cpp, modules/DateTime.h, modules/Location.cpp, modules/Location.h, modules/WorldTime.cpp, modules/WorldTime.h, physics/BBox.cpp, physics/BBox.h, physics/Collision.cpp, physics/Collision.h, physics/Quaternion.cpp, physics/Quaternion.h, physics/Vector3D.cpp, physics/Vector3D.h, physics/VectorPol.h, rulesets/Area.cpp, rulesets/Area.h, rulesets/AreaProperty.cpp, rulesets/AreaProperty.h, rulesets/ArithmeticScript.cpp, rulesets/ArithmeticScript.h, rulesets/BaseMind.cpp, rulesets/BaseMind.h, rulesets/CalendarProperty.cpp, rulesets/CalendarProperty.h, rulesets/Character.cpp, rulesets/Character.h, rulesets/Combat.cpp, rulesets/Combat.h, rulesets/Container.cpp, rulesets/Container.h, rulesets/Creator.cpp, rulesets/Creator.h, rulesets/Entity.cpp, rulesets/Entity.h, rulesets/EntityProperties.cpp, rulesets/Entity_getLocation.h, rulesets/Fell.cpp, rulesets/Fell.h, rulesets/Food.cpp, rulesets/Food.h, rulesets/Line.cpp, rulesets/Line.h, rulesets/LineProperty.cpp, rulesets/LineProperty.h, rulesets/MemEntity.cpp, rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/MemMap.h, rulesets/MemMap_methods.h, rulesets/MindFactory.cpp, rulesets/MindFactory.h, rulesets/Missile.h, rulesets/Motion.cpp, rulesets/Motion.h, rulesets/Movement.cpp, rulesets/Movement.h, rulesets/Pedestrian.cpp, rulesets/Pedestrian.h, rulesets/Plant.cpp, rulesets/Plant.h, rulesets/Py_BBox.cpp, rulesets/Py_BBox.h, rulesets/Py_EntityWrapper.h, rulesets/Py_Location.cpp, rulesets/Py_Location.h, rulesets/Py_Map.cpp, rulesets/Py_Map.h, rulesets/Py_Mind.cpp, rulesets/Py_Mind.h, rulesets/Py_Object.cpp, rulesets/Py_Object.h, rulesets/Py_Operation.cpp, rulesets/Py_Operation.h, rulesets/Py_Oplist.cpp, rulesets/Py_Oplist.h, rulesets/Py_Optime.cpp, rulesets/Py_Optime.h, rulesets/Py_Point3D.cpp, rulesets/Py_Point3D.h, rulesets/Py_Property.cpp, rulesets/Py_Property.h, rulesets/Py_Quaternion.cpp, rulesets/Py_Quaternion.h, rulesets/Py_RootEntity.cpp, rulesets/Py_RootEntity.h, rulesets/Py_Statistics.cpp, rulesets/Py_Statistics.h, rulesets/Py_Task.cpp, rulesets/Py_Task.h, rulesets/Py_Thing.cpp, rulesets/Py_Thing.h, rulesets/Py_Vector3D.cpp, rulesets/Py_Vector3D.h, rulesets/Py_World.cpp, rulesets/Py_World.h, rulesets/Py_WorldTime.cpp, rulesets/Py_WorldTime.h, rulesets/PythonArithmeticScript.cpp, rulesets/PythonArithmeticScript.h, rulesets/PythonMindScript.cpp, rulesets/PythonMindScript.h, rulesets/PythonScript.cpp, rulesets/PythonScript.h, rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h, rulesets/PythonWrapper.cpp, rulesets/PythonWrapper.h, rulesets/Python_API.cpp, rulesets/Python_API.h, rulesets/Python_Script_Utils.h, rulesets/Script.cpp, rulesets/Script.h, rulesets/Stackable.cpp, rulesets/Stackable.h, rulesets/Statistics.cpp, rulesets/Statistics.h, rulesets/StatisticsProperty.cpp, rulesets/StatisticsProperty.h, rulesets/Structure.cpp, rulesets/Structure.h, rulesets/Task.cpp, rulesets/Task.h, rulesets/TaskScript.cpp, rulesets/TaskScript.h, rulesets/TerrainProperty.cpp, rulesets/TerrainProperty.h, rulesets/Thing.cpp, rulesets/Thing.h, rulesets/ThingFactory.cpp, rulesets/ThingFactory.h, rulesets/World.cpp, rulesets/World.h, rulesets/attributes.h, server/Account.cpp, server/Account.h, server/Admin.cpp, server/Admin.h, server/ArithmeticFactory.cpp, server/ArithmeticFactory.h, server/CommClient.cpp, server/CommClient.h, server/CommIdleSocket.cpp, server/CommIdleSocket.h, server/CommListener.cpp, server/CommListener.h, server/CommLocalClient.cpp, server/CommLocalClient.h, server/CommMDNSPublisher.cpp, server/CommMDNSPublisher.h, server/CommMaster.cpp, server/CommMaster.h, server/CommMetaClient.cpp, server/CommMetaClient.h, server/CommPSQLSocket.cpp, server/CommPSQLSocket.h, server/CommPeer.cpp, server/CommPeer.h, server/CommPeerListener.cpp, server/CommPeerListener.h, server/CommRemoteClient.cpp, server/CommRemoteClient.h, server/CommServer.cpp, server/CommServer.h, server/CommSlaveClient.cpp, server/CommSlaveClient.h, server/CommSlaveListener.cpp, server/CommSlaveListener.h, server/CommSocket.cpp, server/CommSocket.h, server/CommUnixListener.cpp, server/CommUnixListener.h, server/Connection.cpp, server/Connection.h, server/Connection_methods.h, server/EntityFactory.cpp, server/EntityFactory.h, server/ExternalMind.cpp, server/ExternalMind.h, server/Idle.cpp, server/Idle.h, server/Lobby.cpp, server/Lobby.h, server/Master.cpp, server/Master.h, server/Peer.cpp, server/Peer.h, server/Persistance.cpp, server/Persistance.h, server/PersistantThingFactory.cpp, server/PersistantThingFactory.h, server/PersistantThingFactory_impl.h, server/Persistor.cpp, server/Persistor.h, server/Persistor_impl.h, server/Player.cpp, server/Player.h, server/Restoration.cpp, server/Restoration.h, server/Restorer.cpp, server/Restorer.h, server/Restorer_impl.h, server/ScriptFactory.cpp, server/ScriptFactory.h, server/ServerRouting.cpp, server/ServerRouting.h, server/ServerRouting_methods.h, server/SlaveClientConnection.cpp, server/SlaveClientConnection.h, server/TaskFactory.cpp, server/TaskFactory.h, server/TrustedConnection.cpp, server/TrustedConnection.h, server/WorldRouter.cpp, server/WorldRouter.h, server/server.cpp, server/server.h, server/slave.cpp, tests/Areatest.cpp, tests/BaseEntitytest.cpp, tests/Charactertest.cpp, tests/Containertest.cpp, tests/Creatortest.cpp, tests/EntityExerciser.h, tests/EntityFactorytest.cpp, tests/Entitytest.cpp, tests/Foodtest.cpp, tests/IGEntityExerciser.h, tests/Linetest.cpp, tests/Locationtest.cpp, tests/OOGThingtest.cpp, tests/Planttest.cpp, tests/Propertytest.cpp, tests/Stackabletest.cpp, tests/Structuretest.cpp, tests/Tasktest.cpp, tests/TestWorld.h, tests/Thingtest.cpp, tests/WorldTimetest.cpp, tests/Worldtest.cpp, tests/allOperations.h, tests/collisiontest.cpp, tests/consttest.cpp, tests/distancetest.cpp, tests/emergencetest.cpp, tests/inheritancetest.cpp, tests/logtest.cpp, tests/randomtest.cpp, tests/systemtest.cpp, tests/transformtest.cpp, tests/type_utilstest.cpp, tests/utilitytest.cpp, tools/AdminClient.cpp, tools/AdminClient.h, tools/cyaddrules.cpp, tools/cycmd.cpp, tools/cyconfig.cpp, tools/cyconvertrules.cpp, tools/cyctrl.cpp, tools/cydbload.cpp, tools/cydumprules.cpp, tools/cyisoload.cpp, tools/cyloadrules.cpp, tools/cypasswd.cpp, tools/cywatchdog.cpp: Replace the copyright and license statements with new versions that include disclaimer of warranty, and permit distribution under later versions of the GPL.
2006-01-19 02:17:06 +00:00
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
// $Id$
/// \page cycmd_index
///
/// \section Introduction
///
/// cycmd is a commandline tool to administrate the running server. For
/// information on the commands available, please see the unix manual page.
/// The manual page is generated from docbook sources, so can
/// also be converted into other formats.
///
/// The majority of the functionality is encapsulated by the Interactive
/// class template.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "common/log.h"
#include "common/OperationRouter.h"
#include "common/globals.h"
#include "common/sockets.h"
#include "common/Tick.h"
#include <Atlas/Objects/Encoder.h>
#include <Atlas/Net/Stream.h>
#include <Atlas/Objects/Decoder.h>
#include <Atlas/Codec.h>
#include <Atlas/Objects/Entity.h>
#include <Atlas/Objects/Anonymous.h>
#include <Atlas/Objects/Operation.h>
#include <varconf/config.h>
#include "common/Monitor.h"
#include "common/Connect.h"
#include "common/compose.hpp"
#include <skstream/skstream_unix.h>
#include <sigc++/connection.h>
#ifndef READLINE_CXX_SANE // defined in config.h
extern "C" {
#endif
#define USE_VARARGS
#define PREFER_STDARG
#include <readline/readline.h>
#include <readline/history.h>
#ifndef READLINE_CXX_SANE
}
#endif
#include <iostream>
#include <algorithm>
#include <cstdio>
using Atlas::Message::Element;
using Atlas::Message::MapType;
using Atlas::Message::ListType;
using Atlas::Objects::Root;
using Atlas::Objects::Operation::Appearance;
using Atlas::Objects::Operation::Create;
using Atlas::Objects::Operation::Delete;
using Atlas::Objects::Operation::Disappearance;
using Atlas::Objects::Operation::Get;
using Atlas::Objects::Operation::Set;
using Atlas::Objects::Operation::Look;
using Atlas::Objects::Operation::Login;
using Atlas::Objects::Operation::Logout;
using Atlas::Objects::Operation::Talk;
using Atlas::Objects::Operation::Tick;
using Atlas::Objects::Entity::RootEntity;
using Atlas::Objects::Entity::Anonymous;
using Atlas::Objects::smart_dynamic_cast;
using Atlas::Objects::Operation::Monitor;
using Atlas::Objects::Operation::Connect;
/// \brief Entry in the global command table for cycmd
struct command {
const char * cmd_string;
const char * cmd_description;
};
struct command commands[] = {
{ "add_agent", "Create an in-game agent", },
{ "connect", "Connect server to a peer", },
{ "cancel", "Cancel the current admin task", },
{ "creator_create", "Use agent to create an entity", },
{ "delete", "Delete an entity from the server", },
{ "get", "Examine a class on the server", },
{ "find_by_name", "Find an entity with the given name", },
{ "find_by_type", "Find an entity with the given type", },
{ "flush", "Flush entities from the server", },
{ "help", "Display this help", },
{ "install", "Install a new type", },
{ "look", "Return the current server lobby", },
{ "logout", "Log user out of server", },
{ "monitor", "Enable in-game op monitoring", },
{ "query", "Examine an object on the server", },
{ "reload", "Reload the script for a type", },
{ "stat", "Return current server status", },
{ "unmonitor", "Disable in-game op monitoring", },
{ NULL, "Guard", }
};
2001-06-04 11:22:27 +00:00
static void help()
{
size_t max_length = 0;
for (struct command * I = &commands[0]; I->cmd_string != NULL; ++I) {
max_length = std::max(max_length, strlen(I->cmd_string));
}
max_length += 2;
std::cout << "Cyphesis commands:" << std::endl << std::endl;
for (struct command * I = &commands[0]; I->cmd_string != NULL; ++I) {
std::cout << " " << I->cmd_string
<< std::string(max_length - strlen(I->cmd_string), ' ')
<< I->cmd_description << std::endl;
}
std::cout << std::endl << std::flush;
}
/// \brief Base class for admin tasks which run for some time.
///
/// Typical tasks that inherit from this class are ones which last for
/// non trivial time and will typically require the user to be able to
/// continue issuing commands.
class AdminTask {
protected:
/// \brief Flag that indicates when the task is complete
bool m_complete;
///\brief AdminTask constructor
AdminTask() : m_complete(false) { }
public:
virtual ~AdminTask() { }
/// \brief Set up the task processing user arguments
virtual void setup(const std::string & arg, OpVector &) = 0;
/// \brief Handle an operation from the server
virtual void operation(const Operation &, OpVector &) = 0;
/// \brief Check whether the task is complete
///
/// @return true if the task is complete, false otherwise
bool isComplete() const { return m_complete; }
};
/// \brief Task class for flushing the server of character entities
class Flusher : public AdminTask {
protected:
const std::string agentId;
std::string type;
public:
explicit Flusher(const std::string & agent_id) : agentId(agent_id) { }
void setup(const std::string & arg, OpVector & ret) {
type = arg;
// Send a look to search by type.
Look l;
Anonymous lmap;
lmap->setParents(std::list<std::string>(1, type));
l->setArgs1(lmap);
l->setFrom(agentId);
ret.push_back(l);
}
void operation(const Operation & op, OpVector & res) {
if (op->getClassNo() == Atlas::Objects::Operation::SIGHT_NO) {
// We have a sight op, check if its the sight of an entity we
// want to delete.
const std::vector<Root> & args = op->getArgs();
if (args.empty()) {
std::cerr << "Got empty sight" << std::endl << std::flush;
return;
}
const Root & arg = args.front();
assert(arg.isValid());
RootEntity sight_ent = smart_dynamic_cast<RootEntity>(arg);
if (!sight_ent.isValid()) {
return;
}
if (!sight_ent->hasAttrFlag(Atlas::Objects::ID_FLAG)) {
std::cerr << "Got sight no ID" << std::endl << std::flush;
return;
}
if (!sight_ent->hasAttrFlag(Atlas::Objects::PARENTS_FLAG)) {
std::cerr << "Got sight no PARENTS" << std::endl << std::flush;
return;
}
if (sight_ent->getParents().empty() ||
sight_ent->getParents().front() != type) {
return;
}
const std::string & id = sight_ent->getId();
std::cout << "Deleting: " << type << "(" << id << ")"
<< std::endl << std::flush;
// Send a delete to the entity we have seen.
Delete d;
Anonymous dmap;
dmap->setId(id);
d->setArgs1(dmap);
d->setFrom(agentId);
d->setTo(id);
res.push_back(d);
// Send a tick for a short time in the future so that
// we can look again once this entity is definitly gone.
Tick t;
Anonymous tick_arg;
tick_arg->setName("flusher");
t->setFrom(agentId);
t->setTo(agentId);
t->setFutureSeconds(0.1);
t->setArgs1(tick_arg);
res.push_back(t);
} else if (op->getParents().front() == "tick") {
// We have a tick op, check if its the one we sent ourselves
// to schedule the next look.
if (op->getArgs().empty() ||
op->getArgs().front()->getName() != "flusher") {
std::cout << "Not for us" << std::endl << std::flush;
return;
}
// Send another look by type.
Look l;
Anonymous lmap;
lmap->setParents(std::list<std::string>(1, type));
l->setArgs1(lmap);
l->setFrom(agentId);
res.push_back(l);
} else if (op->getParents().front() == "unseen") {
// We have an unseen op, which signals our last look returned
// no results.
m_complete = true;
}
}
};
/// \brief Task class for monitoring all in-game operations occuring.
class OperationMonitor : public AdminTask {
protected:
int op_count;
int start_time;
public:
int count() {
return op_count;
}
int startTime() {
return start_time;
}
virtual void setup(const std::string & arg, OpVector &) {
struct timeval tv;
gettimeofday(&tv, NULL);
start_time = tv.tv_sec;
op_count = 0;
}
virtual void operation(const Operation & op, OpVector &) {
++op_count;
std::cout << op->getParents().front() << "(from=\"" << op->getFrom()
<< "\",to=\"" << op->getTo() << "\")"
<< std::endl << std::flush;
}
};
/// \brief Class template for clients used to connect to and administrate
/// a cyphesis server.
class Interactive : public Atlas::Objects::ObjectsDecoder,
virtual public sigc::trackable
{
private:
bool error_flag, reply_flag, login_flag, avatar_flag, server_flag;
int cli_fd;
Atlas::Objects::ObjectsEncoder * encoder;
Atlas::Codec * codec;
basic_socket_stream * ios;
std::string password;
std::string username;
std::string accountType;
std::string accountId;
std::string agentId;
std::string agentName;
std::string serverName;
std::string systemType;
std::string prompt;
bool exit;
AdminTask * currentTask;
void output(const Element & item, int depth = 0);
protected:
void objectArrived(const Atlas::Objects::Root &);
void appearanceArrived(const Operation &);
void disappearanceArrived(const Operation &);
void infoArrived(const Operation &);
void errorArrived(const Operation &);
void sightArrived(const Operation &);
void soundArrived(const Operation &);
int negotiate();
void updatePrompt();
public:
Interactive() : error_flag(false), reply_flag(false), login_flag(false),
avatar_flag(false), server_flag(false), encoder(0),
codec(0), ios(0), serverName("cyphesis"), prompt("cyphesis> "),
exit(false), currentTask(0)
{ }
~Interactive() {
if (encoder != 0) {
delete encoder;
}
if (codec != 0) {
delete codec;
}
}
void send(const Operation &);
int connect_tcp(const std::string & host);
int connect_unix(const std::string & host);
int login();
int setup();
void exec(const std::string & cmd, const std::string & arg);
void loop();
void poll(bool rewrite_prompt = true);
void getLogin();
void runCommand(char *);
int runTask(AdminTask * task, const std::string & arg);
int endTask();
void setPassword(const std::string & passwd) {
password = passwd;
}
void setUsername(const std::string & uname) {
username = uname;
}
static void gotCommand(char *);
};
void Interactive::output(const Element & item, int depth)
{
switch (item.getType()) {
case Element::TYPE_INT:
std::cout << item.Int();
break;
case Element::TYPE_FLOAT:
std::cout << item.Float();
break;
case Element::TYPE_STRING:
std::cout << "\"" << item.String() << "\"";
break;
case Element::TYPE_LIST:
{
std::cout << "[ ";
ListType::const_iterator I = item.List().begin();
ListType::const_iterator Iend = item.List().end();
for(; I != Iend; ++I) {
output(*I, depth);
std::cout << " ";
}
std::cout << "]";
}
break;
case Element::TYPE_MAP:
{
std::cout << "{" << std::endl << std::flush;
MapType::const_iterator I = item.Map().begin();
MapType::const_iterator Iend = item.Map().end();
for(; I != Iend; ++I) {
std::cout << std::string((depth + 1) * 4, ' ') << I->first << ": ";
output(I->second, depth + 1);
std::cout << std::endl;
}
std::cout << std::string(depth * 4, ' ') << "}";
}
break;
default:
std::cout << "(\?\?\?)";
break;
}
}
void Interactive::objectArrived(const Atlas::Objects::Root & obj)
{
Operation op = Atlas::Objects::smart_dynamic_cast<Operation>(obj);
if (!op.isValid()) {
std::cerr << "Non op object received from client" << std::endl << std::flush;
if (!obj->isDefaultParents() && !obj->getParents().empty()) {
std::cerr << "NOTICE: Unexpected object has parent "
<< obj->getParents().front()
<< std::endl << std::flush;
}
if (!obj->isDefaultObjtype()) {
std::cerr << "NOTICE: Unexpected object has objtype "
<< obj->getObjtype()
<< std::endl << std::flush;
}
return;
}
if (currentTask != 0) {
OpVector res;
currentTask->operation(op, res);
OpVector::const_iterator Iend = res.end();
for (OpVector::const_iterator I = res.begin(); I != Iend; ++I) {
encoder->streamObjectsMessage(*I);
}
(*ios) << std::flush;
if (currentTask->isComplete()) {
delete currentTask;
currentTask = 0;
}
}
switch (op->getClassNo()) {
case Atlas::Objects::Operation::APPEARANCE_NO:
appearanceArrived(op);
break;
case Atlas::Objects::Operation::DISAPPEARANCE_NO:
disappearanceArrived(op);
break;
case Atlas::Objects::Operation::INFO_NO:
infoArrived(op);
break;
case Atlas::Objects::Operation::ERROR_NO:
errorArrived(op);
break;
case Atlas::Objects::Operation::SIGHT_NO:
sightArrived(op);
break;
case Atlas::Objects::Operation::SOUND_NO:
soundArrived(op);
break;
default:
break;
}
}
void Interactive::appearanceArrived(const Operation & op)
{
if (accountId.empty()) {
return;
}
if (accountId != op->getTo()) {
// This is an IG op we are monitoring
return;
}
if (op->getArgs().empty()) {
return;
}
RootEntity ent = smart_dynamic_cast<RootEntity>(op->getArgs().front());
if (!ent.isValid()) {
std::cerr << "Got Appearance of non-entity" << std::endl << std::flush;
return;
}
if (!ent->hasAttrFlag(Atlas::Objects::ID_FLAG)) {
std::cerr << "Got Appearance of non-string ID" << std::endl << std::flush;
return;
}
const std::string & id = ent->getId();
std::cout << "Appearance(id: " << id << ")";
if (!ent->hasAttrFlag(Atlas::Objects::Entity::LOC_FLAG)) {
std::cout << std::endl << std::flush;
return;
}
const std::string & loc = ent->getLoc();
std::cout << " in " << loc << std::endl;
if (loc == "lobby") {
std::cout << id << " has logged in." << std::endl;
}
std::cout << std::flush;
}
void Interactive::disappearanceArrived(const Operation & op)
{
if (accountId.empty()) {
return;
}
if (accountId != op->getTo()) {
// This is an IG op we are monitoring
return;
}
if (op->getArgs().empty()) {
return;
}
RootEntity ent = smart_dynamic_cast<RootEntity>(op->getArgs().front());
if (!ent.isValid()) {
std::cerr << "Got Disappearance of non-entity" << std::endl << std::flush;
return;
}
if (!ent->hasAttrFlag(Atlas::Objects::ID_FLAG)) {
std::cerr << "Got Disappearance of non-string ID" << std::endl << std::flush;
return;
}
const std::string & id = ent->getId();
std::cout << "Disappearance(id: " << id << ")";
if (!ent->hasAttrFlag(Atlas::Objects::Entity::LOC_FLAG)) {
std::cout << std::endl << std::flush;
return;
}
const std::string & loc = ent->getLoc();
std::cout << " in " << loc << std::endl;
if (loc == "lobby") {
std::cout << id << " has logged out." << std::endl;
}
std::cout << std::flush;
}
void Interactive::infoArrived(const Operation & op)
{
reply_flag = true;
if (op->getArgs().empty()) {
return;
}
const Root & ent = op->getArgs().front();
if (login_flag) {
std::cout << "login success" << std::endl << std::flush;
if (ent->isDefaultId()) {
std::cerr << "ERROR: Response to login does not contain account id"
<< std::endl << std::flush;
} else {
accountId = ent->getId();
}
if (!ent->isDefaultParents()) {
const std::list<std::string> & parents = ent->getParents();
if (!parents.empty()) {
accountType = parents.front();
}
}
} else if (avatar_flag) {
std::cout << "Create agent success" << std::endl << std::flush;
if (!ent->hasAttrFlag(Atlas::Objects::ID_FLAG)) {
std::cerr << "ERROR: Response to agent create does not contain agent id"
<< std::endl << std::flush;
} else {
agentId = ent->getId();
avatar_flag = false;
}
} else if (server_flag) {
std::cout << "Server query success" << std::endl << std::flush;
if (!ent->isDefaultName()) {
serverName = ent->getName();
std::string::size_type p = serverName.find(".");
if (p != std::string::npos) {
serverName = serverName.substr(0, p);
}
updatePrompt();
}
Element raw_attr;
if (ent->copyAttr("server", raw_attr) == 0) {
if (raw_attr.isString()) {
systemType = raw_attr.String();
updatePrompt();
}
}
server_flag = false;
} else {
std::cout << "Info(" << std::endl;
MapType entmap = ent->asMessage();
MapType::const_iterator Iend = entmap.end();
for (MapType::const_iterator I = entmap.begin(); I != Iend; ++I) {
const Element & item = I->second;
std::cout << " " << I->first << ": ";
output(item, 1);
std::cout << std::endl;
}
std::cout << ")" << std::endl << std::flush;
// Display results of command
}
}
void Interactive::errorArrived(const Operation & op)
{
reply_flag = true;
error_flag = true;
std::cout << "Error(";
const std::vector<Root> & args = op->getArgs();
const Root & arg = args.front();
Element message_attr;
if (arg->copyAttr("message", message_attr) == 0 && message_attr.isString()) {
std::cout << message_attr.asString();
}
std::cout << ")" << std::endl << std::flush;
}
void Interactive::sightArrived(const Operation & op)
{
if (accountId.empty()) {
return;
}
if (accountId != op->getTo() && agentId != op->getTo()) {
// This is an IG op we are monitoring
return;
}
reply_flag = true;
std::cout << "Sight(" << std::endl;
const MapType & ent = op->getArgs().front()->asMessage();
MapType::const_iterator Iend = ent.end();
for (MapType::const_iterator I = ent.begin(); I != Iend; ++I) {
const Element & item = I->second;
std::cout << " " << I->first << ":";
output(item, 1);
std::cout << std::endl;
}
std::cout << ")" << std::endl << std::flush;
}
void Interactive::soundArrived(const Operation & op)
{
if (accountId.empty()) {
return;
}
if (accountId != op->getTo()) {
// This is an IG op we are monitoring
return;
}
reply_flag = true;
const MapType & arg = op->getArgs().front()->asMessage();
MapType::const_iterator I = arg.find("from");
if (I == arg.end() || !I->second.isString()) {
std::cout << "Sound arg has no from" << std::endl << std::flush;
return;
}
const std::string & from = I->second.asString();
I = arg.find("args");
if (I == arg.end() || !I->second.isList()
|| I->second.asList().empty()
|| !I->second.asList().front().isMap()) {
std::cout << "Sound arg has no args" << std::endl << std::flush;
return;
}
const MapType & ent = I->second.asList().front().asMap();
I = ent.find("say");
if (I == ent.end() || !I->second.isString()) {
std::cout << "Sound arg arg has no say" << std::endl << std::flush;
return;
}
const std::string & say = I->second.asString();
std::cout << "[" << from << "] " << say
<< std::endl << std::flush;
}
sigc::signal<void, char *> CmdLine;
void Interactive::gotCommand(char * cmd)
{
CmdLine.emit(cmd);
}
void Interactive::runCommand(char * cmd)
{
if (cmd == NULL) {
exit = true;
std::cout << std::endl << std::flush;
return;
}
if (*cmd == 0) {
free(cmd);
return;
}
add_history(cmd);
char * arg = strchr(cmd, ' ');
if (arg != NULL) {
*arg++ = 0;
int len = strlen(arg);
while (len > 0 && arg[--len] == ' ') { arg[len] = 0; }
} else {
arg = (char *)"";
}
exec(cmd, arg);
}
int Interactive::runTask(AdminTask * task, const std::string & arg)
{
assert(task != 0);
if (currentTask != 0) {
std::cout << "Busy" << std::endl << std::flush;
return -1;
}
currentTask = task;
OpVector res;
currentTask->setup(arg, res);
OpVector::const_iterator Iend = res.end();
for (OpVector::const_iterator I = res.begin(); I != Iend; ++I) {
encoder->streamObjectsMessage(*I);
}
return 0;
}
int Interactive::endTask()
{
if (currentTask == 0) {
return -1;
}
delete currentTask;
currentTask = 0;
return 0;
}
int completion_iterator = 0;
char * completion_generator(const char * text, int state)
{
if (state == 0) {
completion_iterator = 0;
}
for (int i = completion_iterator; commands[i].cmd_string != 0; ++i) {
if (strncmp(text, commands[i].cmd_string, strlen(text)) == 0) {
completion_iterator = i + 1;
return strdup(commands[i].cmd_string);
}
}
return 0;
}
void Interactive::loop()
{
rl_callback_handler_install(prompt.c_str(),
&Interactive::gotCommand);
rl_completion_entry_function = &completion_generator;
CmdLine.connect(sigc::mem_fun(this, &Interactive::runCommand));
while (!exit) {
poll();
};
std::cout << std::endl << std::flush;
rl_callback_handler_remove();
}
void Interactive::poll(bool rewrite_prompt)
// poll the codec if select says there is something there.
{
fd_set infds;
struct timeval tv;
int retval;
FD_ZERO(&infds);
FD_SET(cli_fd, &infds);
FD_SET(STDIN_FILENO, &infds);
tv.tv_sec = 0;
tv.tv_usec = 500000;
if (rewrite_prompt) {
retval = select(cli_fd+1, &infds, NULL, NULL, NULL);
} else {
retval = select(cli_fd+1, &infds, NULL, NULL, &tv);
}
if (retval > 0) {
if (FD_ISSET(cli_fd, &infds)) {
if (ios->peek() == -1) {
std::cout << "Server disconnected" << std::endl << std::flush;
exit = true;
} else {
if (rewrite_prompt) {
std::cout << std::endl;
}
codec->poll();
if (rewrite_prompt) {
rl_forced_update_display();
}
}
}
if (FD_ISSET(STDIN_FILENO, &infds)) {
rl_callback_read_char();
}
}
}
void Interactive::getLogin()
{
// This needs to be re-written to hide input, so the password can be
// secret
std::cout << "Username: " << std::flush;
std::cin >> username;
std::cout << "Password: " << std::flush;
std::cin >> password;
}
int Interactive::connect_tcp(const std::string & host)
{
std::cout << "Connecting... " << std::flush;
ios = new tcp_socket_stream(host, client_port_num);
if (!ios->is_open()) {
std::cout << "failed." << std::endl << std::flush;
return -1;
}
std::cout << "done." << std::endl << std::flush;
cli_fd = ios->getSocket();
return negotiate();
}
int Interactive::connect_unix(const std::string & filename)
{
std::cout << "Connecting... " << std::flush;
ios = new unix_socket_stream(filename);
if (!ios->is_open()) {
std::cout << "failed." << std::endl << std::flush;
return -1;
}
std::cout << "done." << std::endl << std::flush;
cli_fd = ios->getSocket();
return negotiate();
}
int Interactive::negotiate()
{
// Do client negotiation with the server
Atlas::Net::StreamConnect conn("cycmd", *ios);
std::cout << "Negotiating... " << std::flush;
while (conn.getState() == Atlas::Negotiate::IN_PROGRESS) {
// conn.poll() does all the negotiation
conn.poll();
}
std::cout << "done." << std::endl << std::flush;
// Check whether negotiation was successful
if (conn.getState() == Atlas::Negotiate::FAILED) {
std::cerr << "Failed to negotiate." << std::endl;
return -1;
}
// Negotiation was successful
// Get the codec that negotiation established
codec = conn.getCodec(*this);
// Create the encoder
encoder = new Atlas::Objects::ObjectsEncoder(*codec);
// Send whatever codec specific data marks the beginning of a stream
codec->streamBegin();
return 0;
}
void Interactive::updatePrompt()
{
std::string designation(">");
if (!username.empty()) {
prompt = username + "@";
if (accountType == "admin") {
designation = "#";
} else {
designation = "$";
}
} else {
prompt = "";
}
prompt += serverName;
prompt += " ";
prompt += systemType;
prompt += designation;
prompt += " ";
rl_set_prompt(prompt.c_str());
}
int Interactive::login()
{
Atlas::Objects::Entity::Account account;
Login l;
error_flag = false;
reply_flag = false;
login_flag = true;
account->setAttr("username", username);
account->setAttr("password", password);
l->setArgs1(account);
encoder->streamObjectsMessage(l);
* tools/cycmd.cpp: Ensure that login op is flushed after it is sent. * server/Player.cpp: Arg order of std::string.compare() is incompatable between recent libstdc++ versions. Switch back to old version, still in most common use. * rulesets/Thing.cpp: Set refno on ops handled in game. * rulesets/Python_API.cpp: Modify Entity() python constructor so that commonly used attributes from old atlas are translated to their modern equivalents. * rulesets/Py_Thing.cpp, rulesets/Py_Mind.cpp: Differentiate between previously identical error messages in several places. * rulesets/Py_Object.cpp: Rework conversion of python dict to Atlas map to be more efficient and clean. * rulesets/Py_Location.cpp: Rework setting of vector parts of location so that it can accept vectors from python in more formats, including lists and tuples. * rulesets/Creator.h, rulesets/Character.h, common/BaseEntity.h: Re-order virtual methods declarations to fit a convention. * common/stringstream.h: Hardcode use of local stringstream class, as the version provided with older libstdc++ seems to be broken. * common/database.cpp: Use the common header to pick the right stringstream implementation. * common/BaseWorld.cpp, server/Persistance.cpp: Removed unused stringstream include. * rulesets/Creator.cpp: Added extra debug output. * client/define_world.h, client/define_world.cpp, client/CommClient.h: Use CreatorClient to store Creators mind, instead of BaseMind. * client/client.cpp, client/ObserverClient.h, client/ObserverClient.cpp, client/CreatorClient.h, client/CommClient.h, client/CommClient.cpp: Modify method names to fit capitalisation conventions. * client/CreatorClient.cpp: Implement creation of in-game entities, using creator entity. * client/CommClient.cpp: Added correct client side monitoring of creator entity. * client/ClientConnection.h, client/ClientConnection.cpp: Added pending method to establish if ops are in the queue. Switched send() method so we only send ops. Add setting of serialno of sent ops, starting with an offset of 512. * client/CharacterClient.h: Removed unused member, opFound. * client/CharacterClient.cpp: Debugged sendAndWait() method. Al Riddoch <alriddoch@zepler.org>
2001-08-16 17:39:42 +00:00
(*ios) << std::flush;
while (!reply_flag) {
codec->poll();
}
login_flag = false;
if (!error_flag) {
updatePrompt();
return 0;
}
return -1;
}
int Interactive::setup()
{
Get get;
encoder->streamObjectsMessage(get);
(*ios) << std::flush;
server_flag = true;
reply_flag = true;
while (server_flag && !error_flag) {
codec->poll();
}
server_flag = false;
if (!error_flag) {
return 0;
}
return -1;
}
void Interactive::exec(const std::string & cmd, const std::string & arg)
{
bool reply_expected = true;
reply_flag = false;
error_flag = false;
if (cmd == "stat") {
Get g;
encoder->streamObjectsMessage(g);
} else if (cmd == "install") {
size_t space = arg.find(' ');
if (space == std::string::npos || space >= (arg.size() - 1)) {
std::cout << "usage: install <type id> <parent id>"
<< std::endl << std::flush;
} else {
Create c;
c->setFrom(accountId);
Anonymous ent;
ent->setId(std::string(arg, 0, space));
ent->setObjtype("class");
ent->setParents(std::list<std::string>(1, std::string(arg, space + 1)));
c->setArgs1(ent);
encoder->streamObjectsMessage(c);
}
reply_expected = false;
} else if (cmd == "look") {
Look l;
l->setFrom(accountId);
encoder->streamObjectsMessage(l);
} else if (cmd == "logout") {
Logout l;
l->setFrom(accountId);
if (!arg.empty()) {
Anonymous lmap;
lmap->setId(arg);
l->setArgs1(lmap);
reply_expected = false;
}
encoder->streamObjectsMessage(l);
} else if (cmd == "say") {
Talk t;
Anonymous ent;
ent->setAttr("say", arg);
t->setArgs1(ent);
t->setFrom(accountId);
encoder->streamObjectsMessage(t);
} else if (cmd == "help" || cmd == "?") {
reply_expected = false;
help();
} else if (cmd == "query") {
Get g;
Anonymous cmap;
cmap->setObjtype("obj");
if (!arg.empty()) {
cmap->setId(arg);
}
g->setArgs1(cmap);
g->setFrom(accountId);
encoder->streamObjectsMessage(g);
} else if (cmd == "reload") {
if (arg.empty()) {
reply_expected = false;
std::cout << "reload: Argument required" << std::endl << std::flush;
} else {
Set s;
Anonymous tmap;
tmap->setObjtype("class");
tmap->setId(arg);
s->setArgs1(tmap);
s->setFrom(accountId);
encoder->streamObjectsMessage(s);
}
} else if (cmd == "get") {
Get g;
Anonymous cmap;
cmap->setObjtype("class");
if (!arg.empty()) {
cmap->setId(arg);
}
g->setArgs1(cmap);
g->setFrom(accountId);
encoder->streamObjectsMessage(g);
} else if (cmd == "monitor") {
AdminTask * task = new OperationMonitor;
if (runTask(task, arg) == 0) {
Monitor m;
m->setArgs1(Anonymous());
m->setFrom(accountId);
encoder->streamObjectsMessage(m);
}
reply_expected = false;
} else if (cmd == "unmonitor") {
OperationMonitor * om = dynamic_cast<OperationMonitor *>(currentTask);
if (om != 0) {
Monitor m;
m->setFrom(accountId);
encoder->streamObjectsMessage(m);
reply_expected = false;
struct timeval tv;
gettimeofday(&tv, NULL);
int monitor_time = tv.tv_sec - om->startTime();
std::cout << om->count() << " operations monitored in "
<< monitor_time << " seconds = "
<< om->count() / monitor_time
<< " operations per second"
<< std::endl << std::flush;
endTask();
}
} else if (cmd == "connect") {
reply_expected = false;
Connect m;
Anonymous cmap;
cmap->setAttr("hostname", arg);
m->setArgs1(cmap);
m->setFrom(accountId);
encoder->streamObjectsMessage(m);
} else if (cmd == "add_agent") {
std::string agent_type("creator");
if (!arg.empty()) {
agent_type = arg;
}
Create c;
Anonymous cmap;
cmap->setParents(std::list<std::string>(1, agent_type));
cmap->setName("cycmd agent");
cmap->setObjtype("obj");
c->setArgs1(cmap);
c->setFrom(accountId);
avatar_flag = true;
encoder->streamObjectsMessage(c);
} else if (cmd == "delete") {
if (agentId.empty()) {
std::cout << "Use add_agent to add an in-game agent first" << std::endl << std::flush;
reply_expected = false;
} else if (arg.empty()) {
std::cout << "Please specify the entity to delete" << std::endl << std::flush;
reply_expected = false;
} else {
Delete del;
Anonymous del_arg;
del_arg->setId(arg);
del->setArgs1(del_arg);
del->setFrom(agentId);
del->setTo(arg);
encoder->streamObjectsMessage(del);
reply_expected = false;
}
} else if (cmd == "find_by_name") {
if (agentId.empty()) {
std::cout << "Use add_agent to add an in-game agent first" << std::endl << std::flush;
reply_expected = false;
} else if (arg.empty()) {
std::cout << "Please specify the name to search for" << std::endl << std::flush;
reply_expected = false;
} else {
Look l;
Anonymous lmap;
lmap->setName(arg);
l->setArgs1(lmap);
l->setFrom(agentId);
encoder->streamObjectsMessage(l);
reply_expected = false;
}
} else if (cmd == "find_by_type") {
if (agentId.empty()) {
std::cout << "Use add_agent to add an in-game agent first" << std::endl << std::flush;
reply_expected = false;
} else if (arg.empty()) {
std::cout << "Please specify the type to search for" << std::endl << std::flush;
reply_expected = false;
} else {
Look l;
Anonymous lmap;
lmap->setParents(std::list<std::string>(1, arg));
l->setArgs1(lmap);
l->setFrom(agentId);
encoder->streamObjectsMessage(l);
reply_expected = false;
}
} else if (cmd == "flush") {
if (agentId.empty()) {
std::cout << "Use add_agent to add an in-game agent first" << std::endl << std::flush;
reply_expected = false;
} else if (arg.empty()) {
std::cout << "Please specify the type to flush" << std::endl << std::flush;
reply_expected = false;
} else {
AdminTask * task = new Flusher(agentId);
runTask(task, arg);
reply_expected = false;
}
} else if (cmd == "creator_create") {
if (agentId.empty()) {
std::cout << "Use add_agent to add an in-game agent first" << std::endl << std::flush;
reply_expected = false;
} else if (arg.empty()) {
std::cout << "Use add_agent to add an in-game agent first" << std::endl << std::flush;
reply_expected = false;
} else {
Create c;
Anonymous thing;
thing->setParents(std::list<std::string>(1, arg));
c->setArgs1(thing);
c->setFrom(agentId);
encoder->streamObjectsMessage(c);
reply_expected = false;
}
} else if (cmd == "cancel") {
if (endTask() != 0) {
std::cout << "No task currently running" << std::endl << std::flush;
}
} else {
reply_expected = false;
std::cout << cmd << ": Command not known" << std::endl << std::flush;
}
(*ios) << std::flush;
if (!reply_expected) { return; }
// Wait for reply
time_t wait_start_time = time(NULL);
while (!reply_flag) {
if (time(NULL) - wait_start_time > 5) {
std::cout << cmd << ": No reply from server" << std::endl << std::flush;
return;
}
poll(false);
}
}
2001-06-04 11:22:27 +00:00
static void usage(char * prg)
{
std::cerr << "usage: " << prg << " [ cmd [ server ] ]" << std::endl << std::flush;
}
int main(int argc, char ** argv)
{
int config_status = loadConfig(argc, argv, USAGE_CYCMD);
if (config_status < 0) {
if (config_status == CONFIG_VERSION) {
reportVersion(argv[0]);
return 0;
} else if (config_status == CONFIG_HELP) {
showUsage(argv[0], USAGE_CYCMD, "[ cmd [ server ] ]");
return 0;
} else if (config_status != CONFIG_ERROR) {
log(ERROR, "Unknown error reading configuration.");
}
// Fatal error loading config file
return 1;
}
int optind = config_status;
std::string server;
readConfigItem("client", "serverhost", server);
int useslave = 0;
readConfigItem("client", "useslave", useslave);
bool interactive = true;
std::string cmd;
if (optind < argc) {
if ((argc - optind) == 2) {
server = argv[optind + 1];
} else if ((argc - optind) > 2) {
usage(argv[0]);
return 1;
}
cmd = argv[optind];
interactive = false;
}
Interactive bridge;
if (server.empty()) {
std::string localSocket;
if (useslave != 0) {
localSocket = slave_socket_name;
} else {
localSocket = client_socket_name;
}
std::cout << "Attempting local connection" << std::endl << std::flush;
if (bridge.connect_unix(localSocket) == 0) {
bridge.setUsername("admin");
bridge.setup();
std::cout << "Logging in... " << std::flush;
if (bridge.login() != 0) {
std::cout << "failed." << std::endl << std::flush;
bridge.getLogin();
std::cout << "Logging in... " << std::flush;
if (!bridge.login()) {
std::cout << "failed." << std::endl << std::flush;
return 1;
}
}
std::cout << "done." << std::endl << std::flush;
if (!interactive) {
bridge.exec(cmd, "");
return 0;
* aiclient/ClientConnection.cpp, aiclient/client.cpp, client/ClientConnection.cpp, common/database.h, common/globals.cpp, common/persistance.cpp, common/stringstream.h, server/CommClient.cpp, server/CommServer.cpp, server/Persistance.cpp, tools/cyctrl.cpp, tools/cyctrl.cpp, tools/cydbload.cpp, tools/cyisoload.cpp, tools/cypasswd.cpp: Removed unused config.h. * client/ObserverClient.cpp, common/const.h, tools/cycmd.cpp: Use default password if the admin account cannot be fetched from the database. * client/Py_CreatorClient.cpp, common/BaseEntity.cpp, common/BaseEntity.h, rulesets/Character.cpp, rulesets/Creator.cpp, rulesets/Entity.cpp, rulesets/Entity.h, rulesets/EntityFactory.cpp, rulesets/MemMap.cpp, rulesets/Py_Mind.cpp, rulesets/Py_Thing.cpp, rulesets/Py_World.cpp, rulesets/Thing.cpp, server/Account.cpp, server/Admin.cpp, server/Connection.cpp, tools/cywatchdog.cpp: Make many of the member variables of Entity protected, and add the required accessors. Changed the name of the id attribute to m_id. * common/BaseWorld.h, common/database.cpp, common/persistance.cpp: Removed unused includes. * common/Chop.h, common/Cut.h, common/Eat.h, common/Fire.h, common/Generic.h, common/Load.h, common/Nourish.h, common/Save.h, common/Setup.h, common/Tick.h: Moved definition of virtual functions into cpp file, to reduce wasted code. * common/Makefile.am: Create cyphesis library, which can be used by other applications to access cyphesis databases. * common/config.h, common/database.h, server/Persistance.cpp, tools/cydbload.cpp, tools/cyisoload.cpp, tools/cypasswd.cpp: Remove conditional compilation of db code. db3 is now required. * server/WorldRouter.h: Fixed getNewId() so it take const string. * server/server.cpp: Removed python shutdown, so it does not mess up the db if it causes a segfault. Al Riddoch <alriddoch@zepler.org>
2001-10-17 14:09:42 +00:00
} else {
bridge.loop();
* aiclient/ClientConnection.cpp, aiclient/client.cpp, client/ClientConnection.cpp, common/database.h, common/globals.cpp, common/persistance.cpp, common/stringstream.h, server/CommClient.cpp, server/CommServer.cpp, server/Persistance.cpp, tools/cyctrl.cpp, tools/cyctrl.cpp, tools/cydbload.cpp, tools/cyisoload.cpp, tools/cypasswd.cpp: Removed unused config.h. * client/ObserverClient.cpp, common/const.h, tools/cycmd.cpp: Use default password if the admin account cannot be fetched from the database. * client/Py_CreatorClient.cpp, common/BaseEntity.cpp, common/BaseEntity.h, rulesets/Character.cpp, rulesets/Creator.cpp, rulesets/Entity.cpp, rulesets/Entity.h, rulesets/EntityFactory.cpp, rulesets/MemMap.cpp, rulesets/Py_Mind.cpp, rulesets/Py_Thing.cpp, rulesets/Py_World.cpp, rulesets/Thing.cpp, server/Account.cpp, server/Admin.cpp, server/Connection.cpp, tools/cywatchdog.cpp: Make many of the member variables of Entity protected, and add the required accessors. Changed the name of the id attribute to m_id. * common/BaseWorld.h, common/database.cpp, common/persistance.cpp: Removed unused includes. * common/Chop.h, common/Cut.h, common/Eat.h, common/Fire.h, common/Generic.h, common/Load.h, common/Nourish.h, common/Save.h, common/Setup.h, common/Tick.h: Moved definition of virtual functions into cpp file, to reduce wasted code. * common/Makefile.am: Create cyphesis library, which can be used by other applications to access cyphesis databases. * common/config.h, common/database.h, server/Persistance.cpp, tools/cydbload.cpp, tools/cyisoload.cpp, tools/cypasswd.cpp: Remove conditional compilation of db code. db3 is now required. * server/WorldRouter.h: Fixed getNewId() so it take const string. * server/server.cpp: Removed python shutdown, so it does not mess up the db if it causes a segfault. Al Riddoch <alriddoch@zepler.org>
2001-10-17 14:09:42 +00:00
}
return 0;
}
server = "localhost";
}
std::cerr << "Attempting tcp connection" << std::endl << std::flush;
if (bridge.connect_tcp(server) != 0) {
return 1;
}
bridge.setup();
if (!interactive) {
std::cerr << "WARNING: No login details available for remote host"
<< std::endl
<< "WARNING: Attempting command without logging in"
<< std::endl << std::flush;
} else {
bridge.getLogin();
std::cout << "Logging in... " << std::flush;
if (bridge.login() != 0) {
std::cout << "failed." << std::endl << std::flush;
return 1;
}
std::cout << "done." << std::endl << std::flush;
}
if (!interactive) {
bridge.exec(cmd, "");
} else {
bridge.loop();
}
delete global_conf;
return 0;
}