/* Copyright (C) 2012 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. 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. * * 0 A.D. 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 0 A.D. If not, see . */ #include "precompiled.h" #include "ps/CLogger.h" #include "scriptinterface/ScriptInterface.h" #include "simulation2/MessageTypes.h" #include "js/jsapi.h" #define TOJSVAL_SETUP() \ JSObject* obj = JS_NewObject(scriptInterface.GetContext(), NULL, NULL, NULL); \ if (! obj) \ return JSVAL_VOID; #define SET_MSG_PROPERTY(name) \ do { \ jsval prop = ScriptInterface::ToJSVal(scriptInterface.GetContext(), this->name); \ if (! JS_SetProperty(scriptInterface.GetContext(), obj, #name, &prop)) \ return JSVAL_VOID; \ } while (0); #define FROMJSVAL_SETUP() \ if (! JSVAL_IS_OBJECT(val)) \ return NULL; \ JSObject* obj = JSVAL_TO_OBJECT(val); \ jsval prop; #define GET_MSG_PROPERTY(type, name) \ if (! JS_GetProperty(scriptInterface.GetContext(), obj, #name, &prop)) \ return NULL; \ type name; \ if (! ScriptInterface::FromJSVal(scriptInterface.GetContext(), prop, name)) \ return NULL; jsval CMessage::ToJSValCached(ScriptInterface& scriptInterface) const { if (m_Cached.uninitialised()) m_Cached = CScriptValRooted(scriptInterface.GetContext(), ToJSVal(scriptInterface)); return m_Cached.get(); } //////////////////////////////// jsval CMessageTurnStart::ToJSVal(ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); return OBJECT_TO_JSVAL(obj); } CMessage* CMessageTurnStart::FromJSVal(ScriptInterface& UNUSED(scriptInterface), jsval UNUSED(val)) { return new CMessageTurnStart(); } //////////////////////////////// #define MESSAGE_1(name, t0, a0) \ jsval CMessage##name::ToJSVal(ScriptInterface& scriptInterface) const \ { \ TOJSVAL_SETUP(); \ SET_MSG_PROPERTY(a0); \ return OBJECT_TO_JSVAL(obj); \ } \ CMessage* CMessage##name::FromJSVal(ScriptInterface& scriptInterface, jsval val) \ { \ FROMJSVAL_SETUP(); \ GET_MSG_PROPERTY(t0, a0); \ return new CMessage##name(a0); \ } MESSAGE_1(Update, fixed, turnLength) MESSAGE_1(Update_MotionFormation, fixed, turnLength) MESSAGE_1(Update_MotionUnit, fixed, turnLength) MESSAGE_1(Update_Final, fixed, turnLength) //////////////////////////////// jsval CMessageInterpolate::ToJSVal(ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(frameTime); SET_MSG_PROPERTY(offset); return OBJECT_TO_JSVAL(obj); } CMessage* CMessageInterpolate::FromJSVal(ScriptInterface& scriptInterface, jsval val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(float, frameTime); GET_MSG_PROPERTY(float, offset); return new CMessageInterpolate(frameTime, offset); } //////////////////////////////// jsval CMessageRenderSubmit::ToJSVal(ScriptInterface& UNUSED(scriptInterface)) const { LOGWARNING(L"CMessageRenderSubmit::ToJSVal not implemented"); return JSVAL_VOID; } CMessage* CMessageRenderSubmit::FromJSVal(ScriptInterface& UNUSED(scriptInterface), jsval UNUSED(val)) { LOGWARNING(L"CMessageRenderSubmit::FromJSVal not implemented"); return NULL; } //////////////////////////////// jsval CMessageProgressiveLoad::ToJSVal(ScriptInterface& UNUSED(scriptInterface)) const { LOGWARNING(L"CMessageProgressiveLoad::ToJSVal not implemented"); return JSVAL_VOID; } CMessage* CMessageProgressiveLoad::FromJSVal(ScriptInterface& UNUSED(scriptInterface), jsval UNUSED(val)) { LOGWARNING(L"CMessageProgressiveLoad::FromJSVal not implemented"); return NULL; } //////////////////////////////// jsval CMessageCreate::ToJSVal(ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(entity); return OBJECT_TO_JSVAL(obj); } CMessage* CMessageCreate::FromJSVal(ScriptInterface& scriptInterface, jsval val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(entity_id_t, entity); return new CMessageCreate(entity); } //////////////////////////////// jsval CMessageDestroy::ToJSVal(ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(entity); return OBJECT_TO_JSVAL(obj); } CMessage* CMessageDestroy::FromJSVal(ScriptInterface& scriptInterface, jsval val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(entity_id_t, entity); return new CMessageDestroy(entity); } //////////////////////////////// jsval CMessageOwnershipChanged::ToJSVal(ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(entity); SET_MSG_PROPERTY(from); SET_MSG_PROPERTY(to); return OBJECT_TO_JSVAL(obj); } CMessage* CMessageOwnershipChanged::FromJSVal(ScriptInterface& scriptInterface, jsval val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(entity_id_t, entity); GET_MSG_PROPERTY(player_id_t, from); GET_MSG_PROPERTY(player_id_t, to); return new CMessageOwnershipChanged(entity, from, to); } //////////////////////////////// jsval CMessagePositionChanged::ToJSVal(ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(entity); SET_MSG_PROPERTY(inWorld); SET_MSG_PROPERTY(x); SET_MSG_PROPERTY(z); SET_MSG_PROPERTY(a); return OBJECT_TO_JSVAL(obj); } CMessage* CMessagePositionChanged::FromJSVal(ScriptInterface& scriptInterface, jsval val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(entity_id_t, entity); GET_MSG_PROPERTY(bool, inWorld); GET_MSG_PROPERTY(entity_pos_t, x); GET_MSG_PROPERTY(entity_pos_t, z); GET_MSG_PROPERTY(entity_angle_t, a); return new CMessagePositionChanged(entity, inWorld, x, z, a); } //////////////////////////////// jsval CMessageMotionChanged::ToJSVal(ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(starting); SET_MSG_PROPERTY(error); return OBJECT_TO_JSVAL(obj); } CMessage* CMessageMotionChanged::FromJSVal(ScriptInterface& scriptInterface, jsval val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(bool, starting); GET_MSG_PROPERTY(bool, error); return new CMessageMotionChanged(starting, error); } //////////////////////////////// jsval CMessageTerrainChanged::ToJSVal(ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(i0); SET_MSG_PROPERTY(j0); SET_MSG_PROPERTY(i1); SET_MSG_PROPERTY(j1); return OBJECT_TO_JSVAL(obj); } CMessage* CMessageTerrainChanged::FromJSVal(ScriptInterface& scriptInterface, jsval val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(int32_t, i0); GET_MSG_PROPERTY(int32_t, j0); GET_MSG_PROPERTY(int32_t, i1); GET_MSG_PROPERTY(int32_t, j1); return new CMessageTerrainChanged(i0, i1, j0, j1); } //////////////////////////////// jsval CMessageTerritoriesChanged::ToJSVal(ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); return OBJECT_TO_JSVAL(obj); } CMessage* CMessageTerritoriesChanged::FromJSVal(ScriptInterface& UNUSED(scriptInterface), jsval UNUSED(val)) { return new CMessageTerritoriesChanged(); } //////////////////////////////// jsval CMessageRangeUpdate::ToJSVal(ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(tag); SET_MSG_PROPERTY(added); SET_MSG_PROPERTY(removed); return OBJECT_TO_JSVAL(obj); } CMessage* CMessageRangeUpdate::FromJSVal(ScriptInterface& UNUSED(scriptInterface), jsval UNUSED(val)) { LOGWARNING(L"CMessageRangeUpdate::FromJSVal not implemented"); return NULL; } //////////////////////////////// jsval CMessagePathResult::ToJSVal(ScriptInterface& UNUSED(scriptInterface)) const { LOGWARNING(L"CMessagePathResult::ToJSVal not implemented"); return JSVAL_VOID; } CMessage* CMessagePathResult::FromJSVal(ScriptInterface& UNUSED(scriptInterface), jsval UNUSED(val)) { LOGWARNING(L"CMessagePathResult::FromJSVal not implemented"); return NULL; } //////////////////////////////// jsval CMessageTechnologyModification::ToJSVal(ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(component); SET_MSG_PROPERTY(player); return OBJECT_TO_JSVAL(obj); } CMessage* CMessageTechnologyModification::FromJSVal(ScriptInterface& scriptInterface, jsval val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(std::wstring, component); GET_MSG_PROPERTY(player_id_t, player); return new CMessageTechnologyModification(component, player); } //////////////////////////////////////////////////////////////// CMessage* CMessageFromJSVal(int mtid, ScriptInterface& scriptingInterface, jsval val) { switch (mtid) { #define MESSAGE(name) case MT_##name: return CMessage##name::FromJSVal(scriptingInterface, val); #define INTERFACE(name) #define COMPONENT(name) #include "simulation2/TypeList.h" #undef COMPONENT #undef INTERFACE #undef MESSAGE } return NULL; }