mirror of
https://github.com/worldforge/cyphesis
synced 2026-08-13 12:26:04 -04:00
* tools/cycmd.cpp, client/CommClient.h, client/CommClient.cpp: Fixed up client code so it does not rely on username being the same as account id. * tools/cycmd.cpp: Added look and logout commands to administrate users logged in. * server/server.cpp: Fixed metaserver code so it only sends termination packet if metaserver functionality is enabled. * server/Connection.h, server/Connection.cpp, server/CommServer.cpp, server/CommClient.h, server/Account.cpp: Fix logouts so they do cause the client connection to be closed. * Finished switch from Fire operation to Burn.
551 lines
16 KiB
C++
551 lines
16 KiB
C++
// This file may be redistributed and modified only under the terms of
|
|
// the GNU General Public License (See COPYING for details).
|
|
// Copyright (C) 2000,2001 Alistair Riddoch
|
|
|
|
#include "BaseMind.h"
|
|
|
|
#include "MemMap_methods.h"
|
|
|
|
#include <common/utility.h>
|
|
#include <common/debug.h>
|
|
#include <common/op_switch.h>
|
|
#include <common/inheritance.h>
|
|
|
|
#include <common/Chop.h>
|
|
#include <common/Cut.h>
|
|
#include <common/Eat.h>
|
|
#include <common/Burn.h>
|
|
#include <common/Load.h>
|
|
#include <common/Save.h>
|
|
|
|
#include <Atlas/Objects/Operation/Login.h>
|
|
#include <Atlas/Objects/Operation/Sight.h>
|
|
#include <Atlas/Objects/Operation/Sound.h>
|
|
#include <Atlas/Objects/Operation/Combine.h>
|
|
#include <Atlas/Objects/Operation/Create.h>
|
|
#include <Atlas/Objects/Operation/Delete.h>
|
|
#include <Atlas/Objects/Operation/Divide.h>
|
|
#include <Atlas/Objects/Operation/Imaginary.h>
|
|
#include <Atlas/Objects/Operation/Move.h>
|
|
#include <Atlas/Objects/Operation/Set.h>
|
|
#include <Atlas/Objects/Operation/Talk.h>
|
|
#include <Atlas/Objects/Operation/Touch.h>
|
|
#include <Atlas/Objects/Operation/Appearance.h>
|
|
#include <Atlas/Objects/Operation/Disappearance.h>
|
|
|
|
//static const bool debug_flag = false;
|
|
|
|
using Atlas::Message::Object;
|
|
using Atlas::Objects::Root;
|
|
|
|
BaseMind::BaseMind(const std::string & id, const std::string & body_name)
|
|
: map(script), isAwake(true)
|
|
{
|
|
setId(id);
|
|
name = body_name;
|
|
map.addObject(this);
|
|
//BaseMind::time=WorldTime();
|
|
|
|
subscribe("sight", OP_SIGHT);
|
|
subscribe("sound", OP_SOUND);
|
|
subscribe("save", OP_SAVE);
|
|
subscribe("load", OP_LOAD);
|
|
subscribe("tick", OP_TICK);
|
|
subscribe("setup", OP_SETUP);
|
|
subscribe("appearance", OP_APPEARANCE);
|
|
subscribe("disappearance", OP_DISAPPEARANCE);
|
|
|
|
sightSubscribe("create", OP_CREATE);
|
|
sightSubscribe("delete", OP_DELETE);
|
|
sightSubscribe("set", OP_SET);
|
|
sightSubscribe("move", OP_MOVE);
|
|
|
|
soundSubscribe("talk", OP_TALK);
|
|
}
|
|
|
|
BaseMind::~BaseMind()
|
|
{
|
|
map.things.erase(getId());
|
|
map.flushMap();
|
|
}
|
|
|
|
void BaseMind::scriptSubscribe(const std::string & op)
|
|
{
|
|
std::string::size_type l = op.find("_");
|
|
if (l == std::string::npos) {
|
|
OpNo n = Inheritance::instance().opEnumerate(op);
|
|
if (n != OP_INVALID) {
|
|
debug(std::cout << "MINDSCRIPT requesting subscription to " << op
|
|
<< std::endl << std::flush;);
|
|
subscribe(op, n);
|
|
} else {
|
|
debug(std::cout << "MINDSCRIPT requesting subscription to " << op
|
|
<< " but inheritance could not give me a reference"
|
|
<< std::endl << std::flush;);
|
|
}
|
|
return;
|
|
}
|
|
// This only works cos sight and sound are the same length
|
|
std::string subop = op.substr(6, std::string::npos);
|
|
OpNo subno = Inheritance::instance().opEnumerate(subop);
|
|
if (subno == OP_INVALID) {
|
|
debug(std::cerr << "Mind script requested subscription to " << op
|
|
<< " operations, of which the argument is " << subop
|
|
<< " but I can't work out what it wants."
|
|
<< std::endl << std::flush;);
|
|
return;
|
|
}
|
|
#if defined(__GNUC__) && __GNUC__ < 3
|
|
if (!op.substr(0,6).compare("sight_")) {
|
|
#else
|
|
if (!op.compare(0,6,"sight_")) {
|
|
#endif
|
|
debug(std::cout << "MINDSCRIPT requesting subscription to sight of "
|
|
<< subop << " ops" << std::endl << std::flush;);
|
|
sightSubscribe(subop, subno);
|
|
#if defined(__GNUC__) && __GNUC__ < 3
|
|
} else if (!op.substr(0,6).compare("sound_")) {
|
|
#else
|
|
} else if (!op.compare(0,6,"sound_")) {
|
|
#endif
|
|
debug(std::cout << "MINDSCRIPT requesting subscription to sound of "
|
|
<< subop << " ops" << std::endl << std::flush;);
|
|
soundSubscribe(subop, subno);
|
|
} else {
|
|
debug(std::cerr << "Mind script requested subscription to " << op
|
|
<< " operations, of which the argument is " << subop
|
|
<< " but op arguments for that kind of op are not yet"
|
|
<< " supported by the mind scriptig interface"
|
|
<< std::endl << std::flush;);
|
|
}
|
|
}
|
|
|
|
OpVector BaseMind::sightLoginOperation(const Sight & op, Login & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sight_login", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightCombineOperation(const Sight & op, Combine & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sight_combine", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightDivideOperation(const Sight & op, Divide & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sight_divide", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightTalkOperation(const Sight & op, Talk & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sight_talk", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightActionOperation(const Sight & op, Action & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sight_action", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightChopOperation(const Sight & op, Chop & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sight_chop", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightCreateOperation(const Sight & op, Create & sub_op)
|
|
{
|
|
OpVector res;
|
|
if (script->Operation("sight_create", op, res, &sub_op) != 0) {
|
|
return res;
|
|
}
|
|
const Object::ListType & args = sub_op.GetArgs();
|
|
if (args.empty() || !args.front().IsMap()) {
|
|
debug( std::cout << " no args!" << std::endl << std::flush;);
|
|
return res;
|
|
}
|
|
const Object::MapType & obj = args.front().AsMap();
|
|
map.add(obj);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightCutOperation(const Sight & op, Cut & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sight_cut", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightDeleteOperation(const Sight & op, Delete & sub_op)
|
|
{
|
|
debug( std::cout << "Sight Delete operation" << std::endl << std::flush;);
|
|
OpVector res;
|
|
if (script->Operation("sight_delete", op, res, &sub_op) != 0) {
|
|
return res;
|
|
}
|
|
const Object::ListType & args = sub_op.GetArgs();
|
|
if (args.empty() || !args.front().IsMap()) {
|
|
debug( std::cout << " no args!" << std::endl << std::flush;);
|
|
return res;
|
|
}
|
|
const Object::MapType & obj = args.front().AsMap();
|
|
Object::MapType::const_iterator I = obj.find("id");
|
|
if ((I != obj.end()) && (I->second.IsString())) {
|
|
map.del(I->second.AsString());
|
|
} else {
|
|
debug(std::cout << "args has no string id" << std::endl << std::flush;);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightEatOperation(const Sight & op, Eat & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sight_eat", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightBurnOperation(const Sight & op, Burn & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sight_burn", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightImaginaryOperation(const Sight & op, Imaginary & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sight_imaginary", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightMoveOperation(const Sight & op, Move & sub_op)
|
|
{
|
|
debug( std::cout << "BaseMind::sightOperation(Sight, Move)" << std::endl << std::flush;);
|
|
OpVector res;
|
|
if (script->Operation("sight_move", op, res, &sub_op) != 0) {
|
|
return res;
|
|
}
|
|
const Object::ListType & args = sub_op.GetArgs();
|
|
if (args.empty() || !args.front().IsMap()) {
|
|
debug( std::cout << " no args!" << std::endl << std::flush;);
|
|
return res;
|
|
}
|
|
const Object::MapType & obj = args.front().AsMap();
|
|
map.update(obj);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightSetOperation(const Sight & op, Set & sub_op)
|
|
{
|
|
OpVector res;
|
|
if (script->Operation("sight_set", op, res, &sub_op) != 0) {
|
|
return res;
|
|
}
|
|
const Object::ListType & args = sub_op.GetArgs();
|
|
if (args.empty() || !args.front().IsMap()) {
|
|
debug( std::cout << " no args!" << std::endl << std::flush;);
|
|
return res;
|
|
}
|
|
const Object::MapType & obj = args.front().AsMap();
|
|
map.update(obj);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightTouchOperation(const Sight & op, Touch & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sight_touch", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::sightOtherOperation(const Sight & op, RootOperation & sub_op)
|
|
{
|
|
debug( std::cout << "BaseMind::sightOperation(Sight, RootOperation)" << std::endl << std::flush;);
|
|
OpVector res;
|
|
script->Operation("sight_undefined", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundLoginOperation(const Sound & op, Login & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_login", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundActionOperation(const Sound & op, Action & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_action", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundCutOperation(const Sound & op, Cut & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_cut", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundChopOperation(const Sound & op, Chop & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_chop", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundCombineOperation(const Sound & op, Combine & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_combine", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundCreateOperation(const Sound & op, Create & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_create", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundDeleteOperation(const Sound & op, Delete & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_delete", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundDivideOperation(const Sound & op, Divide & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_divide", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundEatOperation(const Sound & op, Eat & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_eat", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundBurnOperation(const Sound & op, Burn & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_burn", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundImaginaryOperation(const Sound & op, Imaginary & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_imaginary", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundMoveOperation(const Sound & op, Move & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_move", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundSetOperation(const Sound & op, Set & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_set", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundTouchOperation(const Sound & op, Touch & sub_op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("sound_touch", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundTalkOperation(const Sound & op, Talk & sub_op)
|
|
{
|
|
debug( std::cout << "BaseMind::soundOperation(Sound, Talk)" << std::endl << std::flush;);
|
|
OpVector res;
|
|
script->Operation("sound_talk", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::soundOtherOperation(const Sound & op, RootOperation & sub_op)
|
|
{
|
|
debug( std::cout << "BaseMind::soundOperation(Sound, RootOperation)" << std::endl << std::flush;);
|
|
OpVector res;
|
|
script->Operation("sound_undefined", op, res, &sub_op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::SoundOperation(const Sound & op)
|
|
{
|
|
// Louder sounds might eventually make character wake up
|
|
if (!isAwake) { return OpVector(); }
|
|
// Deliver argument to sound things
|
|
OpVector res;
|
|
if (script->Operation("sound", op, res) != 0) {
|
|
return res;
|
|
}
|
|
const Object::ListType & args = op.GetArgs();
|
|
if (args.empty() || !args.front().IsMap()) {
|
|
debug( std::cout << " no args!" << std::endl << std::flush;);
|
|
return res;
|
|
}
|
|
const Object::MapType & obj = args.front().AsMap();
|
|
RootOperation op2;
|
|
bool isOp = utility::Object_asOperation(obj, op2);
|
|
if (isOp) {
|
|
debug( std::cout << " args is an op!" << std::endl << std::flush;);
|
|
res = callSoundOperation(op, op2);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::SightOperation(const Sight & op)
|
|
{
|
|
if (!isAwake) { return OpVector(); }
|
|
debug( std::cout << "BaseMind::Operation(Sight)" << std::endl << std::flush;);
|
|
// Deliver argument to sight things
|
|
OpVector res;
|
|
if (script->Operation("sight", op, res) != 0) {
|
|
debug( std::cout << " its in the script" << std::endl << std::flush;);
|
|
return res;
|
|
}
|
|
const Object::ListType & args = op.GetArgs();
|
|
if (args.empty() || !args.front().IsMap()) {
|
|
debug( std::cout << " no args!" << std::endl << std::flush;);
|
|
return res;
|
|
}
|
|
const Object::MapType & obj = args.front().AsMap();
|
|
RootOperation op2;
|
|
bool isOp = utility::Object_asOperation(obj, op2);
|
|
if (isOp) {
|
|
debug( std::cout << " args is an op!" << std::endl << std::flush;);
|
|
res = callSightOperation(op, op2);
|
|
} else /* if (op2->GetObjtype() == "object") */ {
|
|
debug( std::cout << " arg is an entity!" << std::endl << std::flush;);
|
|
map.add(obj);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::AppearanceOperation(const Appearance & op)
|
|
{
|
|
if (!isAwake) { return OpVector(); }
|
|
OpVector res;
|
|
script->Operation("appearance", op, res);
|
|
const Object::ListType & args = op.GetArgs();
|
|
Object::ListType::const_iterator I;
|
|
for(I = args.begin(); I != args.end(); I++) {
|
|
map.getAdd(I->AsMap().find("id")->second.AsString());
|
|
}
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::DisappearanceOperation(const Disappearance & op)
|
|
{
|
|
if (!isAwake) { return OpVector(); }
|
|
OpVector res;
|
|
script->Operation("disappearance", op, res);
|
|
// Not quite sure what to do to the map here, but should do something.
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::SaveOperation(const Save & op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("save", op, res);
|
|
Object::MapType emap;
|
|
debug(std::cout << "Got " << res.size() << " stuff to save from mind"
|
|
<< std::endl << std::flush;);
|
|
OpVector::const_iterator I = res.begin();
|
|
if ((I != res.end()) && !((*I)->GetArgs().empty())) {
|
|
emap = (*I)->GetArgs().front().AsMap();
|
|
}
|
|
for (; I != res.end(); ++I) {
|
|
delete *I;
|
|
}
|
|
Info * i = new Info(Info::Instantiate());
|
|
emap["map"] = map.asObject();
|
|
emap["id"] = getId();
|
|
i->SetArgs(Object::ListType(1,emap));
|
|
return OpVector(1,i);
|
|
}
|
|
|
|
OpVector BaseMind::LoadOperation(const Load & op)
|
|
{
|
|
OpVector res;
|
|
script->Operation("load", op, res);
|
|
if (!op.GetArgs().empty()) {
|
|
const Object::MapType & emap = op.GetArgs().front().AsMap();
|
|
Object::MapType::const_iterator I = emap.find("map");
|
|
if ((I != emap.end()) && I->second.IsMap()) {
|
|
const Object::MapType & memmap = I->second.AsMap();
|
|
Object::MapType::const_iterator J = memmap.begin();
|
|
for(; J != memmap.end(); J++) {
|
|
map.add(J->second.AsMap());
|
|
}
|
|
}
|
|
}
|
|
return OpVector();
|
|
}
|
|
|
|
OpVector BaseMind::operation(const RootOperation & op)
|
|
{
|
|
// This might end up being quite tricky to do
|
|
|
|
// In the python the following happens here:
|
|
// Find out if the op refers to any ids we don't know about.
|
|
// If so create look operations to those ids
|
|
// Set the minds time and date
|
|
OpVector res;
|
|
time.update(op.GetSeconds());
|
|
map.getAdd(op.GetFrom());
|
|
RootOperation * look;
|
|
while ((look = map.lookId()) != NULL) {
|
|
res.push_back(look);
|
|
}
|
|
OpVector res2 = callOperation(op);
|
|
for(OpVector::const_iterator I = res2.begin(); I != res2.end(); I++) {
|
|
res.push_back(*I);
|
|
}
|
|
//res = call_triggers(op);
|
|
return res;
|
|
}
|
|
|
|
OpVector BaseMind::callSightOperation(const Sight& op, RootOperation& sub_op) {
|
|
map.getAdd(sub_op.GetFrom());
|
|
OpNo op_no = opEnumerate(sub_op, opSightLookup);
|
|
if (debug_flag && (op_no == OP_INVALID)) {
|
|
std::cout << getId() << " could not deliver sight of "
|
|
<< sub_op.GetParents().front().AsString()
|
|
<< std::endl << std::flush;
|
|
}
|
|
SUB_OP_SWITCH(op, op_no, sight, sub_op)
|
|
return OpVector();
|
|
}
|
|
|
|
OpVector BaseMind::callSoundOperation(const Sound& op, RootOperation& sub_op) {
|
|
map.getAdd(sub_op.GetFrom());
|
|
OpNo op_no = opEnumerate(sub_op, opSoundLookup);
|
|
if (debug_flag && (op_no == OP_INVALID)) {
|
|
std::cout << getId() << " could not deliver sound of "
|
|
<< sub_op.GetParents().front().AsString()
|
|
<< std::endl << std::flush;
|
|
}
|
|
SUB_OP_SWITCH(op, op_no, sound, sub_op)
|
|
return OpVector();
|
|
}
|