mirror of
https://github.com/quizhizhe/LiteLoaderBDS-1.16.40.git
synced 2025-06-05 03:43:40 +00:00
1324 lines
56 KiB
C++
1324 lines
56 KiB
C++
#include "EventAPI.h"
|
||
#include "McAPI.h"
|
||
#include <iostream>
|
||
#include <vector>
|
||
#include <list>
|
||
#include <map>
|
||
#include <string>
|
||
#include <sstream>
|
||
#include <exception>
|
||
#include <cstdarg>
|
||
#include <Global.hpp>
|
||
#include <Engine/TimeTaskSystem.h>
|
||
#include <Engine/EngineOwnData.h>
|
||
#include <Engine/GlobalShareData.h>
|
||
#include <Engine/LocalShareData.h>
|
||
#include <BuiltinCommands.h>
|
||
#include "APIHelp.h"
|
||
#include <NodeJsHelper.h>
|
||
#include "BaseAPI.h"
|
||
#include "BlockAPI.h"
|
||
#include "GuiAPI.h"
|
||
#include "CommandAPI.h"
|
||
#include "ItemAPI.h"
|
||
#include "EntityAPI.h"
|
||
#include "PlayerAPI.h"
|
||
#include <Loader.h>
|
||
#include <Configs.h>
|
||
#include <EventAPI.h>
|
||
#include <ScheduleAPI.h>
|
||
#include <MC/Player.hpp>
|
||
#include <MC/BlockSource.hpp>
|
||
#include <MC/Actor.hpp>
|
||
#include <MC/ActorDamageSource.hpp>
|
||
#include <MC/MobEffectInstance.hpp>
|
||
#include <MC/HashedString.hpp>
|
||
#include <MC/Objective.hpp>
|
||
#include <MC/BlockInstance.hpp>
|
||
#include <MC/Block.hpp>
|
||
#include <MC/VanillaBlocks.hpp>
|
||
#include <MC/ItemStack.hpp>
|
||
using namespace std;
|
||
|
||
//////////////////// Listeners ////////////////////
|
||
|
||
enum class EVENT_TYPES : int {
|
||
/* Player Events */
|
||
onPreJoin = 0,
|
||
onJoin,
|
||
onLeft,
|
||
onRespawn,
|
||
onPlayerDie,
|
||
onPlayerCmd,
|
||
onChat,
|
||
onChangeDim,
|
||
onJump,
|
||
onSneak,
|
||
onAttackEntity,
|
||
onAttackBlock,
|
||
onUseItem,
|
||
onUseItemOn,
|
||
onTakeItem,
|
||
onDropItem,
|
||
onEat,
|
||
onConsumeTotem,
|
||
onEffectAdded,
|
||
onEffectUpdated,
|
||
onEffectRemoved,
|
||
onStartDestroyBlock,
|
||
onDestroyBlock,
|
||
onPlaceBlock,
|
||
afterPlaceBlock,
|
||
onOpenContainer,
|
||
onCloseContainer,
|
||
onInventoryChange,
|
||
onMove,
|
||
onChangeSprinting,
|
||
onSetArmor,
|
||
onUseRespawnAnchor,
|
||
onOpenContainerScreen,
|
||
onExperienceAdd,
|
||
onBedEnter,
|
||
/* Entity Events */
|
||
onMobDie,
|
||
onMobHurt,
|
||
onEntityExplode,
|
||
onProjectileHitEntity,
|
||
onWitherBossDestroy,
|
||
onRide,
|
||
onStepOnPressurePlate,
|
||
onSpawnProjectile,
|
||
onProjectileCreated,
|
||
onNpcCmd,
|
||
onChangeArmorStand,
|
||
onEntityTransformation,
|
||
/* Block Events */
|
||
onBlockInteracted,
|
||
onBlockChanged,
|
||
onBlockExplode,
|
||
onRespawnAnchorExplode,
|
||
onBlockExploded,
|
||
onFireSpread,
|
||
onCmdBlockExecute,
|
||
onContainerChange,
|
||
onProjectileHitBlock,
|
||
onRedStoneUpdate,
|
||
onHopperSearchItem,
|
||
onHopperPushOut,
|
||
onPistonTryPush,
|
||
onPistonPush,
|
||
onFarmLandDecay,
|
||
onUseFrameBlock,
|
||
onLiquidFlow,
|
||
/* Other Events */
|
||
onScoreChanged,
|
||
onTick,
|
||
onServerStarted,
|
||
onConsoleCmd,
|
||
onConsoleOutput,
|
||
/* Economic Events */
|
||
onMoneyAdd,
|
||
onMoneyReduce,
|
||
onMoneyTrans,
|
||
onMoneySet,
|
||
beforeMoneyAdd,
|
||
beforeMoneyReduce,
|
||
beforeMoneyTrans,
|
||
beforeMoneySet,
|
||
onFormResponsePacket,
|
||
/* Outdated Events */
|
||
onAttack,
|
||
onExplode,
|
||
onBedExplode,
|
||
onMobSpawn,
|
||
onContainerChangeSlot,
|
||
EVENT_COUNT
|
||
};
|
||
|
||
struct ListenerListType {
|
||
ScriptEngine* engine;
|
||
script::Global<Function> func;
|
||
};
|
||
|
||
//监听器表
|
||
static std::list<ListenerListType> listenerList[int(EVENT_TYPES::EVENT_COUNT)];
|
||
|
||
//监听器历史
|
||
static bool hasListened[int(EVENT_TYPES::EVENT_COUNT)] = {0};
|
||
|
||
//监听器异常拦截
|
||
string EventTypeToString(EVENT_TYPES e) {
|
||
return string(magic_enum::enum_name(e));
|
||
}
|
||
|
||
#define LISTENER_CATCH(TYPE) \
|
||
catch (const Exception& e) { \
|
||
logger.error("Event Callback Failed!"); \
|
||
logger.error << e << logger.endl; \
|
||
logger.error("In Event: " + EventTypeToString(TYPE)); \
|
||
logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \
|
||
} \
|
||
catch (const std::exception& e) { \
|
||
logger.error("Event Callback Failed!"); \
|
||
logger.error("C++ Uncaught Exception Detected!"); \
|
||
logger.error(TextEncoding::toUTF8(e.what())); \
|
||
PrintScriptStackTrace(); \
|
||
logger.error("In Event: " + EventTypeToString(TYPE)); \
|
||
logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \
|
||
} \
|
||
catch (const seh_exception& e) { \
|
||
logger.error("Event Callback Failed!"); \
|
||
logger.error("SEH Uncaught Exception Detected!"); \
|
||
logger.error(TextEncoding::toUTF8(e.what())); \
|
||
PrintScriptStackTrace(); \
|
||
logger.error("In Event: " + EventTypeToString(TYPE)); \
|
||
logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \
|
||
}
|
||
|
||
//调用事件监听函数,拦截不执行original
|
||
#define CallEventRtnVoid(TYPE, ...) \
|
||
std::list<ListenerListType>& nowList = listenerList[int(TYPE)]; \
|
||
bool passToBDS = true; \
|
||
for (auto& listener : nowList) { \
|
||
EngineScope enter(listener.engine); \
|
||
try { \
|
||
auto result = listener.func.get().call({}, __VA_ARGS__); \
|
||
if (result.isBoolean() && result.asBoolean().value() == false) \
|
||
passToBDS = false; \
|
||
} \
|
||
LISTENER_CATCH(TYPE) \
|
||
} \
|
||
if (!passToBDS) { \
|
||
return; \
|
||
}
|
||
|
||
//调用事件监听函数,拦截返回false
|
||
#define CallEvent(TYPE, ...) \
|
||
std::list<ListenerListType>& nowList = listenerList[int(TYPE)]; \
|
||
bool passToBDS = true; \
|
||
for (auto& listener : nowList) { \
|
||
EngineScope enter(listener.engine); \
|
||
try { \
|
||
auto result = listener.func.get().call({}, __VA_ARGS__); \
|
||
if (result.isBoolean() && result.asBoolean().value() == false) \
|
||
passToBDS = false; \
|
||
} \
|
||
LISTENER_CATCH(TYPE) \
|
||
} \
|
||
return passToBDS;
|
||
|
||
//调用事件监听函数,拦截返回RETURN_VALUE
|
||
#define CallEventRtnValue(TYPE, RETURN_VALUE, ...) \
|
||
std::list<ListenerListType>& nowList = listenerList[int(TYPE)]; \
|
||
bool passToBDS = true; \
|
||
for (auto& listener : nowList) { \
|
||
EngineScope enter(listener.engine); \
|
||
try { \
|
||
auto result = listener.func.get().call({}, __VA_ARGS__); \
|
||
if (result.isBoolean() && result.asBoolean().value() == false) \
|
||
passToBDS = false; \
|
||
} \
|
||
LISTENER_CATCH(TYPE) \
|
||
} \
|
||
if (!passToBDS) { \
|
||
return RETURN_VALUE; \
|
||
}
|
||
|
||
//模拟事件调用监听
|
||
#define FakeCallEvent(ENGINE, TYPE, ...) \
|
||
{ \
|
||
std::list<ListenerListType>& nowList = listenerList[int(TYPE)]; \
|
||
for (auto& listener : nowList) { \
|
||
if (listener.engine == ENGINE) { \
|
||
EngineScope enter(listener.engine); \
|
||
try { \
|
||
listener.func.get().call({}, __VA_ARGS__); \
|
||
} \
|
||
LISTENER_CATCH(TYPE) \
|
||
} \
|
||
} \
|
||
}
|
||
|
||
//延迟调用事件
|
||
#define CallEventDelayed(TYPE, ...) \
|
||
std::list<ListenerListType>& nowList = listenerList[int(TYPE)]; \
|
||
for (auto& listener : nowList) { \
|
||
EngineScope enter(listener.engine); \
|
||
try { \
|
||
NewTimeout(listener.func.get(), {__VA_ARGS__}, 5); \
|
||
} \
|
||
LISTENER_CATCH(TYPE) \
|
||
}
|
||
|
||
//异常检查
|
||
#define IF_LISTENED(TYPE) \
|
||
if (!listenerList[int(TYPE)].empty()) { \
|
||
try
|
||
#define IF_LISTENED_END(TYPE) \
|
||
catch (...) { \
|
||
logger.error("Event Callback Failed!"); \
|
||
logger.error("Uncaught Exception Detected!"); \
|
||
logger.error("In Event: " + EventTypeToString(TYPE)); \
|
||
} \
|
||
} \
|
||
return true;
|
||
|
||
|
||
//////////////////// APIs ////////////////////
|
||
|
||
Local<Value> McClass::listen(const Arguments& args) {
|
||
CHECK_ARGS_COUNT(args, 2);
|
||
CHECK_ARG_TYPE(args[0], ValueKind::kString);
|
||
CHECK_ARG_TYPE(args[1], ValueKind::kFunction);
|
||
|
||
try {
|
||
return Boolean::newBoolean(LLSEAddEventListener(EngineScope::currentEngine(), args[0].toStr(), args[1].asFunction()));
|
||
}
|
||
CATCH("Fail to Bind Listener!");
|
||
}
|
||
|
||
//////////////////// Funcs ////////////////////
|
||
|
||
bool LLSEAddEventListener(ScriptEngine* engine, const string& eventName, const Local<Function>& func) {
|
||
try {
|
||
auto event_enum = magic_enum::enum_cast<EVENT_TYPES>(eventName);
|
||
auto eventId = int(event_enum.value());
|
||
listenerList[eventId].push_back({engine, script::Global<Function>(func)});
|
||
if (!hasListened[eventId]) {
|
||
hasListened[eventId] = true;
|
||
EnableEventListener(eventId);
|
||
}
|
||
return true;
|
||
} catch (...) {
|
||
logger.error("Event \"" + eventName + "\" No Found!\n");
|
||
logger.error("In Plugin: " + ENGINE_GET_DATA(engine)->pluginName);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
bool LLSERemoveAllEventListeners(ScriptEngine* engine) {
|
||
for (auto& listeners : listenerList) {
|
||
listeners.remove_if([engine](auto& listener) {
|
||
return listener.engine == engine;
|
||
});
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool LLSECallEventsOnHotLoad(ScriptEngine* engine) {
|
||
FakeCallEvent(engine, EVENT_TYPES::onServerStarted);
|
||
|
||
auto players = Level::getAllPlayers();
|
||
for (auto& pl : players)
|
||
FakeCallEvent(engine, EVENT_TYPES::onPreJoin, PlayerClass::newPlayer(pl));
|
||
for (auto& pl : players)
|
||
FakeCallEvent(engine, EVENT_TYPES::onJoin, PlayerClass::newPlayer(pl));
|
||
|
||
return true;
|
||
}
|
||
|
||
bool LLSECallEventsOnHotUnload(ScriptEngine* engine) {
|
||
auto players = Level::getAllPlayers();
|
||
for (auto& pl : players)
|
||
FakeCallEvent(engine, EVENT_TYPES::onLeft, PlayerClass::newPlayer(pl));
|
||
for (auto& [index, cb] : ENGINE_GET_DATA(engine)->unloadCallbacks) {
|
||
cb(engine);
|
||
}
|
||
ENGINE_GET_DATA(engine)->unloadCallbacks.clear();
|
||
return true;
|
||
}
|
||
|
||
//////////////////// Events ////////////////////
|
||
|
||
void EnableEventListener(int eventId) {
|
||
using namespace Event;
|
||
|
||
switch ((EVENT_TYPES)eventId) {
|
||
case EVENT_TYPES::onJoin:
|
||
Event::PlayerJoinEvent::subscribe([](const PlayerJoinEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onJoin) {
|
||
CallEvent(EVENT_TYPES::onJoin, PlayerClass::newPlayer((Player*)ev.mPlayer));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onJoin);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onPreJoin:
|
||
Event::PlayerPreJoinEvent::subscribe([](const PlayerPreJoinEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onPreJoin) {
|
||
CallEvent(EVENT_TYPES::onPreJoin, PlayerClass::newPlayer((Player*)ev.mPlayer));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onPreJoin);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onLeft:
|
||
Event::PlayerLeftEvent::subscribe([](const PlayerLeftEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onLeft) {
|
||
CallEvent(EVENT_TYPES::onLeft, PlayerClass::newPlayer((Player*)ev.mPlayer));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onLeft);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onChat:
|
||
Event::PlayerChatEvent::subscribe([](const PlayerChatEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onChat) {
|
||
CallEvent(EVENT_TYPES::onChat, PlayerClass::newPlayer(ev.mPlayer), ev.mMessage);
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onChat);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onChangeDim:
|
||
Event::PlayerChangeDimEvent::subscribe([](const PlayerChangeDimEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onChangeDim) {
|
||
CallEvent(EVENT_TYPES::onChangeDim, PlayerClass::newPlayer(ev.mPlayer), Number::newNumber(ev.mToDimensionId)); //======???
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onChangeDim);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onAttackEntity:
|
||
Event::PlayerAttackEvent::subscribe([](const PlayerAttackEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onAttackEntity) {
|
||
if (ev.mTarget) {
|
||
CallEvent(EVENT_TYPES::onAttackEntity, PlayerClass::newPlayer(ev.mPlayer), EntityClass::newEntity(ev.mTarget));
|
||
}
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onAttackEntity);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onAttackBlock:
|
||
Event::PlayerAttackBlockEvent::subscribe([](const PlayerAttackBlockEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onAttackBlock) {
|
||
CallEvent(EVENT_TYPES::onAttackBlock,
|
||
PlayerClass::newPlayer(ev.mPlayer),
|
||
BlockClass::newBlock(ev.mBlockInstance),
|
||
!ev.mItemStack->isNull() ? ItemClass::newItem(ev.mItemStack) : Local<Value>());
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onAttackBlock);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onPlayerDie:
|
||
Event::PlayerDieEvent::subscribe([](const PlayerDieEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onPlayerDie) {
|
||
Actor* source = ev.mDamageSource->getEntity();
|
||
CallEvent(EVENT_TYPES::onPlayerDie, PlayerClass::newPlayer(ev.mPlayer),
|
||
(source ? EntityClass::newEntity(source) : Local<Value>()));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onPlayerDie);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onRespawn:
|
||
Event::PlayerRespawnEvent::subscribe([](const PlayerRespawnEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onRespawn) {
|
||
CallEvent(EVENT_TYPES::onRespawn, PlayerClass::newPlayer((Player*)ev.mPlayer));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onRespawn)
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onStartDestroyBlock:
|
||
Event::PlayerStartDestroyBlockEvent::subscribe([](const PlayerStartDestroyBlockEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onStartDestroyBlock) {
|
||
CallEvent(EVENT_TYPES::onStartDestroyBlock, PlayerClass::newPlayer(ev.mPlayer),
|
||
BlockClass::newBlock(ev.mBlockInstance));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onStartDestroyBlock);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onDestroyBlock:
|
||
Event::PlayerDestroyBlockEvent::subscribe([](const PlayerDestroyBlockEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onDestroyBlock) {
|
||
CallEvent(EVENT_TYPES::onDestroyBlock, PlayerClass::newPlayer(ev.mPlayer), BlockClass::newBlock(ev.mBlockInstance));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onDestroyBlock);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onPlaceBlock:
|
||
Event::PlayerPlaceBlockEvent::subscribe([](const PlayerPlaceBlockEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onPlaceBlock) {
|
||
CallEvent(EVENT_TYPES::onPlaceBlock, PlayerClass::newPlayer(ev.mPlayer), BlockClass::newBlock(ev.mBlockInstance));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onPlaceBlock);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::afterPlaceBlock:
|
||
Event::BlockPlacedByPlayerEvent::subscribe([](const BlockPlacedByPlayerEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::afterPlaceBlock) {
|
||
CallEvent(EVENT_TYPES::afterPlaceBlock, PlayerClass::newPlayer(ev.mPlayer), BlockClass::newBlock(ev.mBlockInstance));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::afterPlaceBlock);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onMove:
|
||
Event::PlayerMoveEvent::subscribe([](const PlayerMoveEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onMove) {
|
||
CallEvent(EVENT_TYPES::onMove, PlayerClass::newPlayer(ev.mPlayer),
|
||
FloatPos::newPos(ev.mPos, ev.mPlayer->getDimensionId()));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onMove);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onJump:
|
||
Event::PlayerJumpEvent::subscribe([](const PlayerJumpEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onJump) {
|
||
CallEvent(EVENT_TYPES::onJump, PlayerClass::newPlayer(ev.mPlayer));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onJump);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onDropItem:
|
||
Event::PlayerDropItemEvent::subscribe([](const PlayerDropItemEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onDropItem) {
|
||
CallEvent(EVENT_TYPES::onDropItem, PlayerClass::newPlayer(ev.mPlayer), ItemClass::newItem(ev.mItemStack)); //###### Q lost items ######
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onDropItem);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onTakeItem:
|
||
Event::PlayerPickupItemEvent::subscribe([](const PlayerPickupItemEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onTakeItem) {
|
||
CallEvent(EVENT_TYPES::onTakeItem, PlayerClass::newPlayer(ev.mPlayer),
|
||
EntityClass::newEntity(ev.mItemEntity), ev.mItemStack ? ItemClass::newItem(ev.mItemStack) : Local<Value>());
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onTakeItem);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onOpenContainer:
|
||
Event::PlayerOpenContainerEvent::subscribe([](const PlayerOpenContainerEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onOpenContainer) {
|
||
CallEvent(EVENT_TYPES::onOpenContainer, PlayerClass::newPlayer(ev.mPlayer), BlockClass::newBlock(ev.mBlockInstance));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onOpenContainer);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onCloseContainer:
|
||
Event::PlayerCloseContainerEvent::subscribe([](const PlayerCloseContainerEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onCloseContainer) {
|
||
CallEvent(EVENT_TYPES::onCloseContainer, PlayerClass::newPlayer(ev.mPlayer), BlockClass::newBlock(ev.mBlockInstance));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onCloseContainer);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onInventoryChange:
|
||
Event::PlayerInventoryChangeEvent::subscribe([](const PlayerInventoryChangeEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onInventoryChange) {
|
||
CallEvent(EVENT_TYPES::onInventoryChange, PlayerClass::newPlayer(ev.mPlayer), ev.mSlot,
|
||
ItemClass::newItem(ev.mPreviousItemStack), ItemClass::newItem(ev.mNewItemStack));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onInventoryChange);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onUseItem:
|
||
Event::PlayerUseItemEvent::subscribe([](const PlayerUseItemEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onUseItem) {
|
||
CallEvent(EVENT_TYPES::onUseItem, PlayerClass::newPlayer((Player*)ev.mPlayer), ItemClass::newItem(ev.mItemStack));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onUseItem);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onUseItemOn:
|
||
Event::PlayerUseItemOnEvent::subscribe([](const PlayerUseItemOnEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onUseItemOn) {
|
||
CallEvent(EVENT_TYPES::onUseItemOn, PlayerClass::newPlayer((Player*)ev.mPlayer),
|
||
ItemClass::newItem(ev.mItemStack), BlockClass::newBlock(ev.mBlockInstance),
|
||
Number::newNumber(ev.mFace), FloatPos::newPos(ev.mClickPos));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onUseItemOn);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onContainerChange:
|
||
Event::ContainerChangeEvent::subscribe([](const ContainerChangeEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onContainerChange) {
|
||
CallEvent(EVENT_TYPES::onContainerChange, PlayerClass::newPlayer(ev.mPlayer), BlockClass::newBlock(ev.mBlockInstance),
|
||
ev.mSlot, ItemClass::newItem(ev.mPreviousItemStack), ItemClass::newItem(ev.mNewItemStack));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onContainerChange);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onChangeArmorStand:
|
||
Event::ArmorStandChangeEvent::subscribe([](const ArmorStandChangeEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onChangeArmorStand) {
|
||
CallEvent(EVENT_TYPES::onChangeArmorStand, EntityClass::newEntity((Actor*)ev.mArmorStand),
|
||
PlayerClass::newPlayer(ev.mPlayer), Number::newNumber(ev.mSlot));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onChangeArmorStand);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onChangeSprinting:
|
||
Event::PlayerSprintEvent::subscribe([](const PlayerSprintEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onChangeSprinting) {
|
||
CallEvent(EVENT_TYPES::onChangeSprinting, PlayerClass::newPlayer(ev.mPlayer),
|
||
Boolean::newBoolean(ev.mIsSprinting));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onChangeSprinting);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onSneak:
|
||
Event::PlayerSneakEvent::subscribe([](const PlayerSneakEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onSneak) {
|
||
CallEvent(EVENT_TYPES::onSneak, PlayerClass::newPlayer(ev.mPlayer), Boolean::newBoolean(ev.mIsSneaking));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onSneak);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onOpenContainerScreen:
|
||
Event::PlayerOpenContainerScreenEvent::subscribe([](const PlayerOpenContainerScreenEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onOpenContainerScreen) {
|
||
CallEvent(EVENT_TYPES::onOpenContainerScreen, PlayerClass::newPlayer(ev.mPlayer));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onOpenContainerScreen);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onSetArmor:
|
||
Event::PlayerSetArmorEvent::subscribe([](const PlayerSetArmorEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onSetArmor) {
|
||
CallEvent(EVENT_TYPES::onSetArmor, PlayerClass::newPlayer(ev.mPlayer), Number::newNumber(ev.mSlot),
|
||
ItemClass::newItem(ev.mArmorItem));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onSetArmor);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onEat:
|
||
Event::PlayerEatEvent::subscribe([](const PlayerEatEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onEat) {
|
||
CallEvent(EVENT_TYPES::onEat, PlayerClass::newPlayer(ev.mPlayer), ItemClass::newItem(ev.mFoodItem));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onEat);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onConsumeTotem:
|
||
Event::PlayerConsumeTotemEvent::subscribe([](const PlayerConsumeTotemEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onConsumeTotem) {
|
||
CallEvent(EVENT_TYPES::onConsumeTotem, PlayerClass::newPlayer(ev.mPlayer));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onConsumeTotem);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onEffectAdded:
|
||
case EVENT_TYPES::onEffectRemoved:
|
||
case EVENT_TYPES::onEffectUpdated:
|
||
Event::PlayerEffectChangedEvent::subscribe([](const PlayerEffectChangedEvent& ev) {
|
||
if (ev.mEventType == PlayerEffectChangedEvent::EventType::Add) {
|
||
IF_LISTENED(EVENT_TYPES::onEffectAdded) {
|
||
CallEvent(EVENT_TYPES::onEffectAdded, PlayerClass::newPlayer(ev.mPlayer),
|
||
String::newString(ev.mEffect->getComponentName().getString()));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onEffectAdded);
|
||
} else if (ev.mEventType == PlayerEffectChangedEvent::EventType::Remove) {
|
||
IF_LISTENED(EVENT_TYPES::onEffectRemoved) {
|
||
CallEvent(EVENT_TYPES::onEffectRemoved, PlayerClass::newPlayer(ev.mPlayer),
|
||
String::newString(ev.mEffect->getComponentName().getString()));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onEffectRemoved);
|
||
} else if (ev.mEventType == PlayerEffectChangedEvent::EventType::Update) {
|
||
IF_LISTENED(EVENT_TYPES::onEffectUpdated) {
|
||
CallEvent(EVENT_TYPES::onEffectUpdated, PlayerClass::newPlayer(ev.mPlayer),
|
||
String::newString(ev.mEffect->getComponentName().getString()));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onEffectUpdated);
|
||
}
|
||
return true;
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onUseRespawnAnchor:
|
||
Event::PlayerUseRespawnAnchorEvent::subscribe([](const PlayerUseRespawnAnchorEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onUseRespawnAnchor) {
|
||
BlockInstance bl(ev.mBlockInstance);
|
||
CallEvent(EVENT_TYPES::onUseRespawnAnchor, PlayerClass::newPlayer(ev.mPlayer),
|
||
IntPos::newPos(bl.getPosition(), bl.getDimensionId()));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onUseRespawnAnchor);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onRide:
|
||
Event::EntityRideEvent::subscribe([](const EntityRideEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onRide) {
|
||
CallEvent(EVENT_TYPES::onRide, EntityClass::newEntity(ev.mRider), EntityClass::newEntity(ev.mVehicle));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onRide);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onEntityExplode:
|
||
Event::EntityExplodeEvent::subscribe([](const EntityExplodeEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onEntityExplode) {
|
||
CallEvent(EVENT_TYPES::onEntityExplode, ev.mActor ? EntityClass::newEntity(ev.mActor) : Local<Value>(),
|
||
FloatPos::newPos(ev.mPos, ev.mDimension->getDimensionId()),
|
||
Number::newNumber(ev.mRadius), Number::newNumber(ev.mMaxResistance),
|
||
Boolean::newBoolean(ev.mBreaking), Boolean::newBoolean(ev.mFire));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onEntityExplode);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onBlockExplode:
|
||
Event::BlockExplodeEvent::subscribe([](const BlockExplodeEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onBlockExplode) {
|
||
BlockInstance bl(ev.mBlockInstance);
|
||
CallEvent(EVENT_TYPES::onBlockExplode, BlockClass::newBlock(bl),
|
||
IntPos::newPos(bl.getPosition(), bl.getDimensionId()),
|
||
Number::newNumber(ev.mRadius), Number::newNumber(ev.mMaxResistance),
|
||
Boolean::newBoolean(ev.mBreaking), Boolean::newBoolean(ev.mFire));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onBlockExplode);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onRespawnAnchorExplode:
|
||
Event::BlockExplodeEvent::subscribe([](const BlockExplodeEvent& ev) {
|
||
BlockInstance bl(ev.mBlockInstance);
|
||
if (bl.getBlock() == VanillaBlocks::mRespawnAnchor) {
|
||
IF_LISTENED(EVENT_TYPES::onRespawnAnchorExplode) {
|
||
CallEvent(EVENT_TYPES::onRespawnAnchorExplode, IntPos::newPos(bl.getPosition(), bl.getDimensionId()),
|
||
Local<Value>());
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onRespawnAnchorExplode);
|
||
}
|
||
return true;
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onBlockExploded:
|
||
Event::BlockExplodedEvent::subscribe([](const BlockExplodedEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onBlockExploded) {
|
||
CallEvent(EVENT_TYPES::onBlockExploded, BlockClass::newBlock(ev.mBlockInstance),
|
||
EntityClass::newEntity(ev.mExplodeSource));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onBlockExploded);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onCmdBlockExecute:
|
||
Event::CmdBlockExecuteEvent::subscribe([](const CmdBlockExecuteEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onCmdBlockExecute) {
|
||
if (ev.mIsMinecart) {
|
||
CallEvent(EVENT_TYPES::onCmdBlockExecute, String::newString(ev.mCommand),
|
||
FloatPos::newPos(ev.mMinecart->getPosition(), ev.mMinecart->getDimensionId()), true);
|
||
} else {
|
||
BlockInstance bl = ev.mBlockInstance;
|
||
CallEvent(EVENT_TYPES::onCmdBlockExecute, String::newString(ev.mCommand),
|
||
FloatPos::newPos(bl.getPosition().toVec3(), bl.getDimensionId()), true);
|
||
}
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onCmdBlockExecute);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onRedStoneUpdate:
|
||
Event::RedStoneUpdateEvent::subscribe([](const RedStoneUpdateEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onRedStoneUpdate) {
|
||
CallEvent(EVENT_TYPES::onRedStoneUpdate, BlockClass::newBlock(ev.mBlockInstance),
|
||
Number::newNumber(ev.mRedStonePower), Boolean::newBoolean(ev.mIsActivated));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onRedStoneUpdate);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onWitherBossDestroy:
|
||
Event::WitherBossDestroyEvent::subscribe([](const WitherBossDestroyEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onWitherBossDestroy) {
|
||
AABB range = ev.mDestroyRange;
|
||
int dimId = ((Actor*)ev.mWitherBoss)->getDimensionId();
|
||
CallEvent(EVENT_TYPES::onWitherBossDestroy, EntityClass::newEntity((Actor*)ev.mWitherBoss),
|
||
IntPos::newPos(range.min.toBlockPos(), dimId), IntPos::newPos(range.max.toBlockPos(), dimId));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onWitherBossDestroy);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onMobHurt:
|
||
Event::MobHurtEvent::subscribe([](const MobHurtEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onMobHurt) {
|
||
Actor* source = nullptr;
|
||
if (ev.mDamageSource->isEntitySource()) {
|
||
if (ev.mDamageSource->isChildEntitySource())
|
||
source = Level::getEntity(ev.mDamageSource->getEntityUniqueID());
|
||
else
|
||
source = Level::getEntity(ev.mDamageSource->getDamagingEntityUniqueID());
|
||
}
|
||
//TODO 此处的伤害无法获取
|
||
CallEvent(EVENT_TYPES::onMobHurt, EntityClass::newEntity(ev.mMob),
|
||
source ? EntityClass::newEntity(source) : Local<Value>(),
|
||
float(ev.mDamage), Number::newNumber(0));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onMobHurt)
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onStepOnPressurePlate:
|
||
Event::EntityStepOnPressurePlateEvent::subscribe([](const EntityStepOnPressurePlateEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onStepOnPressurePlate) {
|
||
CallEvent(EVENT_TYPES::onStepOnPressurePlate, EntityClass::newEntity(ev.mActor), BlockClass::newBlock(ev.mBlockInstance));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onStepOnPressurePlate);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onMobDie:
|
||
Event::MobDieEvent::subscribe([](const MobDieEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onMobDie) {
|
||
Actor* source = nullptr;
|
||
if (ev.mDamageSource->isEntitySource()) {
|
||
source = Level::getEntity(ev.mDamageSource->getDamagingEntityUniqueID());
|
||
if (ev.mDamageSource->isChildEntitySource())
|
||
source = source->getOwner();
|
||
}
|
||
//TODO 此处的伤害无法获取
|
||
CallEvent(EVENT_TYPES::onMobDie, EntityClass::newEntity((Actor*)ev.mMob),
|
||
(source ? EntityClass::newEntity(source) : Local<Value>()), Number::newNumber(0));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onMobDie);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onNpcCmd:
|
||
Event::NpcCmdEvent::subscribe([](const NpcCmdEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onNpcCmd) {
|
||
CallEvent(EVENT_TYPES::onNpcCmd, EntityClass::newEntity(ev.mNpc), PlayerClass::newPlayer(ev.mPlayer),
|
||
String::newString(ev.mCommand));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onNpcCmd);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onSpawnProjectile:
|
||
Event::ProjectileSpawnEvent::subscribe([](const ProjectileSpawnEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onSpawnProjectile) {
|
||
CallEvent(EVENT_TYPES::onSpawnProjectile, EntityClass::newEntity(ev.mShooter), String::newString(ev.mType));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onSpawnProjectile);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onProjectileCreated:
|
||
Event::ProjectileCreatedEvent::subscribe([](const ProjectileCreatedEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onProjectileCreated) {
|
||
CallEvent(EVENT_TYPES::onProjectileCreated, EntityClass::newEntity(ev.mShooter), EntityClass::newEntity(ev.mProjectile));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onProjectileCreated);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onProjectileHitEntity:
|
||
Event::ProjectileHitEntityEvent::subscribe([](const ProjectileHitEntityEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onProjectileHitEntity) {
|
||
CallEvent(EVENT_TYPES::onProjectileHitEntity, EntityClass::newEntity(ev.mTarget), EntityClass::newEntity(ev.mSource));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onProjectileHitEntity);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onEntityTransformation:
|
||
Event::EntityTransformEvent::subscribe([](const EntityTransformEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onEntityTransformation) {
|
||
CallEvent(EVENT_TYPES::onEntityTransformation, String::newString(to_string(ev.mBeforeEntityUniqueId->id)), EntityClass::newEntity(ev.mAfterEntity));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onEntityTransformation);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onProjectileHitBlock:
|
||
Event::ProjectileHitBlockEvent::subscribe([](const ProjectileHitBlockEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onProjectileHitBlock) {
|
||
CallEvent(EVENT_TYPES::onProjectileHitBlock, BlockClass::newBlock(ev.mBlockInstance),
|
||
EntityClass::newEntity(ev.mSource));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onProjectileHitBlock);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onLiquidFlow:
|
||
Event::LiquidSpreadEvent::subscribe([](const LiquidSpreadEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onLiquidFlow) {
|
||
CallEvent(EVENT_TYPES::onLiquidFlow, BlockClass::newBlock(ev.mBlockInstance), IntPos::newPos(ev.mTarget, ev.mDimensionId));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onLiquidFlow);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onUseFrameBlock:
|
||
Event::PlayerUseFrameBlockEvent::subscribe([](const PlayerUseFrameBlockEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onUseFrameBlock) {
|
||
CallEvent(EVENT_TYPES::onUseFrameBlock, PlayerClass::newPlayer(ev.mPlayer),
|
||
BlockClass::newBlock(ev.mBlockInstance));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onUseFrameBlock);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onBlockInteracted:
|
||
Event::BlockInteractedEvent::subscribe([](const BlockInteractedEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onBlockInteracted) {
|
||
CallEvent(EVENT_TYPES::onBlockInteracted, PlayerClass::newPlayer(ev.mPlayer),
|
||
BlockClass::newBlock(ev.mBlockInstance));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onBlockInteracted);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onFarmLandDecay:
|
||
Event::FarmLandDecayEvent::subscribe([](const FarmLandDecayEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onFarmLandDecay) {
|
||
BlockInstance bl(ev.mBlockInstance);
|
||
CallEvent(EVENT_TYPES::onFarmLandDecay, IntPos::newPos(bl.getPosition(), bl.getDimensionId()),
|
||
EntityClass::newEntity(ev.mActor));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onFarmLandDecay);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onPistonTryPush:
|
||
Event::PistonTryPushEvent::subscribe([](const PistonTryPushEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onPistonTryPush) {
|
||
BlockInstance bl(ev.mPistonBlockInstance);
|
||
CallEvent(EVENT_TYPES::onPistonTryPush, IntPos::newPos(bl.getPosition(), bl.getDimensionId()),
|
||
BlockClass::newBlock(ev.mTargetBlockInstance));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onPistonTryPush);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onPistonPush:
|
||
Event::PistonPushEvent::subscribe([](const PistonPushEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onPistonPush) {
|
||
BlockInstance bl(ev.mPistonBlockInstance);
|
||
CallEvent(EVENT_TYPES::onPistonPush, IntPos::newPos(bl.getPosition(), bl.getDimensionId()),
|
||
BlockClass::newBlock(ev.mTargetBlockInstance));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onPistonPush);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onHopperSearchItem:
|
||
Event::HopperSearchItemEvent::subscribe([](const HopperSearchItemEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onHopperSearchItem) {
|
||
if (ev.isMinecart) {
|
||
CallEvent(EVENT_TYPES::onHopperSearchItem, FloatPos::newPos(ev.mMinecartPos, ev.mDimensionId), ev.isMinecart);
|
||
} else {
|
||
BlockInstance bl = ev.mHopperBlock;
|
||
CallEvent(EVENT_TYPES::onHopperSearchItem, FloatPos::newPos(bl.getPosition().toVec3(), ev.mDimensionId), ev.isMinecart);
|
||
}
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onHopperSearchItem);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onHopperPushOut:
|
||
Event::HopperPushOutEvent::subscribe([](const HopperPushOutEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onHopperPushOut) {
|
||
CallEvent(EVENT_TYPES::onHopperPushOut, FloatPos::newPos(ev.mPos, ev.mDimensionId));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onHopperPushOut);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onFireSpread:
|
||
Event::FireSpreadEvent::subscribe([](const FireSpreadEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onFireSpread) {
|
||
CallEvent(EVENT_TYPES::onFireSpread, IntPos::newPos(ev.mTarget, ev.mDimensionId));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onFireSpread);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onBlockChanged:
|
||
Event::BlockChangedEvent::subscribe([](const BlockChangedEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onBlockChanged) {
|
||
CallEvent(EVENT_TYPES::onBlockChanged, BlockClass::newBlock(ev.mPreviousBlockInstance),
|
||
BlockClass::newBlock(ev.mNewBlockInstance));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onBlockChanged);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onScoreChanged:
|
||
Event::PlayerScoreChangedEvent::subscribe([](const PlayerScoreChangedEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onScoreChanged) {
|
||
CallEvent(EVENT_TYPES::onScoreChanged, PlayerClass::newPlayer(ev.mPlayer),
|
||
Number::newNumber(ev.mScore), String::newString(ev.mObjective->getName()),
|
||
String::newString(ev.mObjective->getDisplayName()));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onScoreChanged);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onConsoleOutput:
|
||
Event::ConsoleOutputEvent::subscribe([](const ConsoleOutputEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onConsoleOutput) {
|
||
CallEvent(EVENT_TYPES::onConsoleOutput, String::newString(ev.mOutput));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onConsoleOutput);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onMobSpawn:
|
||
Event::MobSpawnEvent::subscribe([](const MobSpawnEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onMobSpawn) {
|
||
CallEvent(EVENT_TYPES::onMobSpawn, String::newString(ev.mTypeName), FloatPos::newPos(ev.mPos, ev.mDimensionId));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onMobSpawn);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onExperienceAdd:
|
||
Event::PlayerExperienceAddEvent::subscribe([](const PlayerExperienceAddEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onExperienceAdd) {
|
||
CallEvent(EVENT_TYPES::onExperienceAdd, PlayerClass::newPlayer(ev.mPlayer), Number::newNumber(ev.mExp));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onExperienceAdd);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onBedEnter:
|
||
Event::PlayerBedEnterEvent::subscribe([](const PlayerBedEnterEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onBedEnter) {
|
||
BlockInstance bl(*ev.mBlockInstance);
|
||
CallEvent(EVENT_TYPES::onBedEnter, PlayerClass::newPlayer(ev.mPlayer), IntPos::newPos(bl.getPosition(), bl.getDimensionId()));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onBedEnter);
|
||
});
|
||
break;
|
||
|
||
/* DEPRECATED AND RECENTLY REMOVED - START */
|
||
|
||
case EVENT_TYPES::onAttack:
|
||
Event::PlayerAttackEvent::subscribe([](const PlayerAttackEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onAttack) {
|
||
if (ev.mTarget) {
|
||
CallEvent(EVENT_TYPES::onAttack, PlayerClass::newPlayer(ev.mPlayer), EntityClass::newEntity(ev.mTarget));
|
||
}
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onAttack);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onContainerChangeSlot:
|
||
Event::ContainerChangeEvent::subscribe([](const ContainerChangeEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onContainerChange) {
|
||
CallEvent(EVENT_TYPES::onContainerChange, PlayerClass::newPlayer(ev.mPlayer), BlockClass::newBlock(ev.mBlockInstance),
|
||
ev.mSlot, ItemClass::newItem(ev.mPreviousItemStack), ItemClass::newItem(ev.mNewItemStack));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onContainerChange);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onExplode:
|
||
Event::EntityExplodeEvent::subscribe([](const EntityExplodeEvent& ev) {
|
||
IF_LISTENED(EVENT_TYPES::onExplode) {
|
||
CallEvent(EVENT_TYPES::onExplode, ev.mActor ? EntityClass::newEntity(ev.mActor) : Local<Value>(),
|
||
FloatPos::newPos(ev.mPos, ev.mDimension->getDimensionId()),
|
||
Number::newNumber(ev.mRadius), Number::newNumber(ev.mMaxResistance),
|
||
Boolean::newBoolean(ev.mBreaking), Boolean::newBoolean(ev.mFire));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onExplode);
|
||
});
|
||
break;
|
||
|
||
case EVENT_TYPES::onBedExplode:
|
||
Event::BlockExplodeEvent::subscribe([](const BlockExplodeEvent& ev) {
|
||
BlockInstance bl(ev.mBlockInstance);
|
||
if (bl.getBlock()->getTypeName() == "minecraft:bed") {
|
||
IF_LISTENED(EVENT_TYPES::onBedExplode) {
|
||
CallEvent(EVENT_TYPES::onBedExplode, IntPos::newPos(bl.getPosition(), bl.getDimensionId()));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onBedExplode);
|
||
}
|
||
return true;
|
||
});
|
||
break;
|
||
|
||
/* DEPRECATED AND RECENTLY REMOVED - END */
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
void InitBasicEventListeners() {
|
||
using namespace Event;
|
||
|
||
Event::PlayerCmdEvent::subscribe([](const PlayerCmdEvent& ev) {
|
||
string cmd = ev.mCommand;
|
||
Player* player = ev.mPlayer;
|
||
|
||
vector<string> paras;
|
||
bool isFromOtherEngine = false;
|
||
string prefix = LLSEFindCmdReg(true, cmd, paras, &isFromOtherEngine);
|
||
|
||
if (!prefix.empty()) {
|
||
// LLSE Registered Cmd
|
||
int perm = localShareData->playerCmdCallbacks[prefix].perm;
|
||
|
||
if (player->getCommandPermissionLevel() >= perm) {
|
||
bool callbackRes = CallPlayerCmdCallback(player, prefix, paras);
|
||
IF_LISTENED(EVENT_TYPES::onPlayerCmd) {
|
||
CallEvent(EVENT_TYPES::onPlayerCmd, PlayerClass::newPlayer(player), String::newString(cmd));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onPlayerCmd);
|
||
if (!callbackRes)
|
||
return false;
|
||
}
|
||
} else {
|
||
if (isFromOtherEngine)
|
||
return false;
|
||
|
||
// Other Cmd
|
||
IF_LISTENED(EVENT_TYPES::onPlayerCmd) {
|
||
CallEvent(EVENT_TYPES::onPlayerCmd, PlayerClass::newPlayer(player), String::newString(cmd));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onPlayerCmd);
|
||
}
|
||
return true;
|
||
});
|
||
|
||
Event::ConsoleCmdEvent::subscribe_ref([](ConsoleCmdEvent& ev) {
|
||
string cmd = ev.mCommand;
|
||
|
||
// PreProcess
|
||
if (!ProcessDebugEngine(cmd))
|
||
return false;
|
||
if (!ProcessOldHotManageCommand(ev.mCommand))
|
||
return false;
|
||
#ifdef LLSE_BACKEND_NODEJS
|
||
if (!NodeJsHelper::processConsoleNpmCmd(ev.mCommand))
|
||
return false;
|
||
#endif
|
||
|
||
// CallEvents
|
||
vector<string> paras;
|
||
bool isFromOtherEngine = false;
|
||
string prefix = LLSEFindCmdReg(false, cmd, paras, &isFromOtherEngine);
|
||
|
||
if (!prefix.empty()) {
|
||
// LLSE Registered Cmd
|
||
|
||
bool callbackRes = CallServerCmdCallback(prefix, paras);
|
||
IF_LISTENED(EVENT_TYPES::onConsoleCmd) {
|
||
CallEvent(EVENT_TYPES::onConsoleCmd, String::newString(cmd));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onConsoleCmd);
|
||
if (!callbackRes)
|
||
return false;
|
||
} else {
|
||
if (isFromOtherEngine)
|
||
return false;
|
||
|
||
// Other Cmd
|
||
IF_LISTENED(EVENT_TYPES::onConsoleCmd) {
|
||
CallEvent(EVENT_TYPES::onConsoleCmd, String::newString(cmd));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onConsoleCmd);
|
||
}
|
||
return true;
|
||
});
|
||
|
||
// Plugin Hot Management
|
||
Event::ScriptPluginManagerEvent::subscribe_ref([](ScriptPluginManagerEvent& ev) {
|
||
// if (!LL::isDebugMode())
|
||
// return false;
|
||
|
||
switch (ev.operation) {
|
||
case ScriptPluginManagerEvent::Operation::Load:
|
||
// ev.pluginType is not used
|
||
// since in loadPlugin there will be check
|
||
if (PluginManager::loadPlugin(ev.target, true, true))
|
||
ev.success = true;
|
||
break;
|
||
|
||
case ScriptPluginManagerEvent::Operation::Unload:
|
||
if(PluginManager::unloadPlugin(ev.target))
|
||
ev.success = true;
|
||
break;
|
||
|
||
case ScriptPluginManagerEvent::Operation::Reload:
|
||
if(PluginManager::reloadPlugin(ev.target))
|
||
ev.success = true;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
if (ev.success)
|
||
return false; // Success. No need to spread to next engine
|
||
return true;
|
||
});
|
||
|
||
// For RegisterCmd...
|
||
Event::RegCmdEvent::subscribe([](const RegCmdEvent& ev) {
|
||
isCmdRegisterEnabled = true;
|
||
|
||
//处理延迟注册
|
||
ProcessRegCmdQueue();
|
||
return true;
|
||
});
|
||
|
||
|
||
// ===== onServerStarted =====
|
||
Event::ServerStartedEvent::subscribe([](Event::ServerStartedEvent ev) {
|
||
IF_LISTENED(EVENT_TYPES::onServerStarted) {
|
||
CallEventDelayed(EVENT_TYPES::onServerStarted);
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onServerStarted);
|
||
return true;
|
||
});
|
||
}
|
||
|
||
inline bool CallTickEvent() {
|
||
IF_LISTENED(EVENT_TYPES::onTick) {
|
||
CallEvent(EVENT_TYPES::onTick);
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onTick);
|
||
}
|
||
|
||
// 植入tick
|
||
THook(void, "?tick@ServerLevel@@UEAAXXZ",
|
||
void* _this) {
|
||
#ifndef LLSE_BACKEND_NODEJS
|
||
try {
|
||
std::list<ScriptEngine*> tmpList;
|
||
{
|
||
SRWLockSharedHolder lock(globalShareData->engineListLock);
|
||
// low efficiency
|
||
tmpList = globalShareData->globalEngineList;
|
||
}
|
||
for (auto engine : tmpList) {
|
||
if (EngineManager::isValid(engine) && EngineManager::getEngineType(engine) == LLSE_BACKEND_TYPE) {
|
||
EngineScope enter(engine);
|
||
engine->messageQueue()->loopQueue(script::utils::MessageQueue::LoopType::kLoopOnce);
|
||
}
|
||
}
|
||
} catch (...) {
|
||
logger.error("Error occurred in Engine Message Loop!");
|
||
logger.error("Uncaught Exception Detected!");
|
||
}
|
||
#endif
|
||
CallTickEvent();
|
||
return original(_this);
|
||
}
|
||
|
||
/* onTurnLectern // 由于还是不能拦截掉书,暂时注释
|
||
THook(void, "?handle@ServerNetworkHandler@@UEAAXAEBVNetworkIdentifier@@AEBVLecternUpdatePacket@@@Z",
|
||
ServerNetworkHandler* handler, NetworkIdentifier* id, Packet* pkt)
|
||
{
|
||
IF_LISTENED(EVENT_TYPES::onTurnLectern)
|
||
{
|
||
// Packet* pkt = *(Packet**)pPacket;
|
||
Player* player = Raw_GetPlayerFromPacket(handler, id, pkt);
|
||
if (!player)
|
||
return;
|
||
|
||
int page = *((DWORD*)pkt + 12);
|
||
dAccess<bool>(pkt, 56) = false;
|
||
bool shouldDropBook = *((BYTE*)pkt + 56);
|
||
int totalPages = *((DWORD*)pkt + 13);
|
||
auto* bp = new BlockPos;
|
||
bp->x = *((DWORD*)pkt + 15);
|
||
bp->y = *((DWORD*)pkt + 16);
|
||
bp->z = *((DWORD*)pkt + 17);
|
||
CallEventRtnVoid(EVENT_TYPES::onTurnLectern, PlayerClass::newPlayer(player), IntPos::newPos(bp, Raw_GetPlayerDimId(player)), page, totalPages, Boolean::newBoolean(shouldDropBook));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onTurnLectern);
|
||
original(handler,id,pkt);
|
||
}
|
||
*/
|
||
|
||
bool MoneyBeforeEventCallback(LLMoneyEvent type, xuid_t from, xuid_t to, money_t value) {
|
||
switch (type) {
|
||
case LLMoneyEvent::Add: {
|
||
IF_LISTENED(EVENT_TYPES::beforeMoneyAdd) {
|
||
CallEvent(EVENT_TYPES::beforeMoneyAdd, String::newString(to), Number::newNumber(value));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::beforeMoneyAdd);
|
||
break;
|
||
}
|
||
case LLMoneyEvent::Reduce: {
|
||
IF_LISTENED(EVENT_TYPES::beforeMoneyReduce) {
|
||
CallEvent(EVENT_TYPES::beforeMoneyReduce, String::newString(to), Number::newNumber(value));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::beforeMoneyReduce);
|
||
break;
|
||
}
|
||
case LLMoneyEvent::Trans: {
|
||
IF_LISTENED(EVENT_TYPES::beforeMoneyTrans) {
|
||
CallEvent(EVENT_TYPES::beforeMoneyTrans, String::newString(from), String::newString(to), Number::newNumber(value));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::beforeMoneyTrans);
|
||
break;
|
||
}
|
||
case LLMoneyEvent::Set: {
|
||
IF_LISTENED(EVENT_TYPES::beforeMoneySet) {
|
||
CallEvent(EVENT_TYPES::beforeMoneySet, String::newString(to), Number::newNumber(value));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::beforeMoneySet);
|
||
break;
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool MoneyEventCallback(LLMoneyEvent type, xuid_t from, xuid_t to, money_t value) {
|
||
switch (type) {
|
||
case LLMoneyEvent::Add: {
|
||
IF_LISTENED(EVENT_TYPES::onMoneyAdd) {
|
||
CallEvent(EVENT_TYPES::onMoneyAdd, String::newString(to), Number::newNumber(value));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onMoneyAdd);
|
||
break;
|
||
}
|
||
case LLMoneyEvent::Reduce: {
|
||
IF_LISTENED(EVENT_TYPES::onMoneyReduce) {
|
||
CallEvent(EVENT_TYPES::onMoneyReduce, String::newString(to), Number::newNumber(value));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onMoneyReduce);
|
||
break;
|
||
}
|
||
case LLMoneyEvent::Trans: {
|
||
IF_LISTENED(EVENT_TYPES::onMoneyTrans) {
|
||
CallEvent(EVENT_TYPES::onMoneyTrans, String::newString(from), String::newString(to), Number::newNumber(value));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onMoneyTrans);
|
||
break;
|
||
}
|
||
case LLMoneyEvent::Set: {
|
||
IF_LISTENED(EVENT_TYPES::onMoneySet) {
|
||
CallEvent(EVENT_TYPES::onMoneySet, String::newString(to), Number::newNumber(value));
|
||
}
|
||
IF_LISTENED_END(EVENT_TYPES::onMoneySet);
|
||
break;
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
return true;
|
||
} |