mirror of
https://github.com/neoStudiosLCE/neoLegacy.git
synced 2026-07-17 18:07:02 +00:00
Compare commits
43 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3e02fb2d6 | ||
|
|
78a55e97ef | ||
|
|
4b93dbeedd | ||
|
|
c268ef1cc3 | ||
|
|
f3d4e20b7a | ||
|
|
c0196abe3b | ||
|
|
7f967ed66f | ||
|
|
61f363e803 | ||
|
|
baa6745f45 | ||
|
|
7d93753451 | ||
|
|
76000424e1 | ||
|
|
a465d22390 | ||
|
|
31abba9e04 | ||
|
|
e9b2f724c6 | ||
|
|
4a7d95d8e9 | ||
|
|
d421708b5f | ||
|
|
f8c9349510 | ||
|
|
78759b9f15 | ||
|
|
2417eb4562 | ||
|
|
5857fab1f6 | ||
|
|
db4f09ffb8 | ||
|
|
128651de24 | ||
|
|
1cd3f977e4 | ||
|
|
b7393ab153 | ||
|
|
edee888662 | ||
|
|
7701841381 | ||
|
|
60aba187a7 | ||
|
|
012ada2e88 | ||
|
|
6e29b9f778 | ||
|
|
c19d5bb58e | ||
|
|
2d07c7abee | ||
|
|
311503ec46 | ||
|
|
bb37600c87 | ||
|
|
544befe162 | ||
|
|
285fab70b2 | ||
|
|
ac3ece01c7 | ||
|
|
ef0dad4ffc | ||
|
|
6ed34078fd | ||
|
|
cd50236b8a | ||
|
|
4d745ab65c | ||
|
|
f904fb1972 | ||
|
|
4003a8e548 | ||
|
|
0bd0cd2452 |
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -62,7 +62,7 @@ body:
|
|||
- type: input
|
||||
id: itsrevela
|
||||
attributes:
|
||||
label: Is this reproducable in itsRevela/LCE-Revelations? (https://github.com/itsRevela/LCE-Revelations)
|
||||
label: Is this reproducable in itsRevela/LCE-Revelations? (https://git.revela.dev/itsRevela/LCE-Revelations)
|
||||
description: If this was a "no idea" or similar, it will be rejected.
|
||||
validations:
|
||||
required: true
|
||||
|
|
|
|||
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;
|
||||
};
|
||||
|
|
@ -4323,22 +4323,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)
|
||||
|
|
|
|||
|
|
@ -56,8 +56,7 @@ enum EGameHostOptionWorldSize
|
|||
e_worldSize_Classic,
|
||||
e_worldSize_Small,
|
||||
e_worldSize_Medium,
|
||||
e_worldSize_Large,
|
||||
e_worldSize_Expanded
|
||||
e_worldSize_Large
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -916,7 +916,7 @@ void IUIScene_CraftingMenu::UpdateHighlight()
|
|||
|
||||
// special case for the torch coal/charcoal
|
||||
int id=pTempItemInstAdditional->getDescriptionId();
|
||||
LPCWSTR itemstring;
|
||||
wstring itemstring;
|
||||
|
||||
switch(id)
|
||||
{
|
||||
|
|
@ -945,11 +945,15 @@ void IUIScene_CraftingMenu::UpdateHighlight()
|
|||
}
|
||||
break;
|
||||
default:
|
||||
itemstring=app.GetString(id );
|
||||
if (pTempItemInstAdditional->hasCustomHoverName()) {
|
||||
itemstring = pTempItemInstAdditional->getHoverName();
|
||||
} else {
|
||||
itemstring = app.GetString(id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
setItemText(itemstring);
|
||||
setItemText(itemstring.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
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,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,15 @@ GuiParticles::GuiParticles(Minecraft *mc)
|
|||
this->mc = mc;
|
||||
}
|
||||
|
||||
GuiParticles::~GuiParticles()
|
||||
{
|
||||
for (GuiParticle *gp : particles)
|
||||
{
|
||||
delete gp;
|
||||
}
|
||||
particles.clear();
|
||||
}
|
||||
|
||||
void GuiParticles::tick()
|
||||
{
|
||||
for (unsigned int i = 0; i < particles.size(); i++)
|
||||
|
|
@ -19,6 +28,7 @@ void GuiParticles::tick()
|
|||
|
||||
if (gp->removed)
|
||||
{
|
||||
delete gp;
|
||||
particles.erase(particles.begin()+i);
|
||||
i--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ private:
|
|||
|
||||
public:
|
||||
GuiParticles(Minecraft *mc);
|
||||
~GuiParticles();
|
||||
void tick();
|
||||
void add(GuiParticle *guiParticle);
|
||||
void render(float a);
|
||||
|
|
|
|||
|
|
@ -555,7 +555,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)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,14 @@ public:
|
|||
int id;
|
||||
bool isLoaded;
|
||||
int ticksSinceLastUse;
|
||||
static const int UNUSED_TICKS_TO_FREE = 20;
|
||||
// @CDevJoud
|
||||
// changing the lifetime of the texture from 20 ticks(1 sec) to 200 ticks (10 sec)
|
||||
// as it helps the texture to have longer lifetime and reducing the usage of loadTexture for every second/frame
|
||||
// note that we dont remove the code that removes the textures from `tick()` as it is required in memory limited environment such as older Consoles(PS3/XBOX360)
|
||||
static const int UNUSED_TICKS_TO_FREE = 200;
|
||||
|
||||
//default ctor for int Texture::getHeight(const wstring& url, int backup)
|
||||
MemTexture() = default;
|
||||
|
||||
MemTexture(const wstring& _name, PBYTE pbData, DWORD dwBytes, MemTextureProcessor *processor);
|
||||
~MemTexture();
|
||||
|
|
|
|||
|
|
@ -526,9 +526,10 @@ LevelStorageSource *Minecraft::getLevelSource()
|
|||
|
||||
void Minecraft::setScreen(Screen *screen)
|
||||
{
|
||||
if (this->screen != nullptr)
|
||||
Screen *oldScreen = this->screen;
|
||||
if (oldScreen != nullptr)
|
||||
{
|
||||
this->screen->removed();
|
||||
oldScreen->removed();
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
|
|
@ -4438,6 +4439,8 @@ void Minecraft::setLevel(MultiPlayerLevel *level, int message /*=-1*/, shared_pt
|
|||
// 4J If we are setting the level to nullptr then we are exiting, so delete the levels
|
||||
if( level == nullptr )
|
||||
{
|
||||
if (soundEngine) soundEngine->stopElytraSound();
|
||||
|
||||
if(levels[0]!=nullptr)
|
||||
{
|
||||
delete levels[0];
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ MultiPlayerChunkCache::MultiPlayerChunkCache(Level *level)
|
|||
this->level = level;
|
||||
|
||||
this->cache = new LevelChunk *[XZSIZE * XZSIZE];
|
||||
memset(this->cache, 0, sizeof(LevelChunk*) * XZSIZE * XZSIZE);
|
||||
memset(this->cache, 0, XZSIZE * XZSIZE * sizeof(LevelChunk *));
|
||||
InitializeCriticalSectionAndSpinCount(&m_csLoadCreate,4000);
|
||||
}
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ bool MultiPlayerChunkCache::reallyHasChunk(int x, int z)
|
|||
int idx = ix * XZSIZE + iz;
|
||||
|
||||
LevelChunk *chunk = cache[idx];
|
||||
if (chunk == nullptr)
|
||||
if( chunk == nullptr )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -145,8 +145,7 @@ void MultiPlayerChunkCache::drop(const int x, const int z)
|
|||
const int iz = z + XZOFFSET;
|
||||
if ((ix < 0) || (ix >= XZSIZE)) return;
|
||||
if ((iz < 0) || (iz >= XZSIZE)) return;
|
||||
|
||||
int idx = ix * XZSIZE + iz;
|
||||
const int idx = ix * XZSIZE + iz;
|
||||
LevelChunk* chunk = cache[idx];
|
||||
|
||||
if (chunk != nullptr && !chunk->isEmpty())
|
||||
|
|
@ -170,7 +169,6 @@ LevelChunk *MultiPlayerChunkCache::create(int x, int z)
|
|||
if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk );
|
||||
if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk );
|
||||
int idx = ix * XZSIZE + iz;
|
||||
|
||||
LevelChunk *chunk = cache[idx];
|
||||
LevelChunk *lastChunk = chunk;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
|
|
@ -1868,6 +1926,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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,18 @@ Screen::Screen() // 4J added
|
|||
clickedButton = nullptr;
|
||||
}
|
||||
|
||||
Screen::~Screen()
|
||||
{
|
||||
delete particles;
|
||||
particles = nullptr;
|
||||
|
||||
for (Button *button : buttons)
|
||||
{
|
||||
delete button;
|
||||
}
|
||||
buttons.clear();
|
||||
}
|
||||
|
||||
void Screen::render(int xm, int ym, float a)
|
||||
{
|
||||
for (Button* button : buttons)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ public:
|
|||
GuiParticles *particles;
|
||||
|
||||
Screen(); // 4J added
|
||||
virtual ~Screen();
|
||||
virtual void render(int xm, int ym, float a);
|
||||
protected:
|
||||
virtual void keyPressed(wchar_t eventCharacter, int eventKey);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -138,12 +138,21 @@ private:
|
|||
// 4J - added for implementation of finite limit to number of item entities, tnt and falling block entities
|
||||
public:
|
||||
|
||||
static const int MAX_HANGING_ENTITIES = 400;
|
||||
static const int MAX_ITEM_ENTITIES = 200;
|
||||
static const int MAX_ARROW_ENTITIES = 200;
|
||||
static const int MAX_EXPERIENCEORB_ENTITIES = 50;
|
||||
static const int MAX_PRIMED_TNT = 20;
|
||||
static const int MAX_FALLING_TILE = 20;
|
||||
static const int MAX_HANGING_ENTITIES = 800;
|
||||
static const int MAX_ITEM_ENTITIES = 400;
|
||||
static const int MAX_ARROW_ENTITIES = 400;
|
||||
static const int MAX_EXPERIENCEORB_ENTITIES = 100;
|
||||
static const int MAX_PRIMED_TNT = 40;
|
||||
static const int MAX_FALLING_TILE = 40;
|
||||
|
||||
//static const int MAX_HANGING_ENTITIES = 400;
|
||||
//static const int MAX_ITEM_ENTITIES = 200;
|
||||
//static const int MAX_ARROW_ENTITIES = 200;
|
||||
//static const int MAX_EXPERIENCEORB_ENTITIES = 50;
|
||||
//static const int MAX_PRIMED_TNT = 20;
|
||||
//static const int MAX_FALLING_TILE = 20;
|
||||
|
||||
|
||||
|
||||
int m_primedTntCount;
|
||||
int m_fallingTileCount;
|
||||
|
|
|
|||
|
|
@ -850,8 +850,10 @@ void ServerPlayer::die(DamageSource *source)
|
|||
|
||||
bool ServerPlayer::hurt(DamageSource *dmgSource, float dmg)
|
||||
{
|
||||
if (isInvulnerable()) return false;
|
||||
if (gameMode == nullptr||gameMode->isCreative()) return false;
|
||||
if (isInvulnerable() && dmgSource != DamageSource::outOfWorld) return false;
|
||||
if (gameMode == nullptr || gameMode->isCreative()) {
|
||||
if (dmgSource != DamageSource::outOfWorld) return false;
|
||||
}
|
||||
|
||||
// 4J: Not relevant to console servers
|
||||
// Allow falldamage on dedicated pvpservers -- so people cannot cheat their way out of 'fall traps'
|
||||
|
|
|
|||
|
|
@ -1256,8 +1256,14 @@ int Textures::getHeight(const wstring& url, int backup)
|
|||
|
||||
if (img)
|
||||
{
|
||||
MemTexture* _texture = new MemTexture();
|
||||
_texture->loadedImage = img;
|
||||
_texture->isLoaded = true;
|
||||
_texture->id = getTexture(_texture->loadedImage, C4JRender::TEXTURE_FORMAT_RxGyBzAw, MIPMAP);
|
||||
|
||||
int h = img->getHeight();
|
||||
delete img;
|
||||
//delete img; // commenting this out and inserting the loaded texture to memTextures unordered_map
|
||||
this->memTextures[url] = _texture;
|
||||
return h;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -290,24 +290,53 @@ void TrackedEntity::tick(EntityTracker *tracker, vector<shared_ptr<Player> > *pl
|
|||
wasRiding = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool rot = abs(yRotn - yRotp) >= TOLERANCE_LEVEL || abs(xRotn - xRotp) >= TOLERANCE_LEVEL;
|
||||
if (rot)
|
||||
{
|
||||
// 4J: Changed this to use deltas
|
||||
broadcast(std::make_shared<MoveEntityPacket::Rot>(e->entityId, static_cast<byte>(yRota), static_cast<byte>(xRota)));
|
||||
yRotp = yRotn;
|
||||
xRotp = xRotn;
|
||||
}
|
||||
{
|
||||
// the entity have a rider, the code didnt send position updates,
|
||||
// causing desync between client and server when boat was spritning.
|
||||
|
||||
xp = Mth::floor(e->x * 32.0);
|
||||
yp = Mth::floor(e->y * 32.0);
|
||||
zp = Mth::floor(e->z * 32.0);
|
||||
bool rot = abs(yRotn - yRotp) >= TOLERANCE_LEVEL || abs(xRotn - xRotp) >= TOLERANCE_LEVEL;
|
||||
if (rot)
|
||||
{
|
||||
|
||||
broadcast(std::make_shared<MoveEntityPacket::Rot>(e->entityId, static_cast<byte>(yRota), static_cast<byte>(xRota)));
|
||||
yRotp = yRotn;
|
||||
xRotp = xRotn;
|
||||
}
|
||||
|
||||
sendDirtyEntityData();
|
||||
int xn = Mth::floor(e->x * 32.0);
|
||||
int yn = Mth::floor(e->y * 32.0);
|
||||
int zn = Mth::floor(e->z * 32.0);
|
||||
int xa = xn - xp;
|
||||
int ya = yn - yp;
|
||||
int za = zn - zp;
|
||||
|
||||
wasRiding = true;
|
||||
}
|
||||
// send only if the boat moved enough
|
||||
// or 3 seconds periodically
|
||||
bool pos = abs(xa) >= TOLERANCE_LEVEL || abs(ya) >= TOLERANCE_LEVEL || abs(za) >= TOLERANCE_LEVEL
|
||||
|| (tickCount % (SharedConstants::TICKS_PER_SECOND * 3) == 0);
|
||||
|
||||
if (pos)
|
||||
{
|
||||
// if deltapos is too much big use teleport.
|
||||
if (xa < -128 || xa >= 128 || ya < -128 || ya >= 128 || za < -128 || za >= 128)
|
||||
{
|
||||
broadcast(std::make_shared<TeleportEntityPacket>(e->entityId, xn, yn, zn,
|
||||
static_cast<byte>(yRotn), static_cast<byte>(xRotn)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// small movement, delta
|
||||
broadcast(std::make_shared<MoveEntityPacket::Pos>(e->entityId,
|
||||
static_cast<char>(xa), static_cast<char>(ya), static_cast<char>(za)));
|
||||
}
|
||||
xp = xn;
|
||||
yp = yn;
|
||||
zp = zn;
|
||||
}
|
||||
|
||||
sendDirtyEntityData();
|
||||
wasRiding = true;
|
||||
}
|
||||
|
||||
int yHeadRot = Mth::floor(e->getYHeadRot() * 256 / 360);
|
||||
if (abs(yHeadRot - yHeadRotp) >= TOLERANCE_LEVEL)
|
||||
|
|
|
|||
|
|
@ -149,47 +149,57 @@ static void CopyWideArgToAnsi(LPCWSTR source, char* dest, size_t destSize)
|
|||
dest[destSize - 1] = 0;
|
||||
}
|
||||
|
||||
// ---------- Persistent options (options.txt next to exe) ----------
|
||||
static void GetOptionsFilePath(char *out, size_t outSize)
|
||||
// ---------- Persistent options (options.dat next to exe) ----------
|
||||
static void GetOptionsFilePath(char *out, DWORD outSize)
|
||||
{
|
||||
GetModuleFileNameA(nullptr, out, static_cast<DWORD>(outSize));
|
||||
char *p = strrchr(out, '\\');
|
||||
if (p) *(p + 1) = '\0';
|
||||
strncat_s(out, outSize, "options.txt", _TRUNCATE);
|
||||
GetModuleFileNameA(nullptr, out, outSize);
|
||||
char *p = strrchr(out, '\\');
|
||||
if (p) *(p + 1) = '\0';
|
||||
strncat_s(out, outSize, "settings.dat", _TRUNCATE);
|
||||
}
|
||||
|
||||
static void SaveFullscreenOption(bool fullscreen)
|
||||
{
|
||||
char path[MAX_PATH];
|
||||
GetOptionsFilePath(path, sizeof(path));
|
||||
FILE *f = nullptr;
|
||||
if (fopen_s(&f, path, "w") == 0 && f)
|
||||
{
|
||||
fprintf(f, "fullscreen=%d\n", fullscreen ? 1 : 0);
|
||||
fclose(f);
|
||||
}
|
||||
GAME_SETTINGS settings = {};
|
||||
|
||||
char path[MAX_PATH] = {};
|
||||
GetOptionsFilePath(path, MAX_PATH);
|
||||
FILE *f = nullptr;
|
||||
if (fopen_s(&f, path, "rb") == 0 && f)
|
||||
{
|
||||
fread(&settings, sizeof(GAME_SETTINGS), 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
if (fullscreen)
|
||||
settings.uiBitmaskValues |= (1UL << 25);
|
||||
else
|
||||
settings.uiBitmaskValues &= ~(1UL << 25);
|
||||
|
||||
if (fopen_s(&f, path, "wb") == 0 && f)
|
||||
{
|
||||
fwrite(&settings, sizeof(GAME_SETTINGS), 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
static bool LoadFullscreenOption()
|
||||
{
|
||||
char path[MAX_PATH];
|
||||
char path[MAX_PATH] = {};
|
||||
GetOptionsFilePath(path, sizeof(path));
|
||||
FILE *f = nullptr;
|
||||
if (fopen_s(&f, path, "r") == 0 && f)
|
||||
{
|
||||
char line[256];
|
||||
while (fgets(line, sizeof(line), f))
|
||||
{
|
||||
int val = 0;
|
||||
if (sscanf_s(line, "fullscreen=%d", &val) == 1)
|
||||
{
|
||||
fclose(f);
|
||||
return val != 0;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
return false;
|
||||
|
||||
FILE *f = nullptr;
|
||||
if (fopen_s(&f, path, "rb") != 0 || !f)
|
||||
return false;
|
||||
|
||||
GAME_SETTINGS current = {};
|
||||
bool ok = (fread(¤t, sizeof(GAME_SETTINGS), 1, f) == 1);
|
||||
fclose(f);
|
||||
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
return (current.uiBitmaskValues & (1UL << 25)) != 0;
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
|
|
@ -824,8 +834,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
ShowWindow(g_hWnd, (nCmdShow != SW_HIDE) ? SW_SHOWMAXIMIZED : nCmdShow);
|
||||
UpdateWindow(g_hWnd);
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1456,8 +1465,9 @@ void CleanupDevice()
|
|||
static Minecraft* InitialiseMinecraftRuntime()
|
||||
{
|
||||
app.loadMediaArchive();
|
||||
|
||||
RenderManager.Initialise(g_pd3dDevice, g_pSwapChain);
|
||||
// @CDevJoud: No need to call this method as it gets called once in `InitDevice()`
|
||||
// Calling it again and it results of 20MB of memory leak!
|
||||
//RenderManager.Initialise(g_pd3dDevice, g_pSwapChain);
|
||||
|
||||
app.loadStringTable();
|
||||
ui.init(g_pd3dDevice, g_pImmediateContext, g_pRenderTargetView, g_pDepthStencilView, g_rScreenWidth, g_rScreenHeight);
|
||||
|
|
@ -1695,11 +1705,12 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
|||
CleanupDevice();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Restore fullscreen state from previous session. Route through the
|
||||
// deferred exclusive fullscreen path so the main loop applies it on the
|
||||
// first tick (safer than transitioning during init).
|
||||
if ((LoadFullscreenOption() && !g_isFullscreen) || launchOptions.fullscreen)
|
||||
|
||||
bool FullScreenEnabled = LoadFullscreenOption();
|
||||
if (FullScreenEnabled && !g_isFullscreen)
|
||||
{
|
||||
g_bPendingExclusiveFullscreen = true;
|
||||
g_bPendingExclusiveFullscreenValue = true;
|
||||
|
|
@ -1764,7 +1775,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
|||
return 1;
|
||||
}
|
||||
g_bResizeReady = true;
|
||||
|
||||
|
||||
//app.TemporaryCreateGameStart();
|
||||
|
||||
//Sleep(10000);
|
||||
|
|
@ -1790,6 +1801,20 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
|||
hr = XuiTimersRun();
|
||||
}
|
||||
#endif
|
||||
|
||||
// @CDevJoud The window should only be shown after the engine/game
|
||||
// initialization has fully completed.
|
||||
//
|
||||
// Showing the window too early especially on low end devices,
|
||||
// may cause windows to display a "Not Responding" state while
|
||||
// initialization is still in progress.
|
||||
//
|
||||
// This creates an unprofessional first impression for the player.
|
||||
// Instead, initialize all engine systems first, then display the
|
||||
// window once everything is ready.
|
||||
ShowWindow(g_hWnd, (nCmdShow != SW_HIDE) ? SW_SHOWMAXIMIZED : nCmdShow);
|
||||
UpdateWindow(g_hWnd);
|
||||
|
||||
MSG msg = {0};
|
||||
while( WM_QUIT != msg.message && !app.m_bShutdown)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -628,8 +628,6 @@ static std::string WorldSizeToPropertyValue(int worldSize)
|
|||
return "medium";
|
||||
case e_worldSize_Large:
|
||||
return "large";
|
||||
case e_worldSize_Expanded:
|
||||
return "expanded";
|
||||
case e_worldSize_Classic:
|
||||
default:
|
||||
return "classic";
|
||||
|
|
@ -646,8 +644,6 @@ static int WorldSizeToXzChunks(int worldSize)
|
|||
return LEVEL_WIDTH_MEDIUM;
|
||||
case e_worldSize_Large:
|
||||
return LEVEL_WIDTH_LARGE;
|
||||
case e_worldSize_Expanded:
|
||||
return LEVEL_WIDTH_EXPANDED;
|
||||
case e_worldSize_Classic:
|
||||
default:
|
||||
return LEVEL_WIDTH_CLASSIC;
|
||||
|
|
@ -663,7 +659,6 @@ static int WorldSizeToHellScale(int worldSize)
|
|||
case e_worldSize_Medium:
|
||||
return HELL_LEVEL_SCALE_MEDIUM;
|
||||
case e_worldSize_Large:
|
||||
case e_worldSize_Expanded:
|
||||
return HELL_LEVEL_SCALE_LARGE;
|
||||
case e_worldSize_Classic:
|
||||
default:
|
||||
|
|
@ -699,12 +694,6 @@ static bool TryParseWorldSize(const std::string &lowered, int *outWorldSize)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (lowered == "expanded" || lowered == "344" || lowered == "8")
|
||||
{
|
||||
*outWorldSize = e_worldSize_Expanded;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,10 +54,16 @@ AABB *AABB::newPermanent(double x0, double y0, double z0, double x1, double y1,
|
|||
|
||||
void AABB::clearPool()
|
||||
{
|
||||
ThreadStorage *tls = static_cast<ThreadStorage *>(TlsGetValue(tlsIdx));
|
||||
if (tls != nullptr)
|
||||
{
|
||||
tls->poolPointer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AABB::resetPool()
|
||||
{
|
||||
clearPool();
|
||||
}
|
||||
|
||||
AABB *AABB::newTemp(double x0, double y0, double z0, double x1, double y1, double z1)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
const BlockPos BlockPos::ZERO = BlockPos(0, 0, 0);
|
||||
|
||||
// Costruttori
|
||||
|
||||
BlockPos::BlockPos() : Vec3i(0, 0, 0) {}
|
||||
|
||||
BlockPos::BlockPos(int x, int y, int z) : Vec3i(x, y, z) {}
|
||||
|
|
@ -49,7 +49,7 @@ BlockPos::BlockPos(int compressed) : Vec3i(0, 0, 0) {
|
|||
BlockPos::BlockPos(BlockSource& source)
|
||||
: Vec3i(source.getBlockX(), source.getBlockY(), source.getBlockZ()) {}
|
||||
|
||||
// Metodi di confronto
|
||||
|
||||
bool BlockPos::equals(const BlockPos& other) const {
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
|
|
@ -88,7 +88,7 @@ BlockPos BlockPos::relative(int direction, int distance) const {
|
|||
return BlockPos(x + dx, y, z + dz);
|
||||
}
|
||||
|
||||
// Metodi direzionali
|
||||
// directional methods
|
||||
BlockPos BlockPos::above(int distance) const {
|
||||
return BlockPos(x, y + distance, z);
|
||||
}
|
||||
|
|
@ -119,7 +119,7 @@ BlockPos BlockPos::multiply(int factor) const {
|
|||
return BlockPos(x * factor, y * factor, z * factor);
|
||||
}
|
||||
|
||||
// Compressione
|
||||
// compression
|
||||
int BlockPos::compress() const {
|
||||
static const int MASK_X = (1 << BITS_X) - 1;
|
||||
static const int MASK_Y = (1 << BITS_Y) - 1;
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ void Boat::lerpTo(double x, double y, double z, float yRot, float xRot, int step
|
|||
{
|
||||
if (doLerp)
|
||||
{
|
||||
lSteps = steps + 5;
|
||||
lSteps = steps +5;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -188,6 +188,10 @@ void Boat::lerpMotion(double xd, double yd, double zd)
|
|||
void Boat::tick()
|
||||
{
|
||||
Entity::tick();
|
||||
|
||||
|
||||
|
||||
|
||||
if (getHurtTime() > 0) setHurtTime(getHurtTime() - 1);
|
||||
if (getDamage() > 0) setDamage(getDamage() - 1);
|
||||
xo = x;
|
||||
|
|
@ -199,8 +203,8 @@ void Boat::tick()
|
|||
double waterPercentage = 0;
|
||||
for (int i = 0; i < steps; i++)
|
||||
{
|
||||
double y0 = bb->y0 + (bb->y1 - bb->y0) * (i + 0) / steps - 2 / 16.0f;
|
||||
double y1 = bb->y0 + (bb->y1 - bb->y0) * (i + 1) / steps - 2 / 16.0f;
|
||||
double y0 = bb->y0 + (bb->y1 - bb->y0) * (i + 0) / steps + 1.5f / 16.0f;
|
||||
double y1 = bb->y0 + (bb->y1 - bb->y0) * (i + 1) / steps + 1.5f / 16.0f;
|
||||
AABB *bb2 = AABB::newTemp(bb->x0, y0, bb->z0, bb->x1, y1, bb->z1);
|
||||
if (level->containsLiquid(bb2, Material::water))
|
||||
{
|
||||
|
|
@ -257,18 +261,19 @@ void Boat::tick()
|
|||
return;
|
||||
}
|
||||
|
||||
// Bob in water
|
||||
if (waterPercentage > 0)
|
||||
// Bob in water & gravity
|
||||
if (waterPercentage < 1.0)
|
||||
{
|
||||
double bob = waterPercentage * 2 - 1;
|
||||
double bob = waterPercentage * 2.0 - 1.0;
|
||||
yd += 0.04f * bob;
|
||||
}
|
||||
|
||||
// Reimplement gravity again (??)
|
||||
int tileUnder = level->getTile(Mth::floor(x), Mth::floor(y-0.15), Mth::floor(z));
|
||||
if (tileUnder == 0 && !onGround)
|
||||
else
|
||||
{
|
||||
yd -= 0.04f;
|
||||
if (yd < 0.0)
|
||||
{
|
||||
yd /= 2.0;
|
||||
}
|
||||
yd += 0.007f;
|
||||
}
|
||||
|
||||
// Rider controls
|
||||
|
|
@ -281,24 +286,16 @@ void Boat::tick()
|
|||
{
|
||||
double riderXd = -sin(livingRider->yRot * PI / 180);
|
||||
double riderZd = cos(livingRider->yRot * PI / 180);
|
||||
float mult = livingRider->isSprinting() ? 2.0f : 1.0f;
|
||||
double currentSpeed = sqrt(xd * xd + zd * zd);
|
||||
float moveFactor = (float)forward;
|
||||
if (forward < 0) moveFactor *= 0.5f; // Move slower backwards
|
||||
xd += riderXd * acceleration * 0.05f * mult * moveFactor;
|
||||
zd += riderZd * acceleration * 0.05f * mult * moveFactor;
|
||||
xd += riderXd * acceleration * 0.05f * moveFactor;
|
||||
zd += riderZd * acceleration * 0.05f * moveFactor;
|
||||
}
|
||||
}
|
||||
|
||||
double curSpeed = sqrt(xd * xd + zd * zd);
|
||||
double maxSpeed = MAX_SPEED;
|
||||
if (rider.lock() != nullptr && rider.lock()->instanceof(eTYPE_LIVINGENTITY))
|
||||
{
|
||||
shared_ptr<LivingEntity> livingRider = dynamic_pointer_cast<LivingEntity>(rider.lock());
|
||||
if (livingRider->isSprinting())
|
||||
{
|
||||
maxSpeed *= 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
if (curSpeed > maxSpeed)
|
||||
{
|
||||
|
|
@ -330,10 +327,12 @@ void Boat::tick()
|
|||
move(xd, yd, zd);
|
||||
|
||||
// Break boat on high speed collision
|
||||
float breakThreshold = (rider.lock() != nullptr) ? 0.35f : 0.20f;
|
||||
if ((horizontalCollision && lastSpeed > 0.20))
|
||||
{
|
||||
if (!level->isClientSide && !removed)
|
||||
{
|
||||
|
||||
remove();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
|
|
@ -343,6 +342,9 @@ void Boat::tick()
|
|||
{
|
||||
spawnAtLocation(Item::stick->id, 1, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -472,10 +474,19 @@ bool Boat::interact(shared_ptr<Player> player)
|
|||
if ( (rider.lock() != nullptr) && rider.lock()->instanceof(eTYPE_PLAYER) && (rider.lock() != player) ) return true;
|
||||
if (!level->isClientSide)
|
||||
{
|
||||
bool isRiding = (rider.lock() == player);
|
||||
|
||||
if (isRiding)
|
||||
{
|
||||
|
||||
player->xd = 0;
|
||||
player->yd = 0;
|
||||
player->zd = 0;
|
||||
}
|
||||
// 4J HEG - Fixed issue with player not being able to dismount boat (issue #4446)
|
||||
player->ride( rider.lock() == player ? nullptr : shared_from_this() );
|
||||
}
|
||||
return true;
|
||||
player->ride(isRiding ? nullptr : shared_from_this());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Boat::setDamage(float damage)
|
||||
|
|
|
|||
|
|
@ -7,14 +7,12 @@ class TilePos;
|
|||
// The maximum number of chunks that we can store
|
||||
#ifdef _LARGE_WORLDS
|
||||
// 4J Stu - Our default map (at zoom level 3) is 1024x1024 blocks (or 64 chunks)
|
||||
#define LEVEL_MAX_WIDTH (5*64) //(6*54)
|
||||
|
||||
#define LEVEL_WIDTH_CLASSIC 54
|
||||
#define LEVEL_WIDTH_SMALL 64
|
||||
#define LEVEL_WIDTH_MEDIUM (3*64)
|
||||
#define LEVEL_WIDTH_LARGE (5*64)
|
||||
#define LEVEL_WIDTH_EXPANDED (5*64) + 24
|
||||
|
||||
|
||||
#define LEVEL_MAX_WIDTH LEVEL_WIDTH_EXPANDED
|
||||
|
||||
#else
|
||||
#define LEVEL_MAX_WIDTH 54
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ void ClothDyeRecipes::addRecipes(Recipes *r)
|
|||
}
|
||||
|
||||
// some dye recipes
|
||||
|
||||
//flowers
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::YELLOW),
|
||||
L"tg",
|
||||
Tile::flower,L'D');
|
||||
|
|
@ -46,6 +48,44 @@ void ClothDyeRecipes::addRecipes(Recipes *r)
|
|||
L"tg",
|
||||
Tile::rose,L'D');
|
||||
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::LIGHT_BLUE),
|
||||
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::BLUE_ORCHID), L'D');
|
||||
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::MAGENTA),
|
||||
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::ALLIUM), L'D');
|
||||
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::SILVER),
|
||||
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::AZURE_BLUET), L'D');
|
||||
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::RED),
|
||||
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::RED_TULIP), L'D');
|
||||
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::PINK),
|
||||
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::PINK_TULIP), L'D');
|
||||
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::SILVER),
|
||||
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::WHITE_TULIP), L'D');
|
||||
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::ORANGE),
|
||||
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::ORANGE_TULIP), L'D');
|
||||
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::SILVER),
|
||||
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::OXEYE_DAISY), L'D');
|
||||
|
||||
// Tall flowers
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 2, DyePowderItem::YELLOW),
|
||||
L"zg", new ItemInstance(Item::items[Tile::tallgrass2_Id], 1, TallGrass2::SUNFLOWER), L'D');
|
||||
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 2, DyePowderItem::MAGENTA),
|
||||
L"zg", new ItemInstance(Item::items[Tile::tallgrass2_Id], 1, TallGrass2::LILAC), L'D');
|
||||
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 2, DyePowderItem::RED),
|
||||
L"zg", new ItemInstance(Item::items[Tile::tallgrass2_Id], 1, TallGrass2::ROSE_BUSH), L'D');
|
||||
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 2, DyePowderItem::MAGENTA),
|
||||
L"zg", new ItemInstance(Item::items[Tile::tallgrass2_Id], 1, TallGrass2::PEONY), L'D');
|
||||
|
||||
|
||||
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 3, DyePowderItem::WHITE),
|
||||
L"ig",
|
||||
Item::bone,L'D');
|
||||
|
|
@ -114,6 +154,9 @@ void ClothDyeRecipes::addRecipes(Recipes *r)
|
|||
new ItemInstance(Item::dye_powder, 1, DyePowderItem::RED),
|
||||
new ItemInstance(Item::dye_powder, 1, DyePowderItem::WHITE),L'D');
|
||||
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
r->addShapedRecipy(new ItemInstance(Tile::woolCarpet, 3, i),
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
};
|
||||
|
|
@ -121,8 +121,14 @@ void GrassTile::tick(Level *level, int x, int y, int z, Random *random)
|
|||
}
|
||||
}
|
||||
|
||||
// using isSolid() here is wrong because non full blocks like iron bars,
|
||||
// fences, walls are also flagged as solid by their material
|
||||
int aboveTileId = level->getTile(x, y + 1, z);
|
||||
Material* above = level->getMaterial(x, y + 1, z);
|
||||
if (above->isSolid() || above->isLiquid()) level->setTileAndUpdate(x, y, z, Tile::dirt_Id);
|
||||
if (above->isLiquid() || Tile::lightBlock[aboveTileId] > 2)
|
||||
{
|
||||
level->setTileAndUpdate(x, y, z, Tile::dirt_Id);
|
||||
}
|
||||
}
|
||||
|
||||
int GrassTile::getResource(int data, Random *random, int playerBonusLevel)
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
|
|
@ -46,7 +46,6 @@ DWORD Level::tlsIdxLightCache = TlsAlloc();
|
|||
|
||||
// 4J : WESTY : Added for time played stats.
|
||||
#include "net.minecraft.stats.h"
|
||||
#include "../Minecraft.Client/MultiPlayerChunkCache.h"
|
||||
|
||||
// 4J - Caching of lighting data added. This is implemented as a 16x16x16 cache of ints (ie 16K storage in total). The index of the element to be used in the array is determined by the lower
|
||||
// four bits of each x/y/z position, and the upper 7/4/7 bits of the x/y/z positions are stored within the element itself along with the cached values etc. The cache can be enabled per thread by
|
||||
|
|
@ -1336,7 +1335,7 @@ int Level::getBrightness(LightLayer::variety layer, int x, int y, int z)
|
|||
int idx = ix * chunkSourceXZSize + iz;
|
||||
LevelChunk *c = chunkSourceCache[idx];
|
||||
|
||||
if( c == nullptr) return (int)layer;
|
||||
if( c == nullptr ) return (int)layer;
|
||||
|
||||
if (y < 0) y = 0;
|
||||
if (y >= maxBuildHeight) y = maxBuildHeight - 1;
|
||||
|
|
|
|||
|
|
@ -185,7 +185,6 @@ LevelData::LevelData(CompoundTag *tag)
|
|||
case LEVEL_WIDTH_SMALL: hostOptionworldSize = e_worldSize_Small; break;
|
||||
case LEVEL_WIDTH_MEDIUM: hostOptionworldSize = e_worldSize_Medium; break;
|
||||
case LEVEL_WIDTH_LARGE: hostOptionworldSize = e_worldSize_Large; break;
|
||||
case LEVEL_WIDTH_EXPANDED: hostOptionworldSize = e_worldSize_Expanded; break;
|
||||
default: assert(0); break;
|
||||
}
|
||||
app.SetGameHostOption(eGameHostOption_WorldSize, hostOptionworldSize );
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -63,18 +63,18 @@ void MobCategory::setMaxInstancesPerLevel(int max)
|
|||
m_maxPerLevel = max;
|
||||
}
|
||||
|
||||
int MobCategory::maxAnimalsWithBreeding() { return creature->getMaxInstancesPerLevel() + 20; }
|
||||
int MobCategory::maxChickensWithBreeding() { return creature_chicken->getMaxInstancesPerLevel() + 8; }
|
||||
int MobCategory::maxMushroomCowsWithBreeding() { return creature_mushroomcow->getMaxInstancesPerLevel() + 20; }
|
||||
int MobCategory::maxWolvesWithBreeding() { return creature_wolf->getMaxInstancesPerLevel() + 8; }
|
||||
int MobCategory::maxAnimalsWithBreeding() { return (creature->getMaxInstancesPerLevel() + 20)*2; }
|
||||
int MobCategory::maxChickensWithBreeding() { return (creature_chicken->getMaxInstancesPerLevel() + 8)*2; }
|
||||
int MobCategory::maxMushroomCowsWithBreeding() { return (creature_mushroomcow->getMaxInstancesPerLevel() + 20)*2; }
|
||||
int MobCategory::maxWolvesWithBreeding() { return (creature_wolf->getMaxInstancesPerLevel() + 8)*2; }
|
||||
|
||||
int MobCategory::maxAnimalsWithSpawnEgg() { return maxAnimalsWithBreeding() + 20; }
|
||||
int MobCategory::maxChickensWithSpawnEgg() { return maxChickensWithBreeding() + 10; }
|
||||
int MobCategory::maxWolvesWithSpawnEgg() { return maxWolvesWithBreeding() + 10; }
|
||||
int MobCategory::maxMonstersWithSpawnEgg() { return monster->getMaxInstancesPerLevel() + 20; }
|
||||
int MobCategory::maxMushroomCowsWithSpawnEgg() { return maxMushroomCowsWithBreeding() + 8; }
|
||||
int MobCategory::maxSquidsWithSpawnEgg() { return waterCreature->getMaxInstancesPerLevel() + 8; }
|
||||
int MobCategory::maxAmbientWithSpawnEgg() { return ambient->getMaxInstancesPerLevel() + 8; }
|
||||
int MobCategory::maxAnimalsWithSpawnEgg() { return (maxAnimalsWithBreeding() + 20)*2; }
|
||||
int MobCategory::maxChickensWithSpawnEgg() { return (maxChickensWithBreeding() + 10)*2; }
|
||||
int MobCategory::maxWolvesWithSpawnEgg() { return (maxWolvesWithBreeding() + 10)*2; }
|
||||
int MobCategory::maxMonstersWithSpawnEgg() { return (monster->getMaxInstancesPerLevel() + 20)*2; }
|
||||
int MobCategory::maxMushroomCowsWithSpawnEgg() { return (maxMushroomCowsWithBreeding() + 8)*2; }
|
||||
int MobCategory::maxSquidsWithSpawnEgg() { return (waterCreature->getMaxInstancesPerLevel() + 8)*2; }
|
||||
int MobCategory::maxAmbientWithSpawnEgg() { return (ambient->getMaxInstancesPerLevel() + 8)*2; }
|
||||
|
||||
Material *MobCategory::getSpawnPositionMaterial()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ class MobCategory
|
|||
{
|
||||
public:
|
||||
// 4J - putting constants for xbox spawning in one place to tidy things up a bit - all numbers are per level
|
||||
static const int CONSOLE_MONSTERS_HARD_LIMIT = 50; // Max number of enemies (skeleton, zombie, creeper etc) that the mob spawner will produce
|
||||
static const int CONSOLE_ANIMALS_HARD_LIMIT = 50; // Max number of animals (cows, sheep, pigs) that the mob spawner will produce
|
||||
static const int CONSOLE_AMBIENT_HARD_LIMIT = 20; // Ambient mobs
|
||||
static const int CONSOLE_MONSTERS_HARD_LIMIT = 100; // Max number of enemies (skeleton, zombie, creeper etc) that the mob spawner will produce
|
||||
static const int CONSOLE_ANIMALS_HARD_LIMIT = 100; // Max number of animals (cows, sheep, pigs) that the mob spawner will produce
|
||||
static const int CONSOLE_AMBIENT_HARD_LIMIT = 40; // Ambient mobs
|
||||
|
||||
static const int MAX_XBOX_CHICKENS = 8; // Max number of chickens that the mob spawner will produce
|
||||
static const int MAX_XBOX_WOLVES = 8; // Max number of wolves that the mob spawner will produce
|
||||
|
|
@ -20,7 +20,7 @@ public:
|
|||
static const int MAX_CONSOLE_BOSS = 1; // Max number of bosses (enderdragon/wither)
|
||||
|
||||
// 4J Villager breeding/egg limits - villagers are not a MobCategory so these stay hardcoded
|
||||
static const int MAX_VILLAGERS_WITH_BREEDING = 35;
|
||||
static const int MAX_VILLAGERS_WITH_BREEDING = 70;
|
||||
static const int MAX_XBOX_VILLAGERS_WITH_SPAWN_EGG = MAX_VILLAGERS_WITH_BREEDING + 15;
|
||||
|
||||
// Breeding headroom above the natural spawn cap. Read at call time so these
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -49,10 +49,16 @@ Vec3 *Vec3::newPermanent(double x, double y, double z)
|
|||
|
||||
void Vec3::clearPool()
|
||||
{
|
||||
ThreadStorage *tls = static_cast<ThreadStorage *>(TlsGetValue(tlsIdx));
|
||||
if (tls != nullptr)
|
||||
{
|
||||
tls->poolPointer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Vec3::resetPool()
|
||||
{
|
||||
clearPool();
|
||||
}
|
||||
|
||||
Vec3 *Vec3::newTemp(double x, double y, double z)
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
||||
|
|
|
|||
15
NOTES.md
15
NOTES.md
|
|
@ -1,7 +1,18 @@
|
|||
# neoLegacy v1.0.5b
|
||||
# neoLegacy v1.0.8b
|
||||
|
||||
### Bug Fixes
|
||||
- Fixed crashing, lagging, and lighting issues caused by expanded world generation.
|
||||
- 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