mirror of
https://github.com/quizhizhe/LiteLoaderBDS-1.16.40.git
synced 2025-06-06 20:03:51 +00:00
413 lines
14 KiB
C++
413 lines
14 KiB
C++
#include "APIHelp.h"
|
|
#include "BaseAPI.h"
|
|
#include "McAPI.h"
|
|
#include "BlockAPI.h"
|
|
#include "ContainerAPI.h"
|
|
#include "EntityAPI.h"
|
|
#include "BlockEntityAPI.h"
|
|
#include "NbtAPI.h"
|
|
#include "NativeAPI.h"
|
|
#include <MC/Level.hpp>
|
|
#include <MC/Block.hpp>
|
|
#include <MC/CompoundTag.hpp>
|
|
#include <MC/BlockSource.hpp>
|
|
#include <MC/BlockInstance.hpp>
|
|
#include <MC/BlockActor.hpp>
|
|
#include <exception>
|
|
|
|
//////////////////// Class Definition ////////////////////
|
|
|
|
ClassDefine<BlockClass> BlockClassBuilder =
|
|
defineClass<BlockClass>("LLSE_Block")
|
|
.constructor(nullptr)
|
|
.instanceFunction("asPointer", &BlockClass::asPointer)
|
|
|
|
.instanceProperty("name", &BlockClass::getName)
|
|
.instanceProperty("type", &BlockClass::getType)
|
|
.instanceProperty("id", &BlockClass::getId)
|
|
.instanceProperty("pos", &BlockClass::getPos)
|
|
.instanceProperty("tileData", &BlockClass::getTileData)
|
|
|
|
.instanceFunction("setNbt", &BlockClass::setNbt)
|
|
.instanceFunction("getNbt", &BlockClass::getNbt)
|
|
.instanceFunction("getBlockState", &BlockClass::getBlockState)
|
|
.instanceFunction("hasContainer", &BlockClass::hasContainer)
|
|
.instanceFunction("getContainer", &BlockClass::getContainer)
|
|
.instanceFunction("hasBlockEntity", &BlockClass::hasBlockEntity)
|
|
.instanceFunction("getBlockEntity", &BlockClass::getBlockEntity)
|
|
.instanceFunction("removeBlockEntity", &BlockClass::removeBlockEntity)
|
|
.instanceFunction("destroy", &BlockClass::destroyBlock)
|
|
|
|
// For Compatibility
|
|
.instanceFunction("setTag", &BlockClass::setNbt)
|
|
.instanceFunction("getTag", &BlockClass::getNbt)
|
|
.build();
|
|
|
|
|
|
//////////////////// Classes ////////////////////
|
|
|
|
BlockClass::BlockClass(Block const* p)
|
|
: ScriptClass(ScriptClass::ConstructFromCpp<BlockClass>{}), block(const_cast<Block*>(p)) {
|
|
preloadData({0, 0, 0}, -1);
|
|
}
|
|
|
|
BlockClass::BlockClass(Block const* p, BlockPos bp, int dim)
|
|
: ScriptClass(ScriptClass::ConstructFromCpp<BlockClass>{}), block(const_cast<Block*>(p)) {
|
|
preloadData(bp, dim);
|
|
}
|
|
|
|
// generating function
|
|
Local<Object> BlockClass::newBlock(Block const* p, BlockPos const* pos, int dim) {
|
|
auto newp = new BlockClass(p, *pos, dim);
|
|
return newp->getScriptObject();
|
|
}
|
|
Local<Object> BlockClass::newBlock(BlockPos const* pos, int dim) {
|
|
return BlockClass::newBlock(Level::getBlock(const_cast<BlockPos*>(pos), dim), pos, dim);
|
|
}
|
|
Local<Object> BlockClass::newBlock(const BlockPos& pos, int dim) {
|
|
return newBlock((BlockPos*)&pos, dim);
|
|
}
|
|
Local<Object> BlockClass::newBlock(Block const* p, BlockPos const* pos, BlockSource const* bs) {
|
|
auto newp = new BlockClass(p, *pos, bs->getDimensionId());
|
|
return newp->getScriptObject();
|
|
}
|
|
Local<Object> BlockClass::newBlock(IntVec4 pos) {
|
|
BlockPos bp = {pos.x, pos.y, pos.z};
|
|
return BlockClass::newBlock(Level::getBlock(bp, pos.dim), &bp, pos.dim);
|
|
}
|
|
Local<Object> BlockClass::newBlock(BlockInstance block) {
|
|
BlockPos bp = block.getPosition();
|
|
return BlockClass::newBlock(block.getBlock(), &bp, block.getDimensionId());
|
|
}
|
|
Block* BlockClass::extract(Local<Value> v) {
|
|
if (EngineScope::currentEngine()->isInstanceOf<BlockClass>(v))
|
|
return EngineScope::currentEngine()->getNativeInstance<BlockClass>(v)->get();
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
// member function
|
|
void BlockClass::preloadData(BlockPos bp, int dim) {
|
|
name = block->getTypeName(); // TODO
|
|
type = block->getTypeName();
|
|
id = block->getId();
|
|
pos = {bp.x, bp.y, bp.z, dim};
|
|
}
|
|
|
|
Local<Value> BlockClass::getName() {
|
|
try {
|
|
// preloaded
|
|
return String::newString(name);
|
|
}
|
|
CATCH("Fail in getBlockName!");
|
|
}
|
|
|
|
Local<Value> BlockClass::getType() {
|
|
try {
|
|
// preloaded
|
|
return String::newString(type);
|
|
}
|
|
CATCH("Fail in getBlockType!");
|
|
}
|
|
|
|
Local<Value> BlockClass::getId() {
|
|
try {
|
|
// preloaded
|
|
return Number::newNumber(id);
|
|
}
|
|
CATCH("Fail in getBlockId!");
|
|
}
|
|
|
|
Local<Value> BlockClass::getPos() {
|
|
try {
|
|
// preloaded
|
|
return IntPos::newPos(pos);
|
|
}
|
|
CATCH("Fail in getBlockPos!");
|
|
}
|
|
|
|
Local<Value> BlockClass::getTileData() {
|
|
try {
|
|
// preloaded
|
|
return Number::newNumber(block->getTileData());
|
|
}
|
|
CATCH("Fail in getTileData!");
|
|
}
|
|
|
|
Local<Value> BlockClass::asPointer(const Arguments& args) {
|
|
try {
|
|
return NativePointer::newNativePointer(block);
|
|
}
|
|
CATCH("Fail in asPointer!");
|
|
}
|
|
|
|
Local<Value> BlockClass::destroyBlock(const Arguments& args) {
|
|
CHECK_ARGS_COUNT(args, 1);
|
|
CHECK_ARG_TYPE(args[0], ValueKind::kBoolean);
|
|
|
|
try {
|
|
// same as `Level::getBlockInstance(pos.getBlockPos(), pos.dim).breakNaturally()` when drop
|
|
return Boolean::newBoolean(Global<Level>->destroyBlock(*Level::getBlockSource(pos.dim), pos.getBlockPos(), args[0].asBoolean().value()));
|
|
}
|
|
CATCH("Fail in destroyBlock!");
|
|
}
|
|
|
|
Local<Value> BlockClass::getNbt(const Arguments& args) {
|
|
try {
|
|
return NbtCompoundClass::pack(std::move(block->getNbt()));
|
|
}
|
|
CATCH("Fail in getNbt!");
|
|
}
|
|
|
|
Local<Value> BlockClass::setNbt(const Arguments& args) {
|
|
CHECK_ARGS_COUNT(args, 1);
|
|
|
|
try {
|
|
auto nbt = NbtCompoundClass::extract(args[0]);
|
|
if (!nbt)
|
|
return Local<Value>(); // Null
|
|
|
|
// update Pre Data
|
|
Level::setBlock(pos.getBlockPos(), pos.dim, (CompoundTag*)nbt);
|
|
preloadData(pos.getBlockPos(), pos.getDimensionId());
|
|
return Boolean::newBoolean(true);
|
|
}
|
|
CATCH("Fail in setNbt!")
|
|
}
|
|
|
|
Local<Value> BlockClass::getBlockState(const Arguments& args) {
|
|
try {
|
|
auto list = block->getNbt();
|
|
try {
|
|
return Tag2Value((Tag*)list->get<Tag>("states"), true);
|
|
} catch (...) {
|
|
return Array::newArray();
|
|
}
|
|
} catch (const std::out_of_range& e) {
|
|
return Object::newObject();
|
|
}
|
|
CATCH("Fail in getBlockState!")
|
|
}
|
|
|
|
Local<Value> BlockClass::hasContainer(const Arguments& args) {
|
|
try {
|
|
auto bl = Level::getBlockInstance({pos.x, pos.y, pos.z}, pos.dim);
|
|
return Boolean::newBoolean(bl.hasContainer());
|
|
}
|
|
CATCH("Fail in hasContainer!");
|
|
}
|
|
|
|
Local<Value> BlockClass::getContainer(const Arguments& args) {
|
|
try {
|
|
Container* container = Level::getBlockInstance({pos.x, pos.y, pos.z}, pos.dim).getContainer();
|
|
return container ? ContainerClass::newContainer(container) : Local<Value>();
|
|
}
|
|
CATCH("Fail in getContainer!");
|
|
}
|
|
|
|
Local<Value> BlockClass::hasBlockEntity(const Arguments& args) {
|
|
try {
|
|
return Boolean::newBoolean(block->hasBlockEntity());
|
|
}
|
|
CATCH("Fail in hasBlockEntity!");
|
|
}
|
|
|
|
Local<Value> BlockClass::getBlockEntity(const Arguments& args) {
|
|
try {
|
|
BlockInstance bl = Level::getBlockInstance(pos.getBlockPos(), pos.dim);
|
|
BlockActor* be = bl.getBlockEntity();
|
|
return be ? BlockEntityClass::newBlockEntity(be, pos.dim) : Local<Value>();
|
|
}
|
|
CATCH("Fail in getBlockEntity!");
|
|
}
|
|
|
|
Local<Value> BlockClass::removeBlockEntity(const Arguments& args) {
|
|
try {
|
|
BlockSource* bs = Level::getBlockSource(pos.dim);
|
|
bs->removeBlockEntity(pos.getBlockPos()); //==========???
|
|
return Boolean::newBoolean(true);
|
|
}
|
|
CATCH("Fail in removeBlockEntity!");
|
|
}
|
|
|
|
// public API
|
|
Local<Value> McClass::getBlock(const Arguments& args) {
|
|
CHECK_ARGS_COUNT(args, 1);
|
|
|
|
try {
|
|
IntVec4 pos;
|
|
if (args.size() == 1) {
|
|
// IntPos
|
|
if (IsInstanceOf<IntPos>(args[0])) {
|
|
// IntPos
|
|
IntPos* posObj = IntPos::extractPos(args[0]);
|
|
if (posObj->dim < 0)
|
|
return Boolean::newBoolean(false);
|
|
else {
|
|
pos = *posObj;
|
|
}
|
|
} else if (IsInstanceOf<FloatPos>(args[0])) {
|
|
// FloatPos
|
|
FloatPos* posObj = FloatPos::extractPos(args[0]);
|
|
if (posObj->dim < 0)
|
|
return Boolean::newBoolean(false);
|
|
else {
|
|
pos = posObj->toIntVec4();
|
|
}
|
|
} else {
|
|
LOG_WRONG_ARG_TYPE();
|
|
return Local<Value>();
|
|
}
|
|
} else if (args.size() == 4) {
|
|
// Number Pos
|
|
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
|
|
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
|
|
CHECK_ARG_TYPE(args[2], ValueKind::kNumber);
|
|
CHECK_ARG_TYPE(args[3], ValueKind::kNumber);
|
|
pos = {args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()};
|
|
} else {
|
|
LOG_WRONG_ARGS_COUNT();
|
|
return Local<Value>();
|
|
}
|
|
|
|
auto block = Level::getBlockEx(pos.getBlockPos(), pos.dim);
|
|
if (!block) {
|
|
// LOG_WRONG_ARG_TYPE();
|
|
return Local<Value>();
|
|
}
|
|
BlockPos bp{pos.x, pos.y, pos.z};
|
|
return BlockClass::newBlock(block, &bp, pos.dim);
|
|
}
|
|
CATCH("Fail in GetBlock!")
|
|
}
|
|
|
|
Local<Value> McClass::setBlock(const Arguments& args) {
|
|
CHECK_ARGS_COUNT(args, 2);
|
|
|
|
try {
|
|
IntVec4 pos;
|
|
Local<Value> block;
|
|
unsigned short tileData = 0;
|
|
if (args.size() == 2 || args.size() == 3) {
|
|
if (args.size() == 3) {
|
|
CHECK_ARG_TYPE(args[1], ValueKind::kString);
|
|
CHECK_ARG_TYPE(args[2], ValueKind::kNumber);
|
|
tileData = args[2].toInt();
|
|
}
|
|
if (IsInstanceOf<IntPos>(args[0])) {
|
|
// IntPos
|
|
IntPos* posObj = IntPos::extractPos(args[0]);
|
|
if (posObj->dim < 0)
|
|
return Boolean::newBoolean(false);
|
|
else {
|
|
pos = *posObj;
|
|
block = args[1];
|
|
}
|
|
} else if (IsInstanceOf<FloatPos>(args[0])) {
|
|
// FloatPos
|
|
FloatPos* posObj = FloatPos::extractPos(args[0]);
|
|
if (posObj->dim < 0)
|
|
return Boolean::newBoolean(false);
|
|
else {
|
|
pos = posObj->toIntVec4();
|
|
block = args[1];
|
|
}
|
|
} else {
|
|
LOG_WRONG_ARG_TYPE();
|
|
return Local<Value>();
|
|
}
|
|
} else if (args.size() == 5 || args.size() == 6) {
|
|
// Number Pos
|
|
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
|
|
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
|
|
CHECK_ARG_TYPE(args[2], ValueKind::kNumber);
|
|
CHECK_ARG_TYPE(args[3], ValueKind::kNumber);
|
|
pos = {args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()};
|
|
block = args[4];
|
|
if (args.size() == 6) {
|
|
CHECK_ARG_TYPE(args[4], ValueKind::kString);
|
|
CHECK_ARG_TYPE(args[5], ValueKind::kNumber);
|
|
tileData = args[5].toInt();
|
|
}
|
|
} else {
|
|
LOG_WRONG_ARGS_COUNT();
|
|
return Local<Value>();
|
|
}
|
|
|
|
|
|
if (block.isString()) {
|
|
// block name
|
|
return Boolean::newBoolean(Level::setBlock(pos.getBlockPos(), pos.dim, block.toStr(), tileData));
|
|
} else if (IsInstanceOf<NbtCompoundClass>(block)) {
|
|
// Nbt
|
|
Tag* nbt = NbtCompoundClass::extract(block);
|
|
return Boolean::newBoolean(Level::setBlock(pos.getBlockPos(), pos.dim, (CompoundTag*)nbt));
|
|
} else {
|
|
// other block object
|
|
Block* bl = BlockClass::extract(block);
|
|
if (!bl) {
|
|
LOG_WRONG_ARG_TYPE();
|
|
return Local<Value>();
|
|
}
|
|
return Boolean::newBoolean(Level::setBlock(pos.getBlockPos(), pos.dim, bl));
|
|
}
|
|
}
|
|
CATCH("Fail in SetBlock!")
|
|
}
|
|
|
|
Local<Value> McClass::spawnParticle(const Arguments& args) {
|
|
CHECK_ARGS_COUNT(args, 2)
|
|
|
|
try {
|
|
FloatVec4 pos;
|
|
Local<Value> type;
|
|
|
|
if (args.size() == 2) {
|
|
// IntPos
|
|
CHECK_ARG_TYPE(args[1], ValueKind::kString);
|
|
|
|
if (IsInstanceOf<IntPos>(args[0])) {
|
|
// IntPos
|
|
IntPos* posObj = IntPos::extractPos(args[0]);
|
|
if (posObj->dim < 0)
|
|
return Boolean::newBoolean(false);
|
|
else {
|
|
pos.x = posObj->x;
|
|
pos.y = posObj->y;
|
|
pos.z = posObj->z;
|
|
pos.dim = posObj->dim;
|
|
type = args[1];
|
|
}
|
|
} else if (IsInstanceOf<FloatPos>(args[0])) {
|
|
// FloatPos
|
|
FloatPos* posObj = FloatPos::extractPos(args[0]);
|
|
if (posObj->dim < 0)
|
|
return Boolean::newBoolean(false);
|
|
else {
|
|
pos = *posObj;
|
|
type = args[1];
|
|
}
|
|
} else {
|
|
LOG_WRONG_ARG_TYPE();
|
|
return Local<Value>();
|
|
}
|
|
} else if (args.size() == 5) {
|
|
// Number Pos
|
|
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
|
|
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
|
|
CHECK_ARG_TYPE(args[2], ValueKind::kNumber);
|
|
CHECK_ARG_TYPE(args[3], ValueKind::kNumber);
|
|
CHECK_ARG_TYPE(args[4], ValueKind::kString);
|
|
|
|
pos = {args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), args[2].asNumber().toFloat(), args[3].toInt()};
|
|
type = args[4];
|
|
} else {
|
|
LOG_WRONG_ARGS_COUNT();
|
|
return Local<Value>();
|
|
}
|
|
|
|
Global<Level>->spawnParticleEffect(type.toStr(), pos.getVec3(), Global<Level>->getDimension(pos.dim));
|
|
return Boolean::newBoolean(true);
|
|
}
|
|
CATCH("Fail in SpawnParticle!")
|
|
} |