mirror of
https://bitbucket.org/theswgsource/src-1.2.git
synced 2026-09-11 21:44:58 -04:00
463 lines
18 KiB
C++
Executable File
463 lines
18 KiB
C++
Executable File
// ======================================================================
|
|
//
|
|
// ScriptMethodsMount.cpp
|
|
// Copyright 2003, Sony Online Entertainment, Inc.
|
|
// All rights reserved.
|
|
//
|
|
// ======================================================================
|
|
|
|
#include "serverScript/FirstServerScript.h"
|
|
#include "serverScript/JavaLibrary.h"
|
|
|
|
#include "serverGame/ConfigServerGame.h"
|
|
#include "serverGame/ContainerInterface.h"
|
|
#include "serverGame/CreatureObject.h"
|
|
#include "serverGame/GameServer.h"
|
|
#include "serverGame/ServerObjectTemplate.h"
|
|
#include "sharedGame/MountValidScaleRangeTable.h"
|
|
#include "sharedLog/Log.h"
|
|
#include "sharedObject/NetworkIdManager.h"
|
|
#include "sharedObject/ObjectTemplateList.h"
|
|
|
|
using namespace JNIWrappersNamespace;
|
|
|
|
#define LOCAL_LOG_CHANNEL "mount-script-interface"
|
|
|
|
|
|
// ======================================================================
|
|
// ScriptMethodsMountNamespace
|
|
// ======================================================================
|
|
|
|
namespace ScriptMethodsMountNamespace
|
|
{
|
|
bool install();
|
|
|
|
jboolean JNICALL getMountsEnabled(JNIEnv *env, jobject self);
|
|
jboolean JNICALL getMountsMultiSeaterEnabled(JNIEnv *env, jobject self);
|
|
jboolean JNICALL makePetMountable(JNIEnv *env, jobject self, jlong petId);
|
|
void JNICALL updateMountWearableVisuals(JNIEnv *env, jobject self, jlong mountId);
|
|
jboolean JNICALL mountCreature(JNIEnv *env, jobject self, jlong riderId, jlong mountId);
|
|
void JNICALL dismountCreature(JNIEnv *env, jobject self, jlong riderId);
|
|
jlong JNICALL getMountId(JNIEnv *env, jobject self, jlong riderId);
|
|
jlong JNICALL getRiderId(JNIEnv *env, jobject self, jlong mountId);
|
|
jint JNICALL couldPetBeMadeMountable(JNIEnv *env, jobject self, jlong petId);
|
|
jint JNICALL couldObjectTemplateBeMadeMountable(JNIEnv *env, jobject self, jstring serverObjectTemplateName, jfloat objectScale);
|
|
void JNICALL makeContainerStateInconsistentTestOnly(JNIEnv *env, jobject self, jlong containedObjectId);
|
|
jboolean JNICALL doesMountHaveRoom(JNIEnv * env, jobject self, jlong mountId);
|
|
}
|
|
|
|
|
|
//========================================================================
|
|
// install
|
|
//========================================================================
|
|
|
|
bool ScriptMethodsMountNamespace::install()
|
|
{
|
|
const JNINativeMethod NATIVES[] = {
|
|
#define JF(a,b,c) {a,b,(void*)(ScriptMethodsMountNamespace::c)}
|
|
JF("getMountsEnabled", "()Z", getMountsEnabled),
|
|
JF("getMountsMultiSeaterEnabled", "()Z", getMountsMultiSeaterEnabled),
|
|
JF("_makePetMountable", "(J)Z", makePetMountable),
|
|
JF("_updateMountWearableVisuals", "(J)V", updateMountWearableVisuals),
|
|
JF("_mountCreature", "(JJ)Z", mountCreature),
|
|
JF("_dismountCreature", "(J)V", dismountCreature),
|
|
JF("_getMountId", "(J)J", getMountId),
|
|
JF("_getRiderId", "(J)J", getRiderId),
|
|
JF("_couldPetBeMadeMountable", "(J)I", couldPetBeMadeMountable),
|
|
JF("couldObjectTemplateBeMadeMountable", "(Ljava/lang/String;F)I", couldObjectTemplateBeMadeMountable),
|
|
JF("_makeContainerStateInconsistentTestOnly", "(J)V", makeContainerStateInconsistentTestOnly),
|
|
JF("_doesMountHaveRoom", "(J)Z", doesMountHaveRoom),
|
|
};
|
|
|
|
return JavaLibrary::registerNatives(NATIVES, sizeof(NATIVES)/sizeof(NATIVES[0]));
|
|
}
|
|
|
|
|
|
// ======================================================================
|
|
|
|
jboolean JNICALL ScriptMethodsMountNamespace::getMountsEnabled(JNIEnv *env, jobject self)
|
|
{
|
|
UNREF(env);
|
|
UNREF(self);
|
|
return static_cast<jboolean>(ConfigServerGame::getMountsEnabled() ? JNI_TRUE : JNI_FALSE);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
jboolean JNICALL ScriptMethodsMountNamespace::getMountsMultiSeaterEnabled(JNIEnv * /*env*/, jobject /*self*/)
|
|
{
|
|
LOG(LOCAL_LOG_CHANNEL, ("JavaLibrary::getMountsMultiSeaterEnabled(): is a deprecated call."));
|
|
|
|
return JNI_TRUE;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
jboolean JNICALL ScriptMethodsMountNamespace::makePetMountable(JNIEnv *env, jobject self, jlong petId)
|
|
{
|
|
UNREF(self);
|
|
|
|
//-- Ignore calls if mounts are disabled.
|
|
if (!ConfigServerGame::getMountsEnabled())
|
|
{
|
|
LOG(LOCAL_LOG_CHANNEL, ("JavaLibrary::makePetMountable(): ignoring call, [GameServer] mountsEnabled is false."));
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
//-- Get CreatureObject for pet.
|
|
CreatureObject *const petObject = JavaLibrary::getCreatureThrow(env, petId, "makePetMountable(): error in petId arg");
|
|
if (!petObject)
|
|
return JNI_FALSE;
|
|
|
|
//-- Check if creature can be converted to a mount.
|
|
if (petObject->getMountabilityStatus() != static_cast<int>(MountValidScaleRangeTable::MS_creatureMountable))
|
|
{
|
|
char buffer[512];
|
|
IGNORE_RETURN(snprintf(buffer, sizeof(buffer) - 1, "makePetMountable(): creature id=[%s],object template=[%s] cannot be made mountable.", petObject->getNetworkId().getValueString().c_str(), petObject->getObjectTemplateName()));
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
|
JavaLibrary::throwInternalScriptError(buffer);
|
|
LOG(LOCAL_LOG_CHANNEL, (buffer));
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
//-- Check if creature is already mountable.
|
|
if (petObject->isMountable())
|
|
{
|
|
char buffer[512];
|
|
IGNORE_RETURN(snprintf(buffer, sizeof(buffer) - 1, "makePetMountable(): creature id=[%s],object template=[%s] already is mountable.", petObject->getNetworkId().getValueString().c_str(), petObject->getObjectTemplateName()));
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
|
JavaLibrary::throwInternalScriptError(buffer);
|
|
LOG(LOCAL_LOG_CHANNEL, (buffer));
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
//-- Do it.
|
|
petObject->makePetMountable();
|
|
return JNI_TRUE;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void JNICALL ScriptMethodsMountNamespace::updateMountWearableVisuals(JNIEnv *env, jobject self, jlong mountId)
|
|
{
|
|
UNREF(env);
|
|
UNREF(self);
|
|
UNREF(mountId);
|
|
|
|
LOG(LOCAL_LOG_CHANNEL, ("updateMountWearableVisuals called."));
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
jboolean JNICALL ScriptMethodsMountNamespace::mountCreature(JNIEnv *env, jobject self, jlong riderId, jlong mountId)
|
|
{
|
|
UNREF(self);
|
|
|
|
//-- Ignore calls if mounts are disabled.
|
|
if (!ConfigServerGame::getMountsEnabled())
|
|
{
|
|
LOG(LOCAL_LOG_CHANNEL, ("JavaLibrary::mountCreature(): ignoring call, [GameServer] mountsEnabled is false."));
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
//-- Get the rider object.
|
|
CreatureObject *const riderObject = JavaLibrary::getCreatureThrow(env, riderId, "mountCreature(): error in riderId arg");
|
|
if (!riderObject)
|
|
return JNI_FALSE;
|
|
|
|
//-- Get the mount object.
|
|
CreatureObject *const mountObject = JavaLibrary::getCreatureThrow(env, mountId, "mountCreature(): error in mountId arg");
|
|
if (!mountObject)
|
|
return JNI_FALSE;
|
|
|
|
//-- Ensure that the rider is not already riding a mount.
|
|
if (riderObject->getState(States::RidingMount))
|
|
{
|
|
char buffer[512];
|
|
|
|
IGNORE_RETURN(snprintf(buffer, sizeof(buffer) - 1, "JavaLibrary::mountCreature(): rider id=[%s] is already riding a mount.", riderObject->getNetworkId().getValueString().c_str()));
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
|
JavaLibrary::throwInternalScriptError(buffer);
|
|
LOG(LOCAL_LOG_CHANNEL, (buffer));
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
//-- Check if mount is mountable.
|
|
if (!mountObject->isMountable())
|
|
{
|
|
char buffer[512];
|
|
IGNORE_RETURN(snprintf(buffer, sizeof(buffer) - 1, "mountCreature(): creature id=[%s],object template=[%s] is not a mount.", mountObject->getNetworkId().getValueString().c_str(), mountObject->getObjectTemplateName()));
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
|
JavaLibrary::throwInternalScriptError(buffer);
|
|
LOG(LOCAL_LOG_CHANNEL, (buffer));
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
//-- Check if mount has room;
|
|
if (mountObject->isMountableAndHasRoomForAnother())
|
|
{
|
|
//-- Have the rider mount the creature.
|
|
bool const mountResult = riderObject->mountCreature(*mountObject);
|
|
return static_cast<jboolean>(mountResult);
|
|
}
|
|
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void JNICALL ScriptMethodsMountNamespace::dismountCreature(JNIEnv *env, jobject self, jlong riderId)
|
|
{
|
|
UNREF(env);
|
|
UNREF(self);
|
|
UNREF(riderId);
|
|
|
|
//-- Ignore calls if mounts are disabled.
|
|
if (!ConfigServerGame::getMountsEnabled())
|
|
{
|
|
LOG(LOCAL_LOG_CHANNEL, ("JavaLibrary::dismountCreature(): ignoring call, [GameServer] mountsEnabled is false."));
|
|
return;
|
|
}
|
|
|
|
//-- Get the rider.
|
|
CreatureObject *const riderObject = JavaLibrary::getCreatureThrow(env, riderId, "getMountId(): error in riderId arg");
|
|
if (!riderObject)
|
|
return;
|
|
|
|
//-- Ensure the rider is on a mount.
|
|
if (!riderObject->getState(States::RidingMount))
|
|
{
|
|
LOG(LOCAL_LOG_CHANNEL, ("JavaLibrary::dismountCreature(): rider id=[%s] is not riding a mount.", riderObject->getNetworkId().getValueString().c_str()));
|
|
return;
|
|
}
|
|
|
|
//-- Get the mount.
|
|
CreatureObject *const mountObject = riderObject->getMountedCreature();
|
|
if (!mountObject)
|
|
{
|
|
LOG(LOCAL_LOG_CHANNEL, ("JavaLibrary::dismountCreature(): server id=[%d],rider id=[%s] has RidingMount state but CreatureObject::getMountedCreature() returns nullptr, skipping dismount.", GameServer::getInstance().getProcessId(), riderObject->getNetworkId().getValueString().c_str()));
|
|
return;
|
|
}
|
|
|
|
//-- Detach the rider from the mount.
|
|
IGNORE_RETURN(mountObject->detachRider(riderObject->getNetworkId()));
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
jlong JNICALL ScriptMethodsMountNamespace::getMountId(JNIEnv *env, jobject self, jlong riderId)
|
|
{
|
|
UNREF(env);
|
|
UNREF(self);
|
|
|
|
//-- Ignore calls if mounts are disabled.
|
|
if (!ConfigServerGame::getMountsEnabled())
|
|
return 0;
|
|
|
|
//-- Get the rider object.
|
|
bool const throwIfNotOnServer = false;
|
|
CreatureObject const *const riderObject = JavaLibrary::getCreatureThrow(env, riderId, "getMountId(): error in riderId arg", throwIfNotOnServer);
|
|
if (!riderObject)
|
|
return 0;
|
|
|
|
CreatureObject const *const mountedCreature = riderObject->getMountedCreature();
|
|
NetworkId const mountNetworkId = (mountedCreature ? mountedCreature->getNetworkId() : NetworkId::cms_invalid);
|
|
|
|
return mountNetworkId.getValue();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
jlong JNICALL ScriptMethodsMountNamespace::getRiderId(JNIEnv *env, jobject self, jlong mountId)
|
|
{
|
|
UNREF(env);
|
|
UNREF(self);
|
|
|
|
//-- Ignore calls if mounts are disabled.
|
|
if (!ConfigServerGame::getMountsEnabled())
|
|
return 0;
|
|
|
|
//-- Get the rider object.
|
|
bool const throwIfNotOnServer = false;
|
|
CreatureObject const *const mountObject = JavaLibrary::getCreatureThrow(env, mountId, "getRiderId(): error in mountId arg", throwIfNotOnServer);
|
|
if (!mountObject)
|
|
return 0;
|
|
|
|
CreatureObject const *const riderObject = mountObject->getPrimaryMountingRider();
|
|
NetworkId const riderNetworkId = (riderObject ? riderObject->getNetworkId() : NetworkId::cms_invalid);
|
|
|
|
return riderNetworkId.getValue();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
jint JNICALL ScriptMethodsMountNamespace::couldPetBeMadeMountable(JNIEnv *env, jobject self, jlong petId)
|
|
{
|
|
UNREF(env);
|
|
UNREF(self);
|
|
UNREF(petId);
|
|
|
|
//-- Ignore calls if mounts are disabled.
|
|
if (!ConfigServerGame::getMountsEnabled())
|
|
{
|
|
LOG(LOCAL_LOG_CHANNEL, ("JavaLibrary::couldPetBeMadeMountable(): ignoring call, [GameServer] mountsEnabled is false."));
|
|
return static_cast<int>(MountValidScaleRangeTable::MS_speciesUnmountable);
|
|
}
|
|
|
|
//-- Get CreatureObject for pet.
|
|
CreatureObject const *const petObject = JavaLibrary::getCreatureThrow(env, petId, "couldPetBeMadeMountable(): error in petId arg");
|
|
if (!petObject)
|
|
return static_cast<int>(MountValidScaleRangeTable::MS_speciesUnmountable);
|
|
|
|
//-- Check if creature can be converted to a mount.
|
|
return static_cast<jint>(petObject->getMountabilityStatus());
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
jint JNICALL ScriptMethodsMountNamespace::couldObjectTemplateBeMadeMountable(JNIEnv *env, jobject self, jstring objectTemplateName, jfloat objectScale)
|
|
{
|
|
UNREF(env);
|
|
UNREF(self);
|
|
|
|
//-- Ignore calls if mounts are disabled.
|
|
if (!ConfigServerGame::getMountsEnabled())
|
|
{
|
|
LOG(LOCAL_LOG_CHANNEL, ("JavaLibrary::couldObjectTemplateBeMadeMountable(): ignoring call, [GameServer] mountsEnabled is false."));
|
|
return static_cast<int>(MountValidScaleRangeTable::MS_speciesUnmountable);
|
|
}
|
|
|
|
//-- Convert objectTemplateName from jstring to something else.
|
|
JavaStringParam objectTemplateNameParam(objectTemplateName);
|
|
std::string objectTemplateNameNarrow;
|
|
IGNORE_RETURN(JavaLibrary::convert(objectTemplateNameParam, objectTemplateNameNarrow));
|
|
|
|
//-- Get the appearance name.
|
|
//... first grab the server object template name.
|
|
ObjectTemplate const *const objectTemplate = ObjectTemplateList::fetch(objectTemplateNameNarrow);
|
|
if (!objectTemplate)
|
|
{
|
|
LOG(LOCAL_LOG_CHANNEL, ("JavaLibrary::couldObjectTemplateBeMadeMountable(): object template [%s] could not be fetched.", objectTemplateNameNarrow.c_str()));
|
|
return static_cast<int>(MountValidScaleRangeTable::MS_speciesUnmountable);
|
|
}
|
|
|
|
//... grab the shared object template name from it.
|
|
ServerObjectTemplate const *const serverObjectTemplate = dynamic_cast<ServerObjectTemplate const*>(objectTemplate);
|
|
if (!serverObjectTemplate)
|
|
{
|
|
LOG(LOCAL_LOG_CHANNEL, ("JavaLibrary::couldObjectTemplateBeMadeMountable(): object template [%s] is not a ServerObjectTemplate.", objectTemplateNameNarrow.c_str()));
|
|
objectTemplate->releaseReference();
|
|
return static_cast<int>(MountValidScaleRangeTable::MS_speciesUnmountable);
|
|
}
|
|
|
|
std::string const &sharedObjectTemplateName = serverObjectTemplate->getSharedTemplate();
|
|
|
|
//... get the shared object template.
|
|
ObjectTemplate const *const sharedObjectTemplateBase = ObjectTemplateList::fetch(sharedObjectTemplateName);
|
|
|
|
if (!sharedObjectTemplateBase)
|
|
{
|
|
LOG(LOCAL_LOG_CHANNEL, ("JavaLibrary::couldObjectTemplateBeMadeMountable(): could not load shared object template [%s].", sharedObjectTemplateName.c_str()));
|
|
objectTemplate->releaseReference();
|
|
return static_cast<int>(MountValidScaleRangeTable::MS_speciesUnmountable);
|
|
}
|
|
|
|
SharedObjectTemplate const *const sharedObjectTemplate = sharedObjectTemplateBase->asSharedObjectTemplate();
|
|
if (!sharedObjectTemplate)
|
|
{
|
|
LOG(LOCAL_LOG_CHANNEL, ("JavaLibrary::couldObjectTemplateBeMadeMountable(): shared object template [%s] is not derived from class SharedObjectTemplate.", sharedObjectTemplateName.c_str()));
|
|
objectTemplate->releaseReference();
|
|
sharedObjectTemplateBase->releaseReference();
|
|
return static_cast<int>(MountValidScaleRangeTable::MS_speciesUnmountable);
|
|
}
|
|
|
|
//... get the appearance name.
|
|
TemporaryCrcString appearanceTemplateName(sharedObjectTemplate->getAppearanceFilename().c_str(), true);
|
|
|
|
//-- Check if creature can be converted to a mount.
|
|
int const saddleCapacity = 1;
|
|
MountValidScaleRangeTable::MountabilityStatus const msResult = MountValidScaleRangeTable::doesCreatureSupportScaleAndSaddleCapacity(appearanceTemplateName, static_cast<float>(objectScale), saddleCapacity);
|
|
|
|
//-- Release resources.
|
|
objectTemplate->releaseReference();
|
|
sharedObjectTemplateBase->releaseReference();
|
|
|
|
//-- Return result.
|
|
return static_cast<jint>(msResult);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void JNICALL JNICALL ScriptMethodsMountNamespace::makeContainerStateInconsistentTestOnly(JNIEnv *env, jobject self, jlong containedObjectId)
|
|
{
|
|
//-- Get the ServerObject from the object id.
|
|
if (!containedObjectId)
|
|
{
|
|
LOG("script-bug", ("makeContainerStateInconsistentTestOnly(): containedObjectId is nullptr"));
|
|
return;
|
|
}
|
|
|
|
NetworkId networkId(containedObjectId);
|
|
if (networkId == NetworkId::cms_invalid)
|
|
{
|
|
LOG("script-bug", ("makeContainerStateInconsistentTestOnly(): containedObjectId is invalid"));
|
|
return;
|
|
}
|
|
|
|
Object *const containedObject = NetworkIdManager::getObjectById(networkId);
|
|
if (!containedObject)
|
|
{
|
|
LOG("script-bug", ("makeContainerStateInconsistentTestOnly(): containedObjectId [%s] is not on this server", networkId.getValueString().c_str()));
|
|
return;
|
|
}
|
|
|
|
if (!containedObject->isAuthoritative())
|
|
{
|
|
LOG("script-bug", ("makeContainerStateInconsistentTestOnly(): containedObjectId [%s] is not authoritative on this server", networkId.getValueString().c_str()));
|
|
return;
|
|
}
|
|
|
|
//-- Get the container.
|
|
Object* containerObject = ContainerInterface::getContainedByObject(*containedObject);
|
|
if (!containerObject)
|
|
{
|
|
LOG("script-bug", ("makeContainerStateInconsistentTestOnly(): containedObjectId [%s] is not contained by anything", networkId.getValueString().c_str()));
|
|
return;
|
|
}
|
|
|
|
Container* container = ContainerInterface::getContainer(*containerObject);
|
|
if (!container)
|
|
{
|
|
LOG("script-bug", ("makeContainerStateInconsistentTestOnly(): containerObject [%s] returned a nullptr container", containerObject->getNetworkId().getValueString().c_str()));
|
|
return;
|
|
}
|
|
|
|
//-- Break the containment relationship.
|
|
container->internalItemRemoved(*containedObject);
|
|
LOG("script-bug", ("makeContainerStateInconsistentTestOnly(): broke containment relationship for containedObjectId [%s], container [%s] now has invalid information", networkId.getValueString().c_str(), containerObject->getNetworkId().getValueString().c_str()));
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
jboolean JNICALL ScriptMethodsMountNamespace::doesMountHaveRoom(JNIEnv * env, jobject self, jlong mountId)
|
|
{
|
|
//-- Ignore calls if mounts are disabled.
|
|
if (!ConfigServerGame::getMountsEnabled())
|
|
{
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
//-- Get the rider object.
|
|
bool const throwIfNotOnServer = false;
|
|
CreatureObject const * const mountObject = JavaLibrary::getCreatureThrow(env, mountId, "getRiderId(): error in mountId arg", throwIfNotOnServer);
|
|
|
|
if (mountObject == 0)
|
|
{
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
return static_cast<jboolean>(mountObject->isMountableAndHasRoomForAnother());
|
|
}
|
|
|
|
// ======================================================================
|