mirror of
https://github.com/neoStudiosLCE/neoLegacy.git
synced 2026-06-28 06:47:04 +00:00
Merge branch 'neoStudiosLCE:main' into dlc-skin-corrections
This commit is contained in:
commit
4caa7be9ef
BIN
.github/banner.png
vendored
BIN
.github/banner.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 656 KiB After Width: | Height: | Size: 673 KiB |
|
|
@ -8,7 +8,6 @@ ArmorStandModel::ArmorStandModel(float scale) : HumanoidModel(scale)
|
|||
{
|
||||
texWidth = 64;
|
||||
texHeight = 64;
|
||||
|
||||
|
||||
head = new ModelPart(this, 0, 0);
|
||||
head->addBox(-1.0f, -7.0f, -1.0f, 2, 7, 2, scale);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "PlayerRenderer.h"
|
||||
#include "../Minecraft.World/SkullItem.h"
|
||||
#include "../Minecraft.World/SkullTileEntity.h"
|
||||
#include "../Minecraft.World/ElytraItem.h"
|
||||
|
||||
static const float DEG_TO_RAD = 3.14159265f / 180.0f;
|
||||
|
||||
|
|
@ -84,9 +85,22 @@ void ArmorStandRenderer::render(shared_ptr<Entity> entity,
|
|||
double x, double y, double z,
|
||||
float rot, float a)
|
||||
{
|
||||
shared_ptr<LivingEntity> mob = dynamic_pointer_cast<LivingEntity>(entity);
|
||||
|
||||
float brightness = SharedConstants::TEXTURE_LIGHTING ? 1 : mob->getBrightness(a);
|
||||
glColor3f(brightness, brightness, brightness);
|
||||
shared_ptr<ItemInstance> item = mob->getCarriedItem();
|
||||
|
||||
prepareCarriedItem(mob, item);
|
||||
|
||||
LivingEntityRenderer::render(entity, x, y, z, rot, a);
|
||||
}
|
||||
|
||||
void ArmorStandRenderer::prepareCarriedItem(shared_ptr<Entity> mob, shared_ptr<ItemInstance> item)
|
||||
{
|
||||
armorLayer->armorModel1->holdingRightHand = armorLayer->armorModel2->holdingRightHand = item != nullptr ? 1 : 0;
|
||||
}
|
||||
|
||||
void ArmorStandRenderer::renderModel(shared_ptr<LivingEntity> mob,
|
||||
float wp, float ws, float bob,
|
||||
float headRotMinusBodyRot,
|
||||
|
|
@ -165,7 +179,109 @@ void ArmorStandRenderer::renderModel(shared_ptr<LivingEntity> mob,
|
|||
|
||||
void ArmorStandRenderer::additionalRendering(shared_ptr<LivingEntity> mob, float a)
|
||||
{
|
||||
|
||||
|
||||
{
|
||||
shared_ptr<ItemInstance> chestItem = mob->getEquipmentSlots()[ArmorStand::SLOT_CHEST];
|
||||
if (chestItem != nullptr && dynamic_cast<ElytraItem*>(chestItem->getItem()) != nullptr)
|
||||
{
|
||||
static ResourceLocation elytraTexture(L"item/elytra.png");
|
||||
bindTexture(&elytraTexture);
|
||||
|
||||
float brightness2 = SharedConstants::TEXTURE_LIGHTING ? 1 : mob->getBrightness(a);
|
||||
glColor3f(brightness2, brightness2, brightness2);
|
||||
|
||||
ArmorStandModel* standModel = ((ArmorStandModel*)this->model);
|
||||
ArmorStand* stand = dynamic_cast<ArmorStand*>(mob.get());
|
||||
|
||||
float wf = 0.2617994f;
|
||||
float wf1 = -0.2617994f;
|
||||
float wf2 = standModel->body->y;
|
||||
float wf3 = 0.0f;
|
||||
|
||||
stand->rotateElytraX += (wf - stand->rotateElytraX) * 0.3f;
|
||||
stand->rotateElytraY += (wf3 - stand->rotateElytraY) * 0.3f;
|
||||
stand->rotateElytraZ += (wf1 - stand->rotateElytraZ) * 0.3f;
|
||||
|
||||
|
||||
standModel->elytraRight->y = wf2;
|
||||
standModel->elytraRight->xRot = stand->rotateElytraX;
|
||||
standModel->elytraRight->yRot = stand->rotateElytraY;
|
||||
standModel->elytraRight->zRot = stand->rotateElytraZ;
|
||||
|
||||
standModel->elytraLeft->y = wf2;
|
||||
standModel->elytraLeft->xRot = stand->rotateElytraX;
|
||||
standModel->elytraLeft->yRot = -stand->rotateElytraY;
|
||||
standModel->elytraLeft->zRot = -stand->rotateElytraZ;
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(0, 0.0f, (2.0f + 0.125f) / 16.0f);
|
||||
standModel->renderElytra(1 / 16.0f, true);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<ItemInstance> item = mob->getCarriedItem();
|
||||
if (item != nullptr)
|
||||
{
|
||||
glPushMatrix();
|
||||
|
||||
ArmorStandModel* standModel = ((ArmorStandModel*)model);
|
||||
|
||||
if (standModel->young) {
|
||||
float s = 0.5f;
|
||||
glTranslatef(0 / 16.0f, 10 / 16.0f, 0 / 16.0f);
|
||||
glRotatef(-20, -1, 0, 0);
|
||||
glScalef(s, s, s);
|
||||
}
|
||||
|
||||
|
||||
standModel->arm1->translateTo(1 / 16.0f);
|
||||
glTranslatef(-1 / 16.0f, 7 / 16.0f, 1 / 16.0f);
|
||||
|
||||
if (item->id < 256 && TileRenderer::canRender(Tile::tiles[item->id]->getRenderShape()) && item->id != Tile::barrier_Id)
|
||||
{
|
||||
float s = 8 / 16.0f;
|
||||
glTranslatef(-0 / 16.0f, 3 / 16.0f, -5 / 16.0f);
|
||||
s *= 0.75f;
|
||||
glRotatef(20, 1, 0, 0);
|
||||
glRotatef(45, 0, 1, 0);
|
||||
glScalef(-s, -s, s);
|
||||
}
|
||||
else if (item->id == Item::bow_Id)
|
||||
{
|
||||
float s = 10 / 16.0f;
|
||||
glTranslatef(0 / 16.0f, 2 / 16.0f, 5 / 16.0f);
|
||||
glRotatef(-20, 0, 1, 0);
|
||||
glScalef(s, -s, s);
|
||||
glRotatef(-100, 1, 0, 0);
|
||||
glRotatef(45, 0, 1, 0);
|
||||
}
|
||||
else if (Item::items[item->id]->isHandEquipped())
|
||||
{
|
||||
float s = 10 / 16.0f;
|
||||
glTranslatef(0, 3 / 16.0f, 0);
|
||||
glScalef(s, -s, s);
|
||||
glRotatef(-100, 1, 0, 0);
|
||||
glRotatef(45, 0, 1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
float s = 6 / 16.0f;
|
||||
glTranslatef(+4 / 16.0f, +3 / 16.0f, -3 / 16.0f);
|
||||
glScalef(s, s, s);
|
||||
glRotatef(60, 0, 0, 1);
|
||||
glRotatef(-90, 1, 0, 0);
|
||||
glRotatef(20, 0, 0, 1);
|
||||
}
|
||||
|
||||
this->entityRenderDispatcher->itemInHandRenderer->renderItem(mob, item, 0);
|
||||
if (item->getItem()->hasMultipleSpriteLayers())
|
||||
{
|
||||
this->entityRenderDispatcher->itemInHandRenderer->renderItem(mob, item, 1);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -47,5 +47,7 @@ public:
|
|||
float headRotMinusBodyRot,
|
||||
float headRotx, float scale) override;
|
||||
virtual int prepareArmor(shared_ptr<LivingEntity> mob, int layer, float a) override;
|
||||
void prepareCarriedItem(shared_ptr<Entity> mob, shared_ptr<ItemInstance> item);
|
||||
|
||||
virtual void additionalRendering(shared_ptr<LivingEntity> mob, float a) override;
|
||||
};
|
||||
|
|
@ -4328,22 +4328,19 @@ void ClientConnection::handleSetPlayerTeamPacket(shared_ptr<SetPlayerTeamPacket>
|
|||
|
||||
void ClientConnection::handleParticleEvent(shared_ptr<LevelParticlesPacket> packet)
|
||||
{
|
||||
const ParticleType* type = packet->getType();
|
||||
if (type == nullptr) return;
|
||||
ePARTICLE_TYPE particleId = (ePARTICLE_TYPE)Integer::parseInt(packet->getName());
|
||||
|
||||
ePARTICLE_TYPE particleId = (ePARTICLE_TYPE)type->getId();
|
||||
for (int i = 0; i < packet->getCount(); i++)
|
||||
{
|
||||
double xVarience = random->nextGaussian() * packet->getXDist();
|
||||
double yVarience = random->nextGaussian() * packet->getYDist();
|
||||
double zVarience = random->nextGaussian() * packet->getZDist();
|
||||
double xa = random->nextGaussian() * packet->getMaxSpeed();
|
||||
double ya = random->nextGaussian() * packet->getMaxSpeed();
|
||||
double za = random->nextGaussian() * packet->getMaxSpeed();
|
||||
|
||||
for (int i = 0; i < packet->getCount(); i++)
|
||||
{
|
||||
double xVarience = random->nextGaussian() * packet->getXDist();
|
||||
double yVarience = random->nextGaussian() * packet->getYDist();
|
||||
double zVarience = random->nextGaussian() * packet->getZDist();
|
||||
double xa = random->nextGaussian() * packet->getMaxSpeed();
|
||||
double ya = random->nextGaussian() * packet->getMaxSpeed();
|
||||
double za = random->nextGaussian() * packet->getMaxSpeed();
|
||||
|
||||
level->addParticle(particleId, packet->getX() + xVarience, packet->getY() + yVarience, packet->getZ() + zVarience, xa, ya, za);
|
||||
}
|
||||
level->addParticle(particleId, packet->getX() + xVarience, packet->getY() + yVarience, packet->getZ() + zVarience, xa, ya, za);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientConnection::handleUpdateAttributes(shared_ptr<UpdateAttributesPacket> packet)
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 198 KiB After Width: | Height: | Size: 198 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 2.5 KiB |
|
|
@ -13,11 +13,19 @@
|
|||
#include "../Minecraft.World/SkullTileEntity.h"
|
||||
#include "../Minecraft.World/LivingEntity.h"
|
||||
#include "../Minecraft.World/Facing.h"
|
||||
#include "../Minecraft.Client/SimpleIcon.h"
|
||||
#include "../Minecraft.World/AirTile.h"
|
||||
|
||||
|
||||
CustomHeadLayer::CustomHeadLayer(ModelPart* headPart, LivingEntityRenderer* parentRenderer)
|
||||
: headPart(headPart), parentRenderer(parentRenderer)
|
||||
{
|
||||
tileRenderer = new TileRenderer();
|
||||
|
||||
}
|
||||
|
||||
CustomHeadLayer::~CustomHeadLayer() {
|
||||
delete tileRenderer;
|
||||
}
|
||||
|
||||
int CustomHeadLayer::colorsOnDamage()
|
||||
|
|
@ -90,12 +98,136 @@ void CustomHeadLayer::render(shared_ptr<LivingEntity> mob,
|
|||
|
||||
glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
|
||||
|
||||
Minecraft* mc = Minecraft::GetInstance();
|
||||
if (mc)
|
||||
{
|
||||
auto* iihr = mc->getItemInHandRenderer();
|
||||
if (iihr)
|
||||
iihr->renderItem(mob, helmet, 0, true);
|
||||
// 4J - code borrowed from render method below, although not factoring in brightness as that should already be being taken into account
|
||||
// by texture lighting. This is for colourising things held in 3rd person view.
|
||||
if ((item != nullptr)) {
|
||||
int col = Item::items[item->id]->getColor(helmet, 0);
|
||||
float red = ((col >> 16) & 0xff) / 255.0f;
|
||||
float g = ((col >> 8) & 0xff) / 255.0f;
|
||||
float b = ((col) & 0xff) / 255.0f;
|
||||
|
||||
glColor4f(red, g, b, 1);
|
||||
}
|
||||
|
||||
Minecraft* minecraft = Minecraft::GetInstance();
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
Tile* tile = Tile::tiles[item->id];
|
||||
if ((item->getIconType() == Icon::TYPE_TERRAIN && tile != nullptr && TileRenderer::canRender(tile->getRenderShape())) && item->id != AirTile::barrier_Id)
|
||||
{
|
||||
MemSect(31);
|
||||
minecraft->textures->bindTexture(minecraft->textures->getTextureLocation(Icon::TYPE_TERRAIN));
|
||||
MemSect(0);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
tileRenderer->renderTile(Tile::tiles[item->id], helmet->getAuxValue(), SharedConstants::TEXTURE_LIGHTING ? 1.0f : mob->getBrightness(1)); // 4J - change brought forward from 1.8.2
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
else
|
||||
{
|
||||
MemSect(31);
|
||||
Icon* icon = mob->getItemInHandIcon(helmet, 0);
|
||||
if (icon == nullptr)
|
||||
{
|
||||
glPopMatrix();
|
||||
MemSect(0);
|
||||
return;
|
||||
}
|
||||
|
||||
bool bIsTerrain = item->getIconType() == Icon::TYPE_TERRAIN;
|
||||
minecraft->textures->bindTexture(minecraft->textures->getTextureLocation(item->getIconType()));
|
||||
|
||||
MemSect(0);
|
||||
Tesselator* t = Tesselator::getInstance();
|
||||
|
||||
// Consider forcing the mipmap LOD level to use, if this is to be rendered from a larger than standard source texture.
|
||||
int iconWidth = icon->getWidth();
|
||||
int LOD = -1; // Default to not doing anything special with LOD forcing
|
||||
if (iconWidth == 32)
|
||||
{
|
||||
LOD = 1; // Force LOD level 1 to achieve texture reads from 256x256 map
|
||||
}
|
||||
else if (iconWidth == 64)
|
||||
{
|
||||
LOD = 2; // Force LOD level 2 to achieve texture reads from 256x256 map
|
||||
}
|
||||
RenderManager.StateSetForceLOD(LOD);
|
||||
|
||||
// 4J Original comment
|
||||
// Yes, these are backwards.
|
||||
// No, I don't know why.
|
||||
// 4J Stu - Make them the right way round...u coords were swapped
|
||||
float u0 = icon->getU0();
|
||||
float u1 = icon->getU1();
|
||||
float v0 = icon->getV0();
|
||||
float v1 = icon->getV1();
|
||||
|
||||
float xo = 0.0f;
|
||||
float yo = 0.3f;
|
||||
|
||||
// Re position height of held item if skin is small
|
||||
if (mob->getAnimOverrideBitmask() & (1 << HumanoidModel::eAnim_SmallModel))
|
||||
{
|
||||
if (mob->isRiding())
|
||||
{
|
||||
std::shared_ptr<Entity> ridingEntity = mob->riding;
|
||||
if (ridingEntity != nullptr) // Safety check;
|
||||
{
|
||||
yo += 0.3f; // reverts the change in Boat.cpp for smaller models.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_RESCALE_NORMAL);
|
||||
glTranslatef(-xo, -yo, 0);
|
||||
glScalef(1, 1, 1);
|
||||
|
||||
glRotatef(90, 0, 1, 0);
|
||||
glTranslatef(-7.5f / 16.0f, 9 / 16.0f, 0);
|
||||
glTranslatef(0, 0.03f, 0);
|
||||
float dd = 1 / 16.0f;
|
||||
|
||||
ItemInHandRenderer::renderItem3D(t, u0, v0, u1, v1, icon->getSourceWidth(), icon->getSourceHeight(), 1 / 16.0f, false, bIsTerrain);
|
||||
|
||||
if (item != nullptr && helmet->isFoil())
|
||||
{
|
||||
glDepthFunc(GL_EQUAL);
|
||||
glDisable(GL_LIGHTING);
|
||||
minecraft->textures->bindTexture(&ItemInHandRenderer::ENCHANT_GLINT_LOCATION);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_COLOR, GL_ONE);
|
||||
float br = 0.76f;
|
||||
glColor4f(0.5f * br, 0.25f * br, 0.8f * br, 1); // MGH - for some reason this colour isn't making it through to the render, so I've added to the tesselator for the glint geom above
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glPushMatrix();
|
||||
float ss = 1 / 8.0f;
|
||||
glScalef(ss, ss, ss);
|
||||
float sx = Minecraft::currentTimeMillis() % (3000) / (3000.0f) * 8;
|
||||
glTranslatef(sx, 0, 0);
|
||||
glRotatef(-50, 0, 0, 1);
|
||||
|
||||
ItemInHandRenderer::renderItem3D(t, 0, 0, 1, 1, 256, 256, 1 / 16.0f, true, bIsTerrain);
|
||||
glPopMatrix();
|
||||
glPushMatrix();
|
||||
glScalef(ss, ss, ss);
|
||||
sx = System::currentTimeMillis() % (3000 + 1873) / (3000 + 1873.0f) * 8;
|
||||
glTranslatef(-sx, 0, 0);
|
||||
glRotatef(10, 0, 0, 1);
|
||||
ItemInHandRenderer::renderItem3D(t, 0, 0, 1, 1, 256, 256, 1 / 16.0f, true, bIsTerrain);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_LIGHTING);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
}
|
||||
|
||||
RenderManager.StateSetForceLOD(-1);
|
||||
|
||||
glDisable(GL_RESCALE_NORMAL);
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,14 +4,17 @@
|
|||
class ModelPart;
|
||||
class LivingEntity;
|
||||
class LivingEntityRenderer;
|
||||
class TileRenderer;
|
||||
|
||||
class CustomHeadLayer : public RenderLayer {
|
||||
public:
|
||||
ModelPart* headPart;
|
||||
LivingEntityRenderer* parentRenderer;
|
||||
|
||||
TileRenderer* tileRenderer;
|
||||
|
||||
CustomHeadLayer(ModelPart* headPart, LivingEntityRenderer* parentRenderer);
|
||||
virtual ~CustomHeadLayer() {}
|
||||
virtual ~CustomHeadLayer();
|
||||
|
||||
virtual int colorsOnDamage() override;
|
||||
virtual void render(shared_ptr<LivingEntity> mob,
|
||||
|
|
|
|||
|
|
@ -474,7 +474,7 @@ void LivingEntityRenderer::renderName(shared_ptr<LivingEntity> mob, double x, do
|
|||
|
||||
bool LivingEntityRenderer::shouldShowName(shared_ptr<LivingEntity> mob)
|
||||
{
|
||||
return Minecraft::renderNames() && mob != entityRenderDispatcher->cameraEntity && !mob->isInvisibleTo(Minecraft::GetInstance()->player) && mob->rider.lock() == nullptr;
|
||||
return Minecraft::renderNames() && mob != entityRenderDispatcher->cameraEntity && (!mob->isInvisibleTo(Minecraft::GetInstance()->player) || mob->isCustomNameVisible()) && mob->rider.lock() == nullptr;
|
||||
}
|
||||
|
||||
void LivingEntityRenderer::renderNameTags(shared_ptr<LivingEntity> mob, double x, double y, double z, const wstring &msg, float scale, double dist)
|
||||
|
|
|
|||
|
|
@ -1046,6 +1046,13 @@ void PlayerConnection::handleCommand(const wstring& message)
|
|||
ss >> cmd;
|
||||
if (cmd == L"tp" || cmd == L"teleport")
|
||||
{
|
||||
|
||||
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
|
||||
{
|
||||
warn(L"Cheats are not enabled on this server.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player->hasPermission(eGameCommand_Teleport))
|
||||
{
|
||||
warn(L"You do not have permission to use this command.");
|
||||
|
|
@ -1138,6 +1145,13 @@ if (cmd == L"tp" || cmd == L"teleport")
|
|||
}
|
||||
} else if (cmd == L"time")
|
||||
{
|
||||
|
||||
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
|
||||
{
|
||||
warn(L"Cheats are not enabled on this server.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player->hasPermission(eGameCommand_Time))
|
||||
{
|
||||
warn(L"You do not have permission to use this command.");
|
||||
|
|
@ -1268,15 +1282,44 @@ if (cmd == L"tp" || cmd == L"teleport")
|
|||
}
|
||||
else if (cmd == L"kill")
|
||||
{
|
||||
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
|
||||
{
|
||||
warn(L"Cheats are not enabled on this server.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player->hasPermission(eGameCommand_Kill))
|
||||
{
|
||||
warn(L"You do not have permission to use this command.");
|
||||
return;
|
||||
}
|
||||
server->getCommandDispatcher()->performCommand(player, eGameCommand_Kill, byteArray());
|
||||
|
||||
wstring targetName;
|
||||
ss >> targetName;
|
||||
|
||||
if (targetName.empty())
|
||||
{
|
||||
|
||||
server->getCommandDispatcher()->performCommand(player, eGameCommand_Kill, byteArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
ByteArrayOutputStream baos;
|
||||
DataOutputStream dos(&baos);
|
||||
dos.writeUTF(targetName);
|
||||
byteArray data = baos.toByteArray();
|
||||
server->getCommandDispatcher()->performCommand(player, eGameCommand_Kill, data);
|
||||
}
|
||||
}
|
||||
else if (cmd == L"toggledownfall")
|
||||
{
|
||||
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
|
||||
{
|
||||
warn(L"Cheats are not enabled on this server.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player->hasPermission(eGameCommand_ToggleDownfall))
|
||||
{
|
||||
warn(L"You do not have permission to use this command.");
|
||||
|
|
@ -1285,6 +1328,14 @@ if (cmd == L"tp" || cmd == L"teleport")
|
|||
shared_ptr<GameCommandPacket> packet = ToggleDownfallCommand::preparePacket();
|
||||
server->getCommandDispatcher()->performCommand(player, eGameCommand_ToggleDownfall, packet->data);
|
||||
} else if (cmd == L"gamemode") {
|
||||
|
||||
|
||||
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
|
||||
{
|
||||
warn(L"Cheats are not enabled on this server.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player->hasPermission(eGameCommand_GameMode))
|
||||
{
|
||||
warn(L"You do not have permission to use this command.");
|
||||
|
|
@ -1323,6 +1374,13 @@ if (cmd == L"tp" || cmd == L"teleport")
|
|||
shared_ptr<GameCommandPacket> packet = GameModeCommand::preparePacket(target, mode);
|
||||
server->getCommandDispatcher()->performCommand(player, eGameCommand_GameMode, packet->data);
|
||||
} else if (cmd == L"give") {
|
||||
|
||||
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
|
||||
{
|
||||
warn(L"Cheats are not enabled on this server.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player->hasPermission(eGameCommand_Give))
|
||||
{
|
||||
warn(L"You do not have permission to use this command.");
|
||||
|
|
@ -1877,6 +1935,8 @@ void PlayerConnection::handleGameCommand(shared_ptr<GameCommandPacket> packet)
|
|||
player->getName().c_str(), player->isModerator() ? 1 : 0, isHost ? 1 : 0,
|
||||
static_cast<int>(packet->command));
|
||||
#endif
|
||||
|
||||
|
||||
MinecraftServer::getInstance()->getCommandDispatcher()->performCommand(player, packet->command, packet->data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1683,14 +1683,15 @@ void ServerLevel::flagEntitiesToBeRemoved(unsigned int *flags, bool *removedFoun
|
|||
}
|
||||
void ServerLevel::sendParticles(const ParticleType* type, bool longDistance, double x, double y, double z, int count, double dx, double dy, double dz, double speed, arrayWithLength<int> data)
|
||||
{
|
||||
wchar_t buf[32];
|
||||
swprintf_s(buf, L"%d", type->getId());
|
||||
|
||||
auto packet = make_shared<LevelParticlesPacket>(
|
||||
type,
|
||||
longDistance,
|
||||
buf,
|
||||
(float)x, (float)y, (float)z,
|
||||
(float)dx, (float)dy, (float)dz,
|
||||
(float)speed,
|
||||
count,
|
||||
data
|
||||
count
|
||||
);
|
||||
|
||||
for (auto const& p : players)
|
||||
|
|
|
|||
|
|
@ -1281,10 +1281,9 @@ void __cdecl NativeSpawnParticle(int entityId, int particleId, float x, float y,
|
|||
{
|
||||
auto player = FindPlayer(entityId);
|
||||
if (!player || !player->connection) return;
|
||||
const ParticleType* type = ParticleType::byId(particleId);
|
||||
if (!type) type = ParticleType::getDefault();
|
||||
arrayWithLength<int> noParams = { nullptr, 0 };
|
||||
player->connection->send(std::make_shared<LevelParticlesPacket>(type, false, x, y, z, offsetX, offsetY, offsetZ, speed, count, noParams));
|
||||
wchar_t buf[32];
|
||||
swprintf_s(buf, L"%d", particleId);
|
||||
player->connection->send(std::make_shared<LevelParticlesPacket>(std::wstring(buf), x, y, z, offsetX, offsetY, offsetZ, speed, count));
|
||||
}
|
||||
|
||||
int __cdecl NativeSetPassenger(int entityId, int passengerEntityId)
|
||||
|
|
|
|||
|
|
@ -16,11 +16,12 @@
|
|||
#include "ParticleTypes.h"
|
||||
#include "Random.h"
|
||||
#include "AABB.h"
|
||||
#include "../Minecraft.World/LevelChunk.h"
|
||||
|
||||
const Rotations ArmorStand::DEFAULT_HEAD_POSE (0.0f, 0.0f, 0.0f);
|
||||
const Rotations ArmorStand::DEFAULT_BODY_POSE (0.0f, 0.0f, 0.0f);
|
||||
const Rotations ArmorStand::DEFAULT_LEFT_ARM_POSE (-10.0f, 0.0f, -10.0f);
|
||||
const Rotations ArmorStand::DEFAULT_RIGHT_ARM_POSE (-15.0f, 0.0f, 10.0f);
|
||||
const Rotations ArmorStand::DEFAULT_LEFT_ARM_POSE (-15.0f, 0.0f, 10.0f);
|
||||
const Rotations ArmorStand::DEFAULT_RIGHT_ARM_POSE (-10.0f, 0.0f, -10.0f);
|
||||
const Rotations ArmorStand::DEFAULT_LEFT_LEG_POSE (-1.0f, 0.0f, -1.0f);
|
||||
const Rotations ArmorStand::DEFAULT_RIGHT_LEG_POSE (1.0f, 0.0f, 1.0f);
|
||||
|
||||
|
|
@ -45,6 +46,10 @@ void ArmorStand::init()
|
|||
for (int i = 0; i < equipmentCount; i++)
|
||||
equipment[i] = nullptr;
|
||||
|
||||
rotateElytraX = 0.2617994f;
|
||||
rotateElytraY = 0.0f;
|
||||
rotateElytraZ = -0.2617994f;
|
||||
|
||||
headPose = DEFAULT_HEAD_POSE;
|
||||
bodyPose = DEFAULT_BODY_POSE;
|
||||
leftArmPose = DEFAULT_LEFT_ARM_POSE;
|
||||
|
|
@ -83,7 +88,7 @@ void ArmorStand::defineSynchedData()
|
|||
|
||||
ArmorStand::~ArmorStand() {}
|
||||
|
||||
|
||||
bool ArmorStand::hasPhysics() const { return (entityData->getByte(DATA_CLIENT_FLAGS) & FLAG_NO_GRAVITY) == 0; }
|
||||
bool ArmorStand::isBaby() const { return (entityData->getByte(DATA_CLIENT_FLAGS) & FLAG_SMALL) != 0; }
|
||||
bool ArmorStand::isSmall() const { return isBaby(); }
|
||||
bool ArmorStand::isShowArms() const { return (entityData->getByte(DATA_CLIENT_FLAGS) & FLAG_SHOW_ARMS) != 0; }
|
||||
|
|
@ -188,6 +193,93 @@ void ArmorStand::updateInvisibilityStatus()
|
|||
setInvisible(invisible);
|
||||
}
|
||||
|
||||
void ArmorStand::travel(float xa, float ya)
|
||||
{
|
||||
if (hasPhysics()) {
|
||||
float friction = 0.91f;
|
||||
int frictionTile = 0;
|
||||
if (onGround)
|
||||
{
|
||||
frictionTile = level->getTile(Mth::floor(x), Mth::floor(bb->y0) - 1, Mth::floor(z));
|
||||
friction = 0.6f * 0.91f;
|
||||
if (frictionTile > 0)
|
||||
{
|
||||
friction = Tile::tiles[frictionTile]->friction * 0.91f;
|
||||
}
|
||||
}
|
||||
|
||||
float friction2 = (0.6f * 0.6f * 0.91f * 0.91f * 0.6f * 0.91f) / (friction * friction * friction);
|
||||
|
||||
float speed;
|
||||
if (onGround)
|
||||
{
|
||||
speed = getSpeed() * friction2;
|
||||
}
|
||||
else
|
||||
{
|
||||
speed = flyingSpeed;
|
||||
}
|
||||
|
||||
moveRelative(xa, ya, speed);
|
||||
|
||||
friction = 0.91f;
|
||||
if (onGround)
|
||||
{
|
||||
friction = 0.6f * 0.91f;
|
||||
if (frictionTile > 0)
|
||||
{
|
||||
friction = Tile::tiles[frictionTile]->friction * 0.91f;
|
||||
}
|
||||
}
|
||||
if (onLadder())
|
||||
{
|
||||
float max = 0.15f;
|
||||
if (xd < -max) xd = -max;
|
||||
if (xd > max) xd = max;
|
||||
if (zd < -max) zd = -max;
|
||||
if (zd > max) zd = max;
|
||||
fallDistance = 0;
|
||||
if (yd < -0.15) yd = -0.15;
|
||||
bool playerSneaking = isSneaking() && this->instanceof(eTYPE_PLAYER);
|
||||
if (playerSneaking && yd < 0) yd = 0;
|
||||
}
|
||||
|
||||
move(xd, yd, zd);
|
||||
|
||||
if (horizontalCollision && onLadder())
|
||||
{
|
||||
yd = 0.2;
|
||||
}
|
||||
|
||||
if (!level->isClientSide || (level->hasChunkAt(static_cast<int>(x), 0, static_cast<int>(z)) && level->getChunkAt(static_cast<int>(x), static_cast<int>(z))->loaded))
|
||||
{
|
||||
yd -= 0.08;
|
||||
}
|
||||
else if (y > 0)
|
||||
{
|
||||
yd = -0.1;
|
||||
}
|
||||
else
|
||||
{
|
||||
yd = 0;
|
||||
}
|
||||
|
||||
yd *= 0.98f;
|
||||
xd *= friction;
|
||||
zd *= friction;
|
||||
|
||||
walkAnimSpeedO = walkAnimSpeed;
|
||||
double xxd = x - xo;
|
||||
double zzd = z - zo;
|
||||
float wst = Mth::sqrt(xxd * xxd + zzd * zzd) * 4;
|
||||
if (wst > 1) wst = 1;
|
||||
walkAnimSpeed += (wst - walkAnimSpeed) * 0.4f;
|
||||
walkAnimPos += walkAnimSpeed;
|
||||
} else {
|
||||
move(xd, yd, zd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ArmorStand::tick()
|
||||
{
|
||||
|
|
@ -195,14 +287,14 @@ void ArmorStand::tick()
|
|||
LivingEntity::tick();
|
||||
if (onGround)
|
||||
{
|
||||
BlockPos pos((int)floorf(x), (int)floorf(y) - 1, (int)floorf(z));
|
||||
int blockId = level->getTile(pos.getX(), pos.getY(), pos.getZ());
|
||||
if (blockId == Tile::topSnow->id)
|
||||
{
|
||||
int meta = level->getData(pos.getX(), pos.getY(), pos.getZ());
|
||||
float snowHeight = ((meta & 0x7) + 1) * 0.125f;
|
||||
moveTo(x, floorf(y) + snowHeight, z, yRot, xRot);
|
||||
}
|
||||
BlockPos pos((int)floorf(x), (int)floorf(y) - 1, (int)floorf(z));
|
||||
int blockId = level->getTile(pos.getX(), pos.getY(), pos.getZ());
|
||||
if (blockId == Tile::topSnow->id)
|
||||
{
|
||||
int meta = level->getData(pos.getX(), pos.getY(), pos.getZ());
|
||||
float snowHeight = ((meta & 0x7) + 1) * 0.125f;
|
||||
moveTo(x, floorf(y) + snowHeight, z, yRot, xRot);
|
||||
}
|
||||
}
|
||||
this->yRot = lockedRot;
|
||||
this->yRotO = lockedRot;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,10 @@ private:
|
|||
bool isMarkerFlag;
|
||||
bool noPhysics;
|
||||
float standDamage;
|
||||
public:
|
||||
float rotateElytraX;
|
||||
float rotateElytraY;
|
||||
float rotateElytraZ;
|
||||
|
||||
public:
|
||||
long long lastHit;
|
||||
|
|
@ -64,6 +68,7 @@ public:
|
|||
explicit ArmorStand(Level* level);
|
||||
virtual ~ArmorStand();
|
||||
|
||||
bool hasPhysics() const;
|
||||
bool isBaby() const;
|
||||
bool isSmall() const;
|
||||
bool isShowArms() const;
|
||||
|
|
@ -142,6 +147,8 @@ public:
|
|||
void updateBoundingBox(bool markerMode);
|
||||
void updateInvisibilityStatus();
|
||||
|
||||
virtual void travel(float xz, float ya);
|
||||
|
||||
virtual shared_ptr<ItemInstance> getCarriedItem() override;
|
||||
virtual shared_ptr<ItemInstance> getCarried(int slot) override;
|
||||
virtual shared_ptr<ItemInstance> getArmor(int pos) override;
|
||||
|
|
|
|||
|
|
@ -1170,7 +1170,13 @@ bool EnderDragon::hurt(shared_ptr<MultiEntityMobPart> MultiEntityMobPart, Damage
|
|||
|
||||
bool EnderDragon::hurt(DamageSource *source, float damage)
|
||||
{
|
||||
return false;
|
||||
if (source == DamageSource::outOfWorld)
|
||||
{
|
||||
setSynchedAction(e_EnderdragonAction_Sitting_Scanning, true);
|
||||
reallyHurt(source, getMaxHealth() + 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EnderDragon::reallyHurt(DamageSource *source, float damage)
|
||||
|
|
|
|||
118
Minecraft.World/EntityTypeMap.cpp
Normal file
118
Minecraft.World/EntityTypeMap.cpp
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#include "stdafx.h"
|
||||
#include "EntityTypeMap.h"
|
||||
|
||||
static const unordered_map<wstring, eINSTANCEOF> s_nameToType = {
|
||||
// animals
|
||||
{ L"pig", eTYPE_PIG },
|
||||
{ L"cow", eTYPE_COW },
|
||||
{ L"sheep", eTYPE_SHEEP },
|
||||
{ L"chicken", eTYPE_CHICKEN },
|
||||
{ L"horse", eTYPE_HORSE },
|
||||
{ L"wolf", eTYPE_WOLF },
|
||||
{ L"ocelot", eTYPE_OCELOT },
|
||||
{ L"rabbit", eTYPE_RABBIT },
|
||||
{ L"mooshroom", eTYPE_MUSHROOMCOW },
|
||||
{ L"squid", eTYPE_SQUID },
|
||||
{ L"bat", eTYPE_BAT },
|
||||
// neutral/passive
|
||||
{ L"villager", eTYPE_VILLAGER },
|
||||
{ L"snowgolem", eTYPE_SNOWMAN },
|
||||
{ L"irongolem", eTYPE_VILLAGERGOLEM },
|
||||
// monsters
|
||||
{ L"zombie", eTYPE_ZOMBIE },
|
||||
{ L"skeleton", eTYPE_SKELETON },
|
||||
{ L"creeper", eTYPE_CREEPER },
|
||||
{ L"spider", eTYPE_SPIDER },
|
||||
{ L"cavespider", eTYPE_CAVESPIDER },
|
||||
{ L"enderman", eTYPE_ENDERMAN },
|
||||
{ L"silverfish", eTYPE_SILVERFISH },
|
||||
{ L"blaze", eTYPE_BLAZE },
|
||||
{ L"witch", eTYPE_WITCH },
|
||||
{ L"ghast", eTYPE_GHAST },
|
||||
{ L"slime", eTYPE_SLIME },
|
||||
{ L"magmacube", eTYPE_LAVASLIME },
|
||||
{ L"zombie_pigman", eTYPE_PIGZOMBIE },
|
||||
{ L"witherboss", eTYPE_WITHERBOSS },
|
||||
{ L"enderdragon", eTYPE_ENDERDRAGON },
|
||||
{ L"giant", eTYPE_GIANT },
|
||||
{ L"endermite", eTYPE_ENDERMITE },
|
||||
{ L"guardian", eTYPE_GUARDIAN },
|
||||
{ L"elder_guardian", eTYPE_ELDER_GUARDIAN },
|
||||
// minecart
|
||||
{ L"minecart", eTYPE_MINECART },
|
||||
{ L"minecart_chest", eTYPE_MINECART_CHEST },
|
||||
{ L"minecart_hopper", eTYPE_MINECART_HOPPER },
|
||||
{ L"minecart_tnt", eTYPE_MINECART_TNT },
|
||||
{ L"minecart_furnace", eTYPE_MINECART_FURNACE },
|
||||
{ L"minecart_spawner", eTYPE_MINECART_SPAWNER },
|
||||
// projectiles
|
||||
{ L"arrow", eTYPE_ARROW },
|
||||
{ L"snowball", eTYPE_SNOWBALL },
|
||||
{ L"egg", eTYPE_THROWNEGG },
|
||||
{ L"enderpearl", eTYPE_THROWNENDERPEARL },
|
||||
{ L"potion", eTYPE_THROWNPOTION },
|
||||
{ L"expbottle", eTYPE_THROWNEXPBOTTLE },
|
||||
{ L"large_fireball", eTYPE_LARGE_FIREBALL },
|
||||
{ L"small_fireball", eTYPE_SMALL_FIREBALL },
|
||||
{ L"wither_skull", eTYPE_WITHER_SKULL },
|
||||
{ L"dragon_fireball", eTYPE_DRAGON_FIREBALL },
|
||||
{ L"fireworks_rocket", eTYPE_FIREWORKS_ROCKET },
|
||||
{ L"eyeofender", eTYPE_EYEOFENDERSIGNAL },
|
||||
// hanging
|
||||
{ L"painting", eTYPE_PAINTING },
|
||||
{ L"item_frame", eTYPE_ITEM_FRAME },
|
||||
{ L"leash_knot", eTYPE_LEASHFENCEKNOT },
|
||||
// others
|
||||
{ L"item", eTYPE_ITEMENTITY },
|
||||
{ L"xp_orb", eTYPE_EXPERIENCEORB },
|
||||
{ L"boat", eTYPE_BOAT },
|
||||
{ L"tnt", eTYPE_PRIMEDTNT },
|
||||
{ L"falling_block", eTYPE_FALLINGTILE },
|
||||
{ L"armor_stand", eTYPE_ARMORSTAND },
|
||||
{ L"ender_crystal", eTYPE_ENDER_CRYSTAL },
|
||||
{ L"lightning_bolt", eTYPE_LIGHTNINGBOLT },
|
||||
};
|
||||
|
||||
static const unordered_map<eINSTANCEOF, wstring> s_typeToName = []()
|
||||
{
|
||||
unordered_map<eINSTANCEOF, wstring> m;
|
||||
for (auto& pair : s_nameToType)
|
||||
{
|
||||
if (m.find(pair.second) == m.end())
|
||||
m[pair.second] = pair.first;
|
||||
}
|
||||
return m;
|
||||
}();
|
||||
|
||||
const unordered_map<wstring, eINSTANCEOF>& EntityTypeMap::getNameToTypeMap()
|
||||
{
|
||||
return s_nameToType;
|
||||
}
|
||||
|
||||
const unordered_map<eINSTANCEOF, wstring>& EntityTypeMap::getTypeToNameMap()
|
||||
{
|
||||
return s_typeToName;
|
||||
}
|
||||
|
||||
eINSTANCEOF EntityTypeMap::getTypeFromName(const wstring& name)
|
||||
{
|
||||
wstring lower = name;
|
||||
transform(lower.begin(), lower.end(), lower.begin(), towlower);
|
||||
auto it = s_nameToType.find(lower);
|
||||
if (it != s_nameToType.end())
|
||||
return it->second;
|
||||
return eTYPE_NOTSET;
|
||||
}
|
||||
|
||||
wstring EntityTypeMap::getNameFromType(eINSTANCEOF type)
|
||||
{
|
||||
auto it = s_typeToName.find(type);
|
||||
if (it != s_typeToName.end())
|
||||
return it->second;
|
||||
return L"";
|
||||
}
|
||||
|
||||
bool EntityTypeMap::isValidType(const wstring& name)
|
||||
{
|
||||
return getTypeFromName(name) != eTYPE_NOTSET;
|
||||
}
|
||||
21
Minecraft.World/EntityTypeMap.h
Normal file
21
Minecraft.World/EntityTypeMap.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
#include "../Minecraft.World/Class.h"
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class EntityTypeMap
|
||||
{
|
||||
public:
|
||||
|
||||
static eINSTANCEOF getTypeFromName(const wstring& name);
|
||||
|
||||
static wstring getNameFromType(eINSTANCEOF type);
|
||||
|
||||
|
||||
static bool isValidType(const wstring& name);
|
||||
|
||||
private:
|
||||
static const unordered_map<wstring, eINSTANCEOF>& getNameToTypeMap();
|
||||
static const unordered_map<eINSTANCEOF, wstring>& getTypeToNameMap();
|
||||
};
|
||||
|
|
@ -1,26 +1,197 @@
|
|||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "net.minecraft.commands.h"
|
||||
#include "net.minecraft.world.entity.player.h"
|
||||
#include "net.minecraft.world.damagesource.h"
|
||||
#include "net.minecraft.world.level.h"
|
||||
#include "BasicTypeContainers.h"
|
||||
#include "KillCommand.h"
|
||||
#include "EntityTypeMap.h"
|
||||
|
||||
|
||||
static void killEntity(shared_ptr<Entity> entity)
|
||||
{
|
||||
if (entity->instanceof(eTYPE_LIVINGENTITY))
|
||||
{
|
||||
auto living = dynamic_pointer_cast<LivingEntity>(entity);
|
||||
if (living != nullptr)
|
||||
{
|
||||
living->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
entity->remove();
|
||||
return;
|
||||
}
|
||||
entity->remove();
|
||||
}
|
||||
|
||||
EGameCommand KillCommand::getId()
|
||||
{
|
||||
return eGameCommand_Kill;
|
||||
return eGameCommand_Kill;
|
||||
}
|
||||
|
||||
int KillCommand::getPermissionLevel()
|
||||
{
|
||||
return LEVEL_ALL;
|
||||
return LEVEL_ALL;
|
||||
}
|
||||
|
||||
void KillCommand::execute(shared_ptr<CommandSender> source, byteArray commandData)
|
||||
{
|
||||
shared_ptr<Player> player = dynamic_pointer_cast<Player>(source);
|
||||
shared_ptr<Player> senderPlayer = dynamic_pointer_cast<Player>(source);
|
||||
if (senderPlayer == nullptr)
|
||||
return;
|
||||
|
||||
player->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
|
||||
Level *level = senderPlayer->level;
|
||||
if (level == nullptr)
|
||||
return;
|
||||
|
||||
source->sendMessage(L"Ouch. That look like it hurt.");
|
||||
//source.sendMessage(ChatMessageComponent.forTranslation("commands.kill.success"));
|
||||
|
||||
//nothing is the same of @s
|
||||
if (commandData.length == 0 || commandData.data == nullptr)
|
||||
{
|
||||
senderPlayer->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
ByteArrayInputStream bais(commandData);
|
||||
DataInputStream dis(&bais);
|
||||
wstring targetName = dis.readUTF();
|
||||
|
||||
wstring targetLower = targetName;
|
||||
transform(targetLower.begin(), targetLower.end(), targetLower.begin(), towlower);
|
||||
|
||||
//@s
|
||||
if (targetLower == L"@s")
|
||||
{
|
||||
senderPlayer->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
//@a
|
||||
if (targetLower == L"@a")
|
||||
{
|
||||
vector<shared_ptr<Player>> toKill;
|
||||
for (auto& p : level->players)
|
||||
if (p != nullptr && !p->removed)
|
||||
toKill.push_back(p);
|
||||
for (auto& p : toKill)
|
||||
p->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
//@p
|
||||
if (targetLower == L"@p")
|
||||
{
|
||||
shared_ptr<Player> nearest = level->getNearestPlayer(
|
||||
dynamic_pointer_cast<Entity>(senderPlayer), 9999.0);
|
||||
if (nearest != nullptr)
|
||||
{
|
||||
nearest->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
|
||||
source->sendMessage(L"Killed " + nearest->getName() + L".");
|
||||
}
|
||||
else
|
||||
{
|
||||
source->sendMessage(L"No player found.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//@r
|
||||
if (targetLower == L"@r")
|
||||
{
|
||||
if (level->players.empty())
|
||||
{
|
||||
source->sendMessage(L"No player found.");
|
||||
return;
|
||||
}
|
||||
int idx = rand() % (int)level->players.size();
|
||||
auto& p = level->players[idx];
|
||||
if (p != nullptr && !p->removed)
|
||||
{
|
||||
p->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
|
||||
source->sendMessage(L"Killed " + p->getName() + L".");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// @e
|
||||
if (targetLower.size() >= 2 && targetLower.substr(0, 2) == L"@e")
|
||||
{
|
||||
eINSTANCEOF filterType = eTYPE_NOTSET;
|
||||
bool invertFilter = false;
|
||||
bool filterIsPlayer = false;
|
||||
|
||||
if (targetLower.size() > 3 && targetLower[2] == L'[')
|
||||
{
|
||||
wstring inner = targetLower.substr(3, targetLower.size() - 4);
|
||||
wstring key = L"type=";
|
||||
size_t pos = inner.find(key);
|
||||
if (pos == wstring::npos)
|
||||
{
|
||||
source->sendMessage(L"Invalid selector syntax. Usage: @e[type=<entity_type>]");
|
||||
return;
|
||||
}
|
||||
|
||||
wstring typeStr = inner.substr(pos + key.size());
|
||||
if (!typeStr.empty() && typeStr[0] == L'!')
|
||||
{
|
||||
invertFilter = true;
|
||||
typeStr = typeStr.substr(1);
|
||||
}
|
||||
|
||||
if (typeStr == L"player")
|
||||
{
|
||||
filterIsPlayer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
filterType = EntityTypeMap::getTypeFromName(typeStr);
|
||||
if (filterType == eTYPE_NOTSET)
|
||||
{
|
||||
source->sendMessage(L"Unknown entity type: " + typeStr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector<shared_ptr<Entity>> toKill;
|
||||
for (auto& entity : level->entities)
|
||||
{
|
||||
if (entity == nullptr || entity->removed) continue;
|
||||
|
||||
bool isPlayer = entity->instanceof(eTYPE_PLAYER);
|
||||
|
||||
|
||||
bool matchesFilter;
|
||||
if (filterType == eTYPE_NOTSET && !filterIsPlayer)
|
||||
matchesFilter = true;
|
||||
else if (filterIsPlayer)
|
||||
matchesFilter = isPlayer;
|
||||
else
|
||||
matchesFilter = entity->instanceof(filterType);
|
||||
|
||||
if (invertFilter) matchesFilter = !matchesFilter;
|
||||
|
||||
if (matchesFilter)
|
||||
toKill.push_back(entity);
|
||||
}
|
||||
|
||||
for (auto& entity : toKill)
|
||||
if (!entity->removed)
|
||||
killEntity(entity);
|
||||
|
||||
source->sendMessage(L"Killed " + to_wstring(toKill.size()) + L" entities.");
|
||||
return;
|
||||
}
|
||||
|
||||
// by player name
|
||||
shared_ptr<Player> targetPlayer = level->getPlayerByName(targetName);
|
||||
if (targetPlayer != nullptr)
|
||||
{
|
||||
targetPlayer->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
|
||||
source->sendMessage(L"Killed " + targetName + L".");
|
||||
return;
|
||||
}
|
||||
|
||||
source->sendMessage(L"No entity was found.");
|
||||
}
|
||||
|
|
@ -1,127 +1,110 @@
|
|||
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "PacketListener.h"
|
||||
#include "LevelParticlesPacket.h"
|
||||
#include "../Minecraft.Client/ParticleType.h"
|
||||
|
||||
LevelParticlesPacket::LevelParticlesPacket()
|
||||
{
|
||||
|
||||
this->overrideLimiter = false;
|
||||
this->type = nullptr;
|
||||
this->count = 0;
|
||||
this->y = 0.0f;
|
||||
this->paramCount = 0;
|
||||
this->x = 0.0f;
|
||||
this->yDist = 0.0f;
|
||||
this->zDist = 0.0f;
|
||||
this->z = 0.0f;
|
||||
this->maxSpeed = 0.0f;
|
||||
this->xDist = 0.0f;
|
||||
this->params = nullptr;
|
||||
this->name = L"";
|
||||
this->x = 0.0f;
|
||||
this->y = 0.0f;
|
||||
this->z = 0.0f;
|
||||
this->xDist = 0.0f;
|
||||
this->yDist = 0.0f;
|
||||
this->zDist = 0.0f;
|
||||
this->maxSpeed = 0.0f;
|
||||
this->count = 0;
|
||||
}
|
||||
|
||||
LevelParticlesPacket::LevelParticlesPacket(const ParticleType* type, bool overrideLimiter,
|
||||
float x, float y, float z,
|
||||
float xDist, float yDist, float zDist,
|
||||
float maxSpeed, int count,
|
||||
arrayWithLength<int> data)
|
||||
LevelParticlesPacket::LevelParticlesPacket(const wstring& name, float x, float y, float z, float xDist, float yDist, float zDist, float maxSpeed, int count)
|
||||
{
|
||||
this->type = type;
|
||||
this->overrideLimiter = overrideLimiter;
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
this->xDist = xDist;
|
||||
this->yDist = yDist;
|
||||
this->zDist = zDist;
|
||||
this->maxSpeed = maxSpeed;
|
||||
this->count = count;
|
||||
this->paramCount = data.length;
|
||||
|
||||
if (data.data && data.length > 0)
|
||||
{
|
||||
this->params = new int[data.length];
|
||||
memcpy(this->params, data.data, data.length * sizeof(int));
|
||||
}
|
||||
else
|
||||
{
|
||||
this->params = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LevelParticlesPacket::~LevelParticlesPacket()
|
||||
{
|
||||
|
||||
if (params)
|
||||
{
|
||||
delete[] params;
|
||||
params = nullptr;
|
||||
}
|
||||
this->name = name;
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
this->xDist = xDist;
|
||||
this->yDist = yDist;
|
||||
this->zDist = zDist;
|
||||
this->maxSpeed = maxSpeed;
|
||||
this->count = count;
|
||||
}
|
||||
|
||||
void LevelParticlesPacket::read(DataInputStream* dis)
|
||||
{
|
||||
int particleId = dis->readInt();
|
||||
const ParticleType* resolved = ParticleType::byId(particleId);
|
||||
if (!resolved)
|
||||
resolved = ParticleType::getDefault();
|
||||
this->type = resolved;
|
||||
|
||||
this->overrideLimiter = dis->readBoolean();
|
||||
|
||||
this->x = dis->readFloat();
|
||||
this->y = dis->readFloat();
|
||||
this->z = dis->readFloat();
|
||||
this->xDist = dis->readFloat();
|
||||
this->yDist = dis->readFloat();
|
||||
this->zDist = dis->readFloat();
|
||||
this->maxSpeed = dis->readFloat();
|
||||
this->count = dis->readInt();
|
||||
|
||||
int paramCount = this->type ? this->type->getParamCount() : 0;
|
||||
this->paramCount = paramCount;
|
||||
|
||||
if (paramCount > 0)
|
||||
{
|
||||
this->params = new int[paramCount]();
|
||||
for (int i = 0; i < paramCount; i++)
|
||||
{
|
||||
this->params[i] = dis->readInt();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->params = nullptr;
|
||||
}
|
||||
name = readUtf(dis, 64);
|
||||
x = dis->readFloat();
|
||||
y = dis->readFloat();
|
||||
z = dis->readFloat();
|
||||
xDist = dis->readFloat();
|
||||
yDist = dis->readFloat();
|
||||
zDist = dis->readFloat();
|
||||
maxSpeed = dis->readFloat();
|
||||
count = dis->readInt();
|
||||
}
|
||||
|
||||
void LevelParticlesPacket::write(DataOutputStream* dos)
|
||||
{
|
||||
dos->writeInt(this->type ? this->type->getId() : 0);
|
||||
dos->writeBoolean(this->overrideLimiter);
|
||||
dos->writeFloat(this->x);
|
||||
dos->writeFloat(this->y);
|
||||
dos->writeFloat(this->z);
|
||||
dos->writeFloat(this->xDist);
|
||||
dos->writeFloat(this->yDist);
|
||||
dos->writeFloat(this->zDist);
|
||||
dos->writeFloat(this->maxSpeed);
|
||||
dos->writeInt(this->count);
|
||||
writeUtf(name, dos);
|
||||
dos->writeFloat(x);
|
||||
dos->writeFloat(y);
|
||||
dos->writeFloat(z);
|
||||
dos->writeFloat(xDist);
|
||||
dos->writeFloat(yDist);
|
||||
dos->writeFloat(zDist);
|
||||
dos->writeFloat(maxSpeed);
|
||||
dos->writeInt(count);
|
||||
}
|
||||
|
||||
int toWrite = this->type ? this->type->getParamCount() : 0;
|
||||
for (int i = 0; i < toWrite; i++)
|
||||
{
|
||||
dos->writeInt(this->params[i]);
|
||||
}
|
||||
wstring LevelParticlesPacket::getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
double LevelParticlesPacket::getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
double LevelParticlesPacket::getY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
double LevelParticlesPacket::getZ()
|
||||
{
|
||||
return z;
|
||||
}
|
||||
|
||||
float LevelParticlesPacket::getXDist()
|
||||
{
|
||||
return xDist;
|
||||
}
|
||||
|
||||
float LevelParticlesPacket::getYDist()
|
||||
{
|
||||
return yDist;
|
||||
}
|
||||
|
||||
float LevelParticlesPacket::getZDist()
|
||||
{
|
||||
return zDist;
|
||||
}
|
||||
|
||||
float LevelParticlesPacket::getMaxSpeed()
|
||||
{
|
||||
return maxSpeed;
|
||||
}
|
||||
|
||||
int LevelParticlesPacket::getCount()
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
void LevelParticlesPacket::handle(PacketListener* listener)
|
||||
{
|
||||
listener->handleParticleEvent(shared_from_this());
|
||||
listener->handleParticleEvent(shared_from_this());
|
||||
}
|
||||
|
||||
int LevelParticlesPacket::getEstimatedSize()
|
||||
{
|
||||
return 0x40;
|
||||
return 4 * 2 + 7 * 8;
|
||||
}
|
||||
|
|
@ -1,53 +1,39 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Packet.h"
|
||||
#include "../Minecraft.Client/ParticleType.h"
|
||||
|
||||
class LevelParticlesPacket : public Packet, public enable_shared_from_this<LevelParticlesPacket>
|
||||
{
|
||||
private:
|
||||
|
||||
const ParticleType* type;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float xDist;
|
||||
float yDist;
|
||||
float zDist;
|
||||
float maxSpeed;
|
||||
int count;
|
||||
bool overrideLimiter;
|
||||
int* params;
|
||||
int paramCount;
|
||||
wstring name;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float xDist;
|
||||
float yDist;
|
||||
float zDist;
|
||||
float maxSpeed;
|
||||
int count;
|
||||
|
||||
public:
|
||||
LevelParticlesPacket();
|
||||
LevelParticlesPacket(const ParticleType* type, bool overrideLimiter,
|
||||
float x, float y, float z,
|
||||
float xDist, float yDist, float zDist,
|
||||
float maxSpeed, int count,
|
||||
arrayWithLength<int> data);
|
||||
~LevelParticlesPacket();
|
||||
LevelParticlesPacket();
|
||||
LevelParticlesPacket(const wstring& name, float x, float y, float z, float xDist, float yDist, float zDist, float maxSpeed, int count);
|
||||
|
||||
void read(DataInputStream* dis) override;
|
||||
void write(DataOutputStream* dos) override;
|
||||
void read(DataInputStream* dis);
|
||||
void write(DataOutputStream* dos);
|
||||
wstring getName();
|
||||
double getX();
|
||||
double getY();
|
||||
double getZ();
|
||||
float getXDist();
|
||||
float getYDist();
|
||||
float getZDist();
|
||||
float getMaxSpeed();
|
||||
int getCount();
|
||||
void handle(PacketListener* listener);
|
||||
int getEstimatedSize();
|
||||
|
||||
const ParticleType* getType() { return type; }
|
||||
double getX() { return x; }
|
||||
double getY() { return y; }
|
||||
double getZ() { return z; }
|
||||
double getXDist() { return xDist; }
|
||||
double getYDist() { return yDist; }
|
||||
double getZDist() { return zDist; }
|
||||
double getMaxSpeed() { return maxSpeed; }
|
||||
int getCount() { return count; }
|
||||
bool isOverrideLimiter() { return overrideLimiter; }
|
||||
int* getParams() { return params; }
|
||||
int getParamCount() { return paramCount; }
|
||||
|
||||
void handle(PacketListener* listener) override;
|
||||
int getEstimatedSize() override;
|
||||
|
||||
static shared_ptr<Packet> create() { return std::make_shared<LevelParticlesPacket>(); }
|
||||
virtual int getId() override { return 63; }
|
||||
public:
|
||||
static shared_ptr<Packet> create() { return std::make_shared<LevelParticlesPacket>(); }
|
||||
virtual int getId() { return 63; }
|
||||
};
|
||||
|
|
@ -51,9 +51,10 @@ public:
|
|||
static const int DATA_ARROW_COUNT_ID = 9;
|
||||
|
||||
private:
|
||||
BaseAttributeMap* attributes;
|
||||
CombatTracker* combatTracker;
|
||||
unordered_map<int, MobEffectInstance*> activeEffects;
|
||||
protected:
|
||||
BaseAttributeMap* attributes;
|
||||
ItemInstanceArray lastEquipment;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -35,13 +35,16 @@ Ocelot::Ocelot(Level *level) : TamableAnimal(level)
|
|||
registerAttributes();
|
||||
setHealth(getMaxHealth());
|
||||
|
||||
avoidPlayerGoal = nullptr;
|
||||
|
||||
reassessTameGoals();
|
||||
|
||||
setSize(0.6f, 0.8f);
|
||||
|
||||
getNavigation()->setAvoidWater(true);
|
||||
goalSelector.addGoal(1, new FloatGoal(this));
|
||||
goalSelector.addGoal(2, sitGoal, false);
|
||||
goalSelector.addGoal(3, temptGoal = new TemptGoal(this, SNEAK_SPEED_MOD, Item::fish_raw_Id, true), false);
|
||||
goalSelector.addGoal(4, new AvoidPlayerGoal(this, typeid(Player), 16, WALK_SPEED_MOD, SPRINT_SPEED_MOD));
|
||||
goalSelector.addGoal(5, new FollowOwnerGoal(this, FOLLOW_SPEED_MOD, 10, 5));
|
||||
goalSelector.addGoal(6, new OcelotSitOnTileGoal(this, SPRINT_SPEED_MOD));
|
||||
goalSelector.addGoal(7, new LeapAtTargetGoal(this, 0.3f));
|
||||
|
|
@ -60,6 +63,21 @@ void Ocelot::defineSynchedData()
|
|||
entityData->define(DATA_TYPE_ID, static_cast<byte>(0));
|
||||
}
|
||||
|
||||
void Ocelot::reassessTameGoals()
|
||||
{
|
||||
if (!avoidPlayerGoal)
|
||||
avoidPlayerGoal = new AvoidPlayerGoal(this, typeid(Player), 16, WALK_SPEED_MOD, SPRINT_SPEED_MOD);
|
||||
|
||||
goalSelector.removeGoal(avoidPlayerGoal);
|
||||
if (!isTame())
|
||||
goalSelector.addGoal(4, avoidPlayerGoal, false);
|
||||
}
|
||||
|
||||
void Ocelot::setTame(bool tame)
|
||||
{
|
||||
TamableAnimal::setTame(tame);
|
||||
}
|
||||
|
||||
void Ocelot::serverAiMobStep()
|
||||
{
|
||||
if (getMoveControl()->hasWanted())
|
||||
|
|
@ -199,7 +217,10 @@ bool Ocelot::mobInteract(shared_ptr<Player> player)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (/*temptGoal->isRunning() &&*/ item != nullptr && item->id == Item::fish_raw_Id && player->distanceToSqr(shared_from_this()) < 3 * 3)
|
||||
//player must be close holding raw fish
|
||||
// temptGoal->isRunning() check removed
|
||||
// when the player enters interaction range, which would block taming entirely
|
||||
if (item != nullptr && item->id == Item::fish_raw_Id && player->distanceToSqr(shared_from_this()) < 3 * 3)
|
||||
{
|
||||
// 4J-PB - don't lose the fish in creative mode
|
||||
if (!player->abilities.instabuild) item->count--;
|
||||
|
|
@ -284,6 +305,8 @@ void Ocelot::setCatType(int type)
|
|||
|
||||
bool Ocelot::canSpawn()
|
||||
{
|
||||
|
||||
//return level->random->nextInt(3) != 0; when checkSpawnObstruction is implemented
|
||||
// artificially make ozelots more rare
|
||||
if (level->random->nextInt(3) == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "TamableAnimal.h"
|
||||
#include "AvoidPlayerGoal.h"
|
||||
|
||||
class TemptGoal;
|
||||
|
||||
|
|
@ -32,6 +33,7 @@ public:
|
|||
|
||||
private:
|
||||
TemptGoal *temptGoal;
|
||||
AvoidPlayerGoal *avoidPlayerGoal;
|
||||
|
||||
public:
|
||||
Ocelot(Level *level);
|
||||
|
|
@ -41,6 +43,8 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void serverAiMobStep();
|
||||
virtual void reassessTameGoals();
|
||||
virtual void setTame(bool tame);
|
||||
|
||||
protected:
|
||||
virtual bool removeWhenFarAway();
|
||||
|
|
@ -78,6 +82,7 @@ public:
|
|||
virtual int getCatType();
|
||||
virtual void setCatType(int type);
|
||||
virtual bool canSpawn();
|
||||
//virtual bool checkSpawnObstruction(); TODO when blockstates will be merged.
|
||||
virtual wstring getAName();
|
||||
virtual MobGroupData *finalizeMobSpawn(MobGroupData *groupData, int extraData = 0); // 4J Added extraData param
|
||||
|
||||
|
|
|
|||
|
|
@ -204,6 +204,8 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_COMMANDS_COMMON
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/ToggleDownfallCommand.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/WeatherCommand.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/net.minecraft.commands.common.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/EntityTypeMap.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/EntityTypeMap.cpp"
|
||||
)
|
||||
source_group("net/minecraft/commands/common" FILES ${_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_COMMANDS_COMMON})
|
||||
|
||||
|
|
|
|||
16
NOTES.md
16
NOTES.md
|
|
@ -1,6 +1,18 @@
|
|||
# neoLegacy v1.0.7b
|
||||
# neoLegacy v1.0.8b
|
||||
|
||||
- Reverted "Expanded" world size due to it causing crashing and lighting issues.
|
||||
### Bug Fixes
|
||||
- Game has been heavily optimized; expect more FPS.
|
||||
- Fullscreen option is now correctly applied on startup.
|
||||
- `/kill` now kills the player in creative.
|
||||
- Boat now follows the player correctly when speeding.
|
||||
- Ocelots can now be tamed.
|
||||
- Elytras and items are now rendered correctly when on an armor stand.
|
||||
|
||||
### Changes
|
||||
- Added new logo (made by rdust).
|
||||
- Added TU31 parity changes which include:
|
||||
- Dye recipes using flowers.
|
||||
- Prismarine block animation.
|
||||
|
||||
<img width="784" height="410" alt="roadmap" src="https://github.com/user-attachments/assets/134856ae-b151-4003-aa97-7ecf19ccd278" />
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ Huge thanks to the following projects:
|
|||
- [Patoke/LCERenewed](https://github.com/Patoke/LCERenewed) - for some of the patches that required deep decompilation
|
||||
- [itsRevela/LCE-Revelations](https://git.revela.dev/itsRevela/LCE-Revelations) - for providing a stable project for neoLegacy to continue with
|
||||
- [GabsPuNs/Project-Zenith](https://github.com/GabsPuNs/Project-Zenith-Main) - for providing us with their implemention of the Classic Crafting Feature.
|
||||
- rdust_dusted (Discord) - for providing us with a redesigned logo that we currently use.
|
||||
|
||||
# Build & Run
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue