Merge branch 'main' into pr/win64-world-saves
# Conflicts: # Minecraft.Client/MinecraftServer.cpp # README.md
This commit is contained in:
@@ -49,7 +49,7 @@ void AABB::ReleaseThreadStorage()
|
||||
|
||||
AABB *AABB::newPermanent(double x0, double y0, double z0, double x1, double y1, double z1)
|
||||
{
|
||||
return new AABB(x0, y0, z0, x1, y1, z1);
|
||||
return new AABB(x0, y0, z0, x1, y1, z1);
|
||||
}
|
||||
|
||||
void AABB::clearPool()
|
||||
@@ -66,277 +66,289 @@ AABB *AABB::newTemp(double x0, double y0, double z0, double x1, double y1, doubl
|
||||
AABB *thisAABB = &tls->pool[tls->poolPointer];
|
||||
thisAABB->set(x0, y0, z0, x1, y1, z1);
|
||||
tls->poolPointer = ( tls->poolPointer + 1 ) % ThreadStorage::POOL_SIZE;
|
||||
return thisAABB;
|
||||
return thisAABB;
|
||||
}
|
||||
|
||||
AABB::AABB(double x0, double y0, double z0, double x1, double y1, double z1)
|
||||
{
|
||||
this->x0 = x0;
|
||||
this->y0 = y0;
|
||||
this->z0 = z0;
|
||||
this->x1 = x1;
|
||||
this->y1 = y1;
|
||||
this->z1 = z1;
|
||||
this->x0 = x0;
|
||||
this->y0 = y0;
|
||||
this->z0 = z0;
|
||||
this->x1 = x1;
|
||||
this->y1 = y1;
|
||||
this->z1 = z1;
|
||||
}
|
||||
|
||||
|
||||
AABB *AABB::set(double x0, double y0, double z0, double x1, double y1, double z1)
|
||||
{
|
||||
this->x0 = x0;
|
||||
this->y0 = y0;
|
||||
this->z0 = z0;
|
||||
this->x1 = x1;
|
||||
this->y1 = y1;
|
||||
this->z1 = z1;
|
||||
return this;
|
||||
this->x0 = x0;
|
||||
this->y0 = y0;
|
||||
this->z0 = z0;
|
||||
this->x1 = x1;
|
||||
this->y1 = y1;
|
||||
this->z1 = z1;
|
||||
return this;
|
||||
}
|
||||
|
||||
AABB *AABB::expand(double xa, double ya, double za)
|
||||
{
|
||||
double _x0 = x0;
|
||||
double _y0 = y0;
|
||||
double _z0 = z0;
|
||||
double _x1 = x1;
|
||||
double _y1 = y1;
|
||||
double _z1 = z1;
|
||||
double _x0 = x0;
|
||||
double _y0 = y0;
|
||||
double _z0 = z0;
|
||||
double _x1 = x1;
|
||||
double _y1 = y1;
|
||||
double _z1 = z1;
|
||||
|
||||
if (xa < 0) _x0 += xa;
|
||||
if (xa > 0) _x1 += xa;
|
||||
if (xa < 0) _x0 += xa;
|
||||
if (xa > 0) _x1 += xa;
|
||||
|
||||
if (ya < 0) _y0 += ya;
|
||||
if (ya > 0) _y1 += ya;
|
||||
if (ya < 0) _y0 += ya;
|
||||
if (ya > 0) _y1 += ya;
|
||||
|
||||
if (za < 0) _z0 += za;
|
||||
if (za > 0) _z1 += za;
|
||||
if (za < 0) _z0 += za;
|
||||
if (za > 0) _z1 += za;
|
||||
|
||||
return AABB::newTemp(_x0, _y0, _z0, _x1, _y1, _z1);
|
||||
return AABB::newTemp(_x0, _y0, _z0, _x1, _y1, _z1);
|
||||
}
|
||||
|
||||
AABB *AABB::grow(double xa, double ya, double za)
|
||||
{
|
||||
double _x0 = x0 - xa;
|
||||
double _y0 = y0 - ya;
|
||||
double _z0 = z0 - za;
|
||||
double _x1 = x1 + xa;
|
||||
double _y1 = y1 + ya;
|
||||
double _z1 = z1 + za;
|
||||
double _x0 = x0 - xa;
|
||||
double _y0 = y0 - ya;
|
||||
double _z0 = z0 - za;
|
||||
double _x1 = x1 + xa;
|
||||
double _y1 = y1 + ya;
|
||||
double _z1 = z1 + za;
|
||||
|
||||
return AABB::newTemp(_x0, _y0, _z0, _x1, _y1, _z1);
|
||||
return AABB::newTemp(_x0, _y0, _z0, _x1, _y1, _z1);
|
||||
}
|
||||
|
||||
AABB *AABB::minmax(AABB *other)
|
||||
{
|
||||
double _x0 = min(x0, other->x0);
|
||||
double _y0 = min(y0, other->y0);
|
||||
double _z0 = min(z0, other->z0);
|
||||
double _x1 = max(x1, other->x1);
|
||||
double _y1 = max(y1, other->y1);
|
||||
double _z1 = max(z1, other->z1);
|
||||
|
||||
return newTemp(_x0, _y0, _z0, _x1, _y1, _z1);
|
||||
}
|
||||
|
||||
AABB *AABB::cloneMove(double xa, double ya, double za)
|
||||
{
|
||||
return AABB::newTemp(x0 + xa, y0 + ya, z0 + za, x1 + xa, y1 + ya, z1 + za);
|
||||
return AABB::newTemp(x0 + xa, y0 + ya, z0 + za, x1 + xa, y1 + ya, z1 + za);
|
||||
}
|
||||
|
||||
double AABB::clipXCollide(AABB *c, double xa)
|
||||
{
|
||||
if (c->y1 <= y0 || c->y0 >= y1) return xa;
|
||||
if (c->z1 <= z0 || c->z0 >= z1) return xa;
|
||||
if (c->y1 <= y0 || c->y0 >= y1) return xa;
|
||||
if (c->z1 <= z0 || c->z0 >= z1) return xa;
|
||||
|
||||
if (xa > 0 && c->x1 <= x0)
|
||||
if (xa > 0 && c->x1 <= x0)
|
||||
{
|
||||
double max = x0 - c->x1;
|
||||
if (max < xa) xa = max;
|
||||
}
|
||||
if (xa < 0 && c->x0 >= x1)
|
||||
double max = x0 - c->x1;
|
||||
if (max < xa) xa = max;
|
||||
}
|
||||
if (xa < 0 && c->x0 >= x1)
|
||||
{
|
||||
double max = x1 - c->x0;
|
||||
if (max > xa) xa = max;
|
||||
}
|
||||
double max = x1 - c->x0;
|
||||
if (max > xa) xa = max;
|
||||
}
|
||||
|
||||
return xa;
|
||||
return xa;
|
||||
}
|
||||
|
||||
double AABB::clipYCollide(AABB *c, double ya)
|
||||
{
|
||||
if (c->x1 <= x0 || c->x0 >= x1) return ya;
|
||||
if (c->z1 <= z0 || c->z0 >= z1) return ya;
|
||||
if (c->x1 <= x0 || c->x0 >= x1) return ya;
|
||||
if (c->z1 <= z0 || c->z0 >= z1) return ya;
|
||||
|
||||
if (ya > 0 && c->y1 <= y0)
|
||||
if (ya > 0 && c->y1 <= y0)
|
||||
{
|
||||
double max = y0 - c->y1;
|
||||
if (max < ya) ya = max;
|
||||
}
|
||||
if (ya < 0 && c->y0 >= y1)
|
||||
double max = y0 - c->y1;
|
||||
if (max < ya) ya = max;
|
||||
}
|
||||
if (ya < 0 && c->y0 >= y1)
|
||||
{
|
||||
double max = y1 - c->y0;
|
||||
if (max > ya) ya = max;
|
||||
}
|
||||
double max = y1 - c->y0;
|
||||
if (max > ya) ya = max;
|
||||
}
|
||||
|
||||
return ya;
|
||||
return ya;
|
||||
}
|
||||
|
||||
double AABB::clipZCollide(AABB *c, double za)
|
||||
{
|
||||
if (c->x1 <= x0 || c->x0 >= x1) return za;
|
||||
if (c->y1 <= y0 || c->y0 >= y1) return za;
|
||||
if (c->x1 <= x0 || c->x0 >= x1) return za;
|
||||
if (c->y1 <= y0 || c->y0 >= y1) return za;
|
||||
|
||||
if (za > 0 && c->z1 <= z0)
|
||||
if (za > 0 && c->z1 <= z0)
|
||||
{
|
||||
double max = z0 - c->z1;
|
||||
if (max < za) za = max;
|
||||
}
|
||||
if (za < 0 && c->z0 >= z1)
|
||||
double max = z0 - c->z1;
|
||||
if (max < za) za = max;
|
||||
}
|
||||
if (za < 0 && c->z0 >= z1)
|
||||
{
|
||||
double max = z1 - c->z0;
|
||||
if (max > za) za = max;
|
||||
}
|
||||
double max = z1 - c->z0;
|
||||
if (max > za) za = max;
|
||||
}
|
||||
|
||||
return za;
|
||||
return za;
|
||||
}
|
||||
|
||||
bool AABB::intersects(AABB *c)
|
||||
{
|
||||
if (c->x1 <= x0 || c->x0 >= x1) return false;
|
||||
if (c->y1 <= y0 || c->y0 >= y1) return false;
|
||||
if (c->z1 <= z0 || c->z0 >= z1) return false;
|
||||
return true;
|
||||
if (c->x1 <= x0 || c->x0 >= x1) return false;
|
||||
if (c->y1 <= y0 || c->y0 >= y1) return false;
|
||||
if (c->z1 <= z0 || c->z0 >= z1) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AABB::intersectsInner(AABB *c)
|
||||
{
|
||||
if (c->x1 < x0 || c->x0 > x1) return false;
|
||||
if (c->y1 < y0 || c->y0 > y1) return false;
|
||||
if (c->z1 < z0 || c->z0 > z1) return false;
|
||||
return true;
|
||||
if (c->x1 < x0 || c->x0 > x1) return false;
|
||||
if (c->y1 < y0 || c->y0 > y1) return false;
|
||||
if (c->z1 < z0 || c->z0 > z1) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
AABB *AABB::move(double xa, double ya, double za)
|
||||
{
|
||||
x0 += xa;
|
||||
y0 += ya;
|
||||
z0 += za;
|
||||
x1 += xa;
|
||||
y1 += ya;
|
||||
z1 += za;
|
||||
return this;
|
||||
x0 += xa;
|
||||
y0 += ya;
|
||||
z0 += za;
|
||||
x1 += xa;
|
||||
y1 += ya;
|
||||
z1 += za;
|
||||
return this;
|
||||
}
|
||||
|
||||
bool AABB::intersects(double x02, double y02, double z02, double x12, double y12, double z12)
|
||||
{
|
||||
if (x12 <= x0 || x02 >= x1) return false;
|
||||
if (y12 <= y0 || y02 >= y1) return false;
|
||||
if (z12 <= z0 || z02 >= z1) return false;
|
||||
return true;
|
||||
if (x12 <= x0 || x02 >= x1) return false;
|
||||
if (y12 <= y0 || y02 >= y1) return false;
|
||||
if (z12 <= z0 || z02 >= z1) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AABB::contains(Vec3 *p)
|
||||
{
|
||||
if (p->x <= x0 || p->x >= x1) return false;
|
||||
if (p->y <= y0 || p->y >= y1) return false;
|
||||
if (p->z <= z0 || p->z >= z1) return false;
|
||||
return true;
|
||||
if (p->x <= x0 || p->x >= x1) return false;
|
||||
if (p->y <= y0 || p->y >= y1) return false;
|
||||
if (p->z <= z0 || p->z >= z1) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 4J Added
|
||||
bool AABB::containsIncludingLowerBound(Vec3 *p)
|
||||
{
|
||||
if (p->x < x0 || p->x >= x1) return false;
|
||||
if (p->y < y0 || p->y >= y1) return false;
|
||||
if (p->z < z0 || p->z >= z1) return false;
|
||||
return true;
|
||||
if (p->x < x0 || p->x >= x1) return false;
|
||||
if (p->y < y0 || p->y >= y1) return false;
|
||||
if (p->z < z0 || p->z >= z1) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
double AABB::getSize()
|
||||
{
|
||||
double xs = x1 - x0;
|
||||
double ys = y1 - y0;
|
||||
double zs = z1 - z0;
|
||||
return (xs + ys + zs) / 3.0f;
|
||||
double xs = x1 - x0;
|
||||
double ys = y1 - y0;
|
||||
double zs = z1 - z0;
|
||||
return (xs + ys + zs) / 3.0f;
|
||||
}
|
||||
|
||||
AABB *AABB::shrink(double xa, double ya, double za)
|
||||
{
|
||||
double _x0 = x0 + xa;
|
||||
double _y0 = y0 + ya;
|
||||
double _z0 = z0 + za;
|
||||
double _x1 = x1 - xa;
|
||||
double _y1 = y1 - ya;
|
||||
double _z1 = z1 - za;
|
||||
double _x0 = x0 + xa;
|
||||
double _y0 = y0 + ya;
|
||||
double _z0 = z0 + za;
|
||||
double _x1 = x1 - xa;
|
||||
double _y1 = y1 - ya;
|
||||
double _z1 = z1 - za;
|
||||
|
||||
return AABB::newTemp(_x0, _y0, _z0, _x1, _y1, _z1);
|
||||
return AABB::newTemp(_x0, _y0, _z0, _x1, _y1, _z1);
|
||||
}
|
||||
|
||||
AABB *AABB::copy()
|
||||
{
|
||||
return AABB::newTemp(x0, y0, z0, x1, y1, z1);
|
||||
return AABB::newTemp(x0, y0, z0, x1, y1, z1);
|
||||
}
|
||||
|
||||
HitResult *AABB::clip(Vec3 *a, Vec3 *b)
|
||||
{
|
||||
Vec3 *xh0 = a->clipX(b, x0);
|
||||
Vec3 *xh1 = a->clipX(b, x1);
|
||||
Vec3 *xh0 = a->clipX(b, x0);
|
||||
Vec3 *xh1 = a->clipX(b, x1);
|
||||
|
||||
Vec3 *yh0 = a->clipY(b, y0);
|
||||
Vec3 *yh1 = a->clipY(b, y1);
|
||||
Vec3 *yh0 = a->clipY(b, y0);
|
||||
Vec3 *yh1 = a->clipY(b, y1);
|
||||
|
||||
Vec3 *zh0 = a->clipZ(b, z0);
|
||||
Vec3 *zh1 = a->clipZ(b, z1);
|
||||
Vec3 *zh0 = a->clipZ(b, z0);
|
||||
Vec3 *zh1 = a->clipZ(b, z1);
|
||||
|
||||
if (!containsX(xh0)) xh0 = NULL;
|
||||
if (!containsX(xh1)) xh1 = NULL;
|
||||
if (!containsY(yh0)) yh0 = NULL;
|
||||
if (!containsY(yh1)) yh1 = NULL;
|
||||
if (!containsZ(zh0)) zh0 = NULL;
|
||||
if (!containsZ(zh1)) zh1 = NULL;
|
||||
if (!containsX(xh0)) xh0 = NULL;
|
||||
if (!containsX(xh1)) xh1 = NULL;
|
||||
if (!containsY(yh0)) yh0 = NULL;
|
||||
if (!containsY(yh1)) yh1 = NULL;
|
||||
if (!containsZ(zh0)) zh0 = NULL;
|
||||
if (!containsZ(zh1)) zh1 = NULL;
|
||||
|
||||
Vec3 *closest = NULL;
|
||||
Vec3 *closest = NULL;
|
||||
|
||||
if (xh0 != NULL && (closest == NULL || a->distanceToSqr(xh0) < a->distanceToSqr(closest))) closest = xh0;
|
||||
if (xh1 != NULL && (closest == NULL || a->distanceToSqr(xh1) < a->distanceToSqr(closest))) closest = xh1;
|
||||
if (yh0 != NULL && (closest == NULL || a->distanceToSqr(yh0) < a->distanceToSqr(closest))) closest = yh0;
|
||||
if (yh1 != NULL && (closest == NULL || a->distanceToSqr(yh1) < a->distanceToSqr(closest))) closest = yh1;
|
||||
if (zh0 != NULL && (closest == NULL || a->distanceToSqr(zh0) < a->distanceToSqr(closest))) closest = zh0;
|
||||
if (zh1 != NULL && (closest == NULL || a->distanceToSqr(zh1) < a->distanceToSqr(closest))) closest = zh1;
|
||||
if (xh0 != NULL && (closest == NULL || a->distanceToSqr(xh0) < a->distanceToSqr(closest))) closest = xh0;
|
||||
if (xh1 != NULL && (closest == NULL || a->distanceToSqr(xh1) < a->distanceToSqr(closest))) closest = xh1;
|
||||
if (yh0 != NULL && (closest == NULL || a->distanceToSqr(yh0) < a->distanceToSqr(closest))) closest = yh0;
|
||||
if (yh1 != NULL && (closest == NULL || a->distanceToSqr(yh1) < a->distanceToSqr(closest))) closest = yh1;
|
||||
if (zh0 != NULL && (closest == NULL || a->distanceToSqr(zh0) < a->distanceToSqr(closest))) closest = zh0;
|
||||
if (zh1 != NULL && (closest == NULL || a->distanceToSqr(zh1) < a->distanceToSqr(closest))) closest = zh1;
|
||||
|
||||
if (closest == NULL) return NULL;
|
||||
if (closest == NULL) return NULL;
|
||||
|
||||
int face = -1;
|
||||
int face = -1;
|
||||
|
||||
if (closest == xh0) face = 4;
|
||||
if (closest == xh1) face = 5;
|
||||
if (closest == yh0) face = 0;
|
||||
if (closest == yh1) face = 1;
|
||||
if (closest == zh0) face = 2;
|
||||
if (closest == zh1) face = 3;
|
||||
if (closest == xh0) face = 4;
|
||||
if (closest == xh1) face = 5;
|
||||
if (closest == yh0) face = 0;
|
||||
if (closest == yh1) face = 1;
|
||||
if (closest == zh0) face = 2;
|
||||
if (closest == zh1) face = 3;
|
||||
|
||||
return new HitResult(0, 0, 0, face, closest);
|
||||
return new HitResult(0, 0, 0, face, closest);
|
||||
}
|
||||
|
||||
|
||||
bool AABB::containsX(Vec3 *v)
|
||||
{
|
||||
if (v == NULL) return false;
|
||||
return v->y >= y0 && v->y <= y1 && v->z >= z0 && v->z <= z1;
|
||||
if (v == NULL) return false;
|
||||
return v->y >= y0 && v->y <= y1 && v->z >= z0 && v->z <= z1;
|
||||
}
|
||||
|
||||
bool AABB::containsY(Vec3 *v)
|
||||
{
|
||||
if (v == NULL) return false;
|
||||
return v->x >= x0 && v->x <= x1 && v->z >= z0 && v->z <= z1;
|
||||
if (v == NULL) return false;
|
||||
return v->x >= x0 && v->x <= x1 && v->z >= z0 && v->z <= z1;
|
||||
}
|
||||
|
||||
bool AABB::containsZ(Vec3 *v)
|
||||
{
|
||||
if (v == NULL) return false;
|
||||
return v->x >= x0 && v->x <= x1 && v->y >= y0 && v->y <= y1;
|
||||
if (v == NULL) return false;
|
||||
return v->x >= x0 && v->x <= x1 && v->y >= y0 && v->y <= y1;
|
||||
}
|
||||
|
||||
|
||||
void AABB::set(AABB *b)
|
||||
{
|
||||
this->x0 = b->x0;
|
||||
this->y0 = b->y0;
|
||||
this->z0 = b->z0;
|
||||
this->x1 = b->x1;
|
||||
this->y1 = b->y1;
|
||||
this->z1 = b->z1;
|
||||
x0 = b->x0;
|
||||
y0 = b->y0;
|
||||
z0 = b->z0;
|
||||
x1 = b->x1;
|
||||
y1 = b->y1;
|
||||
z1 = b->z1;
|
||||
}
|
||||
|
||||
wstring AABB::toString()
|
||||
{
|
||||
return L"box[" + _toString<double>(x0) + L", " + _toString<double>(y0) + L", " + _toString<double>(z0) + L" -> " +
|
||||
return L"box[" + _toString<double>(x0) + L", " + _toString<double>(y0) + L", " + _toString<double>(z0) + L" -> " +
|
||||
_toString<double>(x1) + L", " + _toString<double>(y1) + L", " + _toString<double>(z1) + L"]";
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
AABB *set(double x0, double y0, double z0, double x1, double y1, double z1);
|
||||
AABB *expand(double xa, double ya, double za);
|
||||
AABB *grow(double xa, double ya, double za);
|
||||
public:
|
||||
AABB *minmax(AABB *other);
|
||||
AABB *cloneMove(double xa, double ya, double za);
|
||||
double clipXCollide(AABB *c, double xa);
|
||||
double clipYCollide(AABB *c, double ya);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
C:\Users\manea\Documents\MinecraftConsoles\Minecraft.World\ARM64EC_Debug\Minecraft.World.lib
|
||||
@@ -63,7 +63,7 @@ float Abilities::getFlyingSpeed()
|
||||
|
||||
void Abilities::setFlyingSpeed(float value)
|
||||
{
|
||||
this->flyingSpeed = value;
|
||||
flyingSpeed = value;
|
||||
}
|
||||
|
||||
float Abilities::getWalkingSpeed()
|
||||
@@ -73,5 +73,5 @@ float Abilities::getWalkingSpeed()
|
||||
|
||||
void Abilities::setWalkingSpeed(float value)
|
||||
{
|
||||
this->walkingSpeed = value;
|
||||
walkingSpeed = value;
|
||||
}
|
||||
20
Minecraft.World/AbsoptionMobEffect.cpp
Normal file
20
Minecraft.World/AbsoptionMobEffect.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "stdafx.h"
|
||||
#include "net.minecraft.world.entity.h"
|
||||
#include "net.minecraft.world.effect.h"
|
||||
#include "AbsoptionMobEffect.h"
|
||||
|
||||
AbsoptionMobEffect::AbsoptionMobEffect(int id, bool isHarmful, eMinecraftColour color) : MobEffect(id, isHarmful, color)
|
||||
{
|
||||
}
|
||||
|
||||
void AbsoptionMobEffect::removeAttributeModifiers(shared_ptr<LivingEntity> entity, BaseAttributeMap *attributes, int amplifier)
|
||||
{
|
||||
entity->setAbsorptionAmount(entity->getAbsorptionAmount() - 4 * (amplifier + 1));
|
||||
MobEffect::removeAttributeModifiers(entity, attributes, amplifier);
|
||||
}
|
||||
|
||||
void AbsoptionMobEffect::addAttributeModifiers(shared_ptr<LivingEntity> entity, BaseAttributeMap *attributes, int amplifier)
|
||||
{
|
||||
entity->setAbsorptionAmount(entity->getAbsorptionAmount() + 4 * (amplifier + 1));
|
||||
MobEffect::addAttributeModifiers(entity, attributes, amplifier);
|
||||
}
|
||||
14
Minecraft.World/AbsoptionMobEffect.h
Normal file
14
Minecraft.World/AbsoptionMobEffect.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
class LivingEntity;
|
||||
|
||||
#include "MobEffect.h"
|
||||
|
||||
class AbsoptionMobEffect : public MobEffect
|
||||
{
|
||||
public:
|
||||
AbsoptionMobEffect(int id, bool isHarmful, eMinecraftColour color);
|
||||
|
||||
void removeAttributeModifiers(shared_ptr<LivingEntity> entity, BaseAttributeMap *attributes, int amplifier);
|
||||
void addAttributeModifiers(shared_ptr<LivingEntity> entity, BaseAttributeMap *attributes, int amplifier);
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "net.minecraft.world.entity.player.h"
|
||||
#include "net.minecraft.world.item.h"
|
||||
#include "net.minecraft.world.level.redstone.h"
|
||||
#include "Slot.h"
|
||||
#include "AbstractContainerMenu.h"
|
||||
|
||||
@@ -8,46 +9,36 @@
|
||||
// TODO Make sure all derived classes also call this
|
||||
AbstractContainerMenu::AbstractContainerMenu()
|
||||
{
|
||||
lastSlots = new vector<shared_ptr<ItemInstance> >();
|
||||
slots = new vector<Slot *>();
|
||||
containerId = 0;
|
||||
|
||||
changeUid = 0;
|
||||
m_bNeedsRendered = false;
|
||||
|
||||
containerListeners = new vector<ContainerListener *>();
|
||||
quickcraftType = -1;
|
||||
quickcraftStatus = 0;
|
||||
|
||||
m_bNeedsRendered = false;
|
||||
}
|
||||
|
||||
AbstractContainerMenu::~AbstractContainerMenu()
|
||||
{
|
||||
delete lastSlots;
|
||||
for( unsigned int i = 0; i < slots->size(); i++ )
|
||||
for( unsigned int i = 0; i < slots.size(); i++ )
|
||||
{
|
||||
delete slots->at(i);
|
||||
delete slots.at(i);
|
||||
}
|
||||
delete slots;
|
||||
delete containerListeners;
|
||||
}
|
||||
|
||||
Slot *AbstractContainerMenu::addSlot(Slot *slot)
|
||||
{
|
||||
slot->index = (int)slots->size();
|
||||
slots->push_back(slot);
|
||||
lastSlots->push_back(nullptr);
|
||||
slot->index = (int)slots.size();
|
||||
slots.push_back(slot);
|
||||
lastSlots.push_back(nullptr);
|
||||
return slot;
|
||||
}
|
||||
|
||||
|
||||
void AbstractContainerMenu::addSlotListener(ContainerListener *listener)
|
||||
{
|
||||
// TODO 4J Add exceptions
|
||||
/*
|
||||
if (containerListeners->contains(listener)) {
|
||||
throw new IllegalArgumentException("Listener already listening");
|
||||
}
|
||||
*/
|
||||
containerListeners->push_back(listener);
|
||||
|
||||
containerListeners.push_back(listener);
|
||||
|
||||
vector<shared_ptr<ItemInstance> > *items = getItems();
|
||||
listener->refreshContainer(this, items);
|
||||
@@ -55,11 +46,17 @@ void AbstractContainerMenu::addSlotListener(ContainerListener *listener)
|
||||
broadcastChanges();
|
||||
}
|
||||
|
||||
void AbstractContainerMenu::removeSlotListener(ContainerListener *listener)
|
||||
{
|
||||
AUTO_VAR(it, std::find(containerListeners.begin(), containerListeners.end(), listener) );
|
||||
if(it != containerListeners.end()) containerListeners.erase(it);
|
||||
}
|
||||
|
||||
vector<shared_ptr<ItemInstance> > *AbstractContainerMenu::getItems()
|
||||
{
|
||||
vector<shared_ptr<ItemInstance> > *items = new vector<shared_ptr<ItemInstance> >();
|
||||
AUTO_VAR(itEnd, slots->end());
|
||||
for (AUTO_VAR(it, slots->begin()); it != itEnd; it++)
|
||||
AUTO_VAR(itEnd, slots.end());
|
||||
for (AUTO_VAR(it, slots.begin()); it != itEnd; it++)
|
||||
{
|
||||
items->push_back((*it)->getItem());
|
||||
}
|
||||
@@ -68,8 +65,8 @@ vector<shared_ptr<ItemInstance> > *AbstractContainerMenu::getItems()
|
||||
|
||||
void AbstractContainerMenu::sendData(int id, int value)
|
||||
{
|
||||
AUTO_VAR(itEnd, containerListeners->end());
|
||||
for (AUTO_VAR(it, containerListeners->begin()); it != itEnd; it++)
|
||||
AUTO_VAR(itEnd, containerListeners.end());
|
||||
for (AUTO_VAR(it, containerListeners.begin()); it != itEnd; it++)
|
||||
{
|
||||
(*it)->setContainerData(this, id, value);
|
||||
}
|
||||
@@ -77,18 +74,20 @@ void AbstractContainerMenu::sendData(int id, int value)
|
||||
|
||||
void AbstractContainerMenu::broadcastChanges()
|
||||
{
|
||||
for (unsigned int i = 0; i < slots->size(); i++)
|
||||
for (unsigned int i = 0; i < slots.size(); i++)
|
||||
{
|
||||
shared_ptr<ItemInstance> current = slots->at(i)->getItem();
|
||||
shared_ptr<ItemInstance> expected = lastSlots->at(i);
|
||||
shared_ptr<ItemInstance> current = slots.at(i)->getItem();
|
||||
shared_ptr<ItemInstance> expected = lastSlots.at(i);
|
||||
if (!ItemInstance::matches(expected, current))
|
||||
{
|
||||
expected = current == NULL ? nullptr : current->copy();
|
||||
(*lastSlots)[i] = expected;
|
||||
// 4J Stu - Added 0 count check. There is a bug in the Java with anvils that means this broadcast
|
||||
// happens while we are in the middle of quickmoving, and before the slot properly gets set to null
|
||||
expected = (current == NULL || current->count == 0) ? nullptr : current->copy();
|
||||
lastSlots[i] = expected;
|
||||
m_bNeedsRendered = true;
|
||||
|
||||
AUTO_VAR(itEnd, containerListeners->end());
|
||||
for (AUTO_VAR(it, containerListeners->begin()); it != itEnd; it++)
|
||||
AUTO_VAR(itEnd, containerListeners.end());
|
||||
for (AUTO_VAR(it, containerListeners.begin()); it != itEnd; it++)
|
||||
{
|
||||
(*it)->slotChanged(this, i, expected);
|
||||
}
|
||||
@@ -101,14 +100,14 @@ bool AbstractContainerMenu::needsRendered()
|
||||
bool needsRendered = m_bNeedsRendered;
|
||||
m_bNeedsRendered = false;
|
||||
|
||||
for (unsigned int i = 0; i < slots->size(); i++)
|
||||
for (unsigned int i = 0; i < slots.size(); i++)
|
||||
{
|
||||
shared_ptr<ItemInstance> current = slots->at(i)->getItem();
|
||||
shared_ptr<ItemInstance> expected = lastSlots->at(i);
|
||||
shared_ptr<ItemInstance> current = slots.at(i)->getItem();
|
||||
shared_ptr<ItemInstance> expected = lastSlots.at(i);
|
||||
if (!ItemInstance::matches(expected, current))
|
||||
{
|
||||
expected = current == NULL ? nullptr : current->copy();
|
||||
(*lastSlots)[i] = expected;
|
||||
lastSlots[i] = expected;
|
||||
needsRendered = true;
|
||||
}
|
||||
}
|
||||
@@ -123,8 +122,8 @@ bool AbstractContainerMenu::clickMenuButton(shared_ptr<Player> player, int butto
|
||||
|
||||
Slot *AbstractContainerMenu::getSlotFor(shared_ptr<Container> c, int index)
|
||||
{
|
||||
AUTO_VAR(itEnd, slots->end());
|
||||
for (AUTO_VAR(it, slots->begin()); it != itEnd; it++)
|
||||
AUTO_VAR(itEnd, slots.end());
|
||||
for (AUTO_VAR(it, slots.begin()); it != itEnd; it++)
|
||||
{
|
||||
Slot *slot = *it; //slots->at(i);
|
||||
if (slot->isAt(c, index))
|
||||
@@ -137,12 +136,12 @@ Slot *AbstractContainerMenu::getSlotFor(shared_ptr<Container> c, int index)
|
||||
|
||||
Slot *AbstractContainerMenu::getSlot(int index)
|
||||
{
|
||||
return slots->at(index);
|
||||
return slots.at(index);
|
||||
}
|
||||
|
||||
shared_ptr<ItemInstance> AbstractContainerMenu::quickMoveStack(shared_ptr<Player> player, int slotIndex)
|
||||
{
|
||||
Slot *slot = slots->at(slotIndex);
|
||||
Slot *slot = slots.at(slotIndex);
|
||||
if (slot != NULL)
|
||||
{
|
||||
return slot->getItem();
|
||||
@@ -150,18 +149,97 @@ shared_ptr<ItemInstance> AbstractContainerMenu::quickMoveStack(shared_ptr<Player
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<ItemInstance> AbstractContainerMenu::clicked(int slotIndex, int buttonNum, int clickType, shared_ptr<Player> player)
|
||||
shared_ptr<ItemInstance> AbstractContainerMenu::clicked(int slotIndex, int buttonNum, int clickType, shared_ptr<Player> player, bool looped) // 4J Added looped param
|
||||
{
|
||||
shared_ptr<ItemInstance> clickedEntity = nullptr;
|
||||
shared_ptr<Inventory> inventory = player->inventory;
|
||||
|
||||
if ((clickType == CLICK_PICKUP || clickType == CLICK_QUICK_MOVE) && (buttonNum == 0 || buttonNum == 1))
|
||||
if (clickType == CLICK_QUICK_CRAFT)
|
||||
{
|
||||
if (slotIndex == CLICKED_OUTSIDE)
|
||||
int expectedStatus = quickcraftStatus;
|
||||
quickcraftStatus = getQuickcraftHeader(buttonNum);
|
||||
|
||||
if ((expectedStatus != QUICKCRAFT_HEADER_CONTINUE || quickcraftStatus != QUICKCRAFT_HEADER_END) && expectedStatus != quickcraftStatus)
|
||||
{
|
||||
resetQuickCraft();
|
||||
}
|
||||
else if (inventory->getCarried() == NULL)
|
||||
{
|
||||
resetQuickCraft();
|
||||
}
|
||||
else if (quickcraftStatus == QUICKCRAFT_HEADER_START)
|
||||
{
|
||||
quickcraftType = getQuickcraftType(buttonNum);
|
||||
|
||||
if (isValidQuickcraftType(quickcraftType))
|
||||
{
|
||||
quickcraftStatus = QUICKCRAFT_HEADER_CONTINUE;
|
||||
quickcraftSlots.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
resetQuickCraft();
|
||||
}
|
||||
}
|
||||
else if (quickcraftStatus == QUICKCRAFT_HEADER_CONTINUE)
|
||||
{
|
||||
Slot *slot = slots.at(slotIndex);
|
||||
|
||||
if (slot != NULL && canItemQuickReplace(slot, inventory->getCarried(), true) && slot->mayPlace(inventory->getCarried()) && inventory->getCarried()->count > quickcraftSlots.size() && canDragTo(slot))
|
||||
{
|
||||
quickcraftSlots.insert(slot);
|
||||
}
|
||||
}
|
||||
else if (quickcraftStatus == QUICKCRAFT_HEADER_END)
|
||||
{
|
||||
if (!quickcraftSlots.empty())
|
||||
{
|
||||
shared_ptr<ItemInstance> source = inventory->getCarried()->copy();
|
||||
int remaining = inventory->getCarried()->count;
|
||||
|
||||
for(AUTO_VAR(it, quickcraftSlots.begin()); it != quickcraftSlots.end(); ++it)
|
||||
{
|
||||
Slot *slot = *it;
|
||||
if (slot != NULL && canItemQuickReplace(slot, inventory->getCarried(), true) && slot->mayPlace(inventory->getCarried()) && inventory->getCarried()->count >= quickcraftSlots.size() && canDragTo(slot))
|
||||
{
|
||||
shared_ptr<ItemInstance> copy = source->copy();
|
||||
int carry = slot->hasItem() ? slot->getItem()->count : 0;
|
||||
getQuickCraftSlotCount(&quickcraftSlots, quickcraftType, copy, carry);
|
||||
|
||||
if (copy->count > copy->getMaxStackSize()) copy->count = copy->getMaxStackSize();
|
||||
if (copy->count > slot->getMaxStackSize()) copy->count = slot->getMaxStackSize();
|
||||
|
||||
remaining -= copy->count - carry;
|
||||
slot->set(copy);
|
||||
}
|
||||
}
|
||||
|
||||
source->count = remaining;
|
||||
if (source->count <= 0)
|
||||
{
|
||||
source = nullptr;
|
||||
}
|
||||
inventory->setCarried(source);
|
||||
}
|
||||
|
||||
resetQuickCraft();
|
||||
}
|
||||
else
|
||||
{
|
||||
resetQuickCraft();
|
||||
}
|
||||
}
|
||||
else if (quickcraftStatus != QUICKCRAFT_HEADER_START)
|
||||
{
|
||||
resetQuickCraft();
|
||||
}
|
||||
else if ((clickType == CLICK_PICKUP || clickType == CLICK_QUICK_MOVE) && (buttonNum == 0 || buttonNum == 1))
|
||||
{
|
||||
if (slotIndex == SLOT_CLICKED_OUTSIDE)
|
||||
{
|
||||
if (inventory->getCarried() != NULL)
|
||||
{
|
||||
if (slotIndex == CLICKED_OUTSIDE)
|
||||
if (slotIndex == SLOT_CLICKED_OUTSIDE)
|
||||
{
|
||||
if (buttonNum == 0)
|
||||
{
|
||||
@@ -179,23 +257,38 @@ shared_ptr<ItemInstance> AbstractContainerMenu::clicked(int slotIndex, int butto
|
||||
}
|
||||
else if (clickType == CLICK_QUICK_MOVE)
|
||||
{
|
||||
Slot *slot = slots->at(slotIndex);
|
||||
if (slotIndex < 0) return nullptr;
|
||||
Slot *slot = slots.at(slotIndex);
|
||||
if(slot != NULL && slot->mayPickup(player))
|
||||
{
|
||||
shared_ptr<ItemInstance> piiClicked = quickMoveStack(player, slotIndex);
|
||||
if (piiClicked != NULL)
|
||||
{
|
||||
//int oldSize = piiClicked->count; // 4J - Commented 1.8.2 and replaced with below
|
||||
int oldType = piiClicked->id;
|
||||
|
||||
clickedEntity = piiClicked->copy();
|
||||
// 4J Stu - We ignore the return value for loopClicks, so don't make a copy
|
||||
if(!looped)
|
||||
{
|
||||
clickedEntity = piiClicked->copy();
|
||||
}
|
||||
|
||||
// 4J Stu - Remove the reference to this before we start a recursive loop
|
||||
piiClicked = nullptr;
|
||||
|
||||
if (slot != NULL)
|
||||
{
|
||||
if (slot->getItem() != NULL && slot->getItem()->id == oldType)
|
||||
{
|
||||
// 4J Stu - Brought forward loopClick from 1.2 to fix infinite recursion bug in creative
|
||||
loopClick(slotIndex, buttonNum, true, player);
|
||||
if(looped)
|
||||
{
|
||||
// Return a non-null value to indicate that we want to loop more
|
||||
clickedEntity = shared_ptr<ItemInstance>(new ItemInstance(0,1,0));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 4J Stu - Brought forward loopClick from 1.2 to fix infinite recursion bug in creative
|
||||
loopClick(slotIndex, buttonNum, true, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,7 +298,7 @@ shared_ptr<ItemInstance> AbstractContainerMenu::clicked(int slotIndex, int butto
|
||||
{
|
||||
if (slotIndex < 0) return nullptr;
|
||||
|
||||
Slot *slot = slots->at(slotIndex);
|
||||
Slot *slot = slots.at(slotIndex);
|
||||
if (slot != NULL)
|
||||
{
|
||||
shared_ptr<ItemInstance> clicked = slot->getItem();
|
||||
@@ -225,7 +318,10 @@ shared_ptr<ItemInstance> AbstractContainerMenu::clicked(int slotIndex, int butto
|
||||
{
|
||||
c = slot->getMaxStackSize();
|
||||
}
|
||||
slot->set(carried->remove(c));
|
||||
if (carried->count >= c)
|
||||
{
|
||||
slot->set(carried->remove(c));
|
||||
}
|
||||
if (carried->count == 0)
|
||||
{
|
||||
inventory->setCarried(nullptr);
|
||||
@@ -318,7 +414,7 @@ shared_ptr<ItemInstance> AbstractContainerMenu::clicked(int slotIndex, int butto
|
||||
}
|
||||
else if (clickType == CLICK_SWAP && buttonNum >= 0 && buttonNum < 9)
|
||||
{
|
||||
Slot *slot = slots->at(slotIndex);
|
||||
Slot *slot = slots.at(slotIndex);
|
||||
if (slot->mayPickup(player))
|
||||
{
|
||||
shared_ptr<ItemInstance> current = inventory->getItem(buttonNum);
|
||||
@@ -359,7 +455,7 @@ shared_ptr<ItemInstance> AbstractContainerMenu::clicked(int slotIndex, int butto
|
||||
}
|
||||
else if (clickType == CLICK_CLONE && player->abilities.instabuild && inventory->getCarried() == NULL && slotIndex >= 0)
|
||||
{
|
||||
Slot *slot = slots->at(slotIndex);
|
||||
Slot *slot = slots.at(slotIndex);
|
||||
if (slot != NULL && slot->hasItem())
|
||||
{
|
||||
shared_ptr<ItemInstance> copy = slot->getItem()->copy();
|
||||
@@ -367,13 +463,66 @@ shared_ptr<ItemInstance> AbstractContainerMenu::clicked(int slotIndex, int butto
|
||||
inventory->setCarried(copy);
|
||||
}
|
||||
}
|
||||
else if (clickType == CLICK_THROW && inventory->getCarried() == NULL && slotIndex >= 0)
|
||||
{
|
||||
Slot *slot = slots.at(slotIndex);
|
||||
if (slot != NULL && slot->hasItem() && slot->mayPickup(player))
|
||||
{
|
||||
shared_ptr<ItemInstance> item = slot->remove(buttonNum == 0 ? 1 : slot->getItem()->count);
|
||||
slot->onTake(player, item);
|
||||
player->drop(item);
|
||||
}
|
||||
}
|
||||
else if (clickType == CLICK_PICKUP_ALL && slotIndex >= 0)
|
||||
{
|
||||
Slot *slot = slots.at(slotIndex);
|
||||
shared_ptr<ItemInstance> carried = inventory->getCarried();
|
||||
|
||||
if (carried != NULL && (slot == NULL || !slot->hasItem() || !slot->mayPickup(player)))
|
||||
{
|
||||
int start = buttonNum == 0 ? 0 : slots.size() - 1;
|
||||
int step = buttonNum == 0 ? 1 : -1;
|
||||
|
||||
for (int pass = 0; pass < 2; pass++ )
|
||||
{
|
||||
// In the first pass, we only get partial stacks.
|
||||
for (int i = start; i >= 0 && i < slots.size() && carried->count < carried->getMaxStackSize(); i += step)
|
||||
{
|
||||
Slot *target = slots.at(i);
|
||||
|
||||
if (target->hasItem() && canItemQuickReplace(target, carried, true) && target->mayPickup(player) && canTakeItemForPickAll(carried, target))
|
||||
{
|
||||
if (pass == 0 && target->getItem()->count == target->getItem()->getMaxStackSize()) continue;
|
||||
int count = min(carried->getMaxStackSize() - carried->count, target->getItem()->count);
|
||||
shared_ptr<ItemInstance> removed = target->remove(count);
|
||||
carried->count += count;
|
||||
|
||||
if (removed->count <= 0)
|
||||
{
|
||||
target->set(nullptr);
|
||||
}
|
||||
target->onTake(player, removed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
broadcastChanges();
|
||||
}
|
||||
return clickedEntity;
|
||||
}
|
||||
|
||||
bool AbstractContainerMenu::canTakeItemForPickAll(shared_ptr<ItemInstance> carried, Slot *target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// 4J Stu - Brought forward from 1.2 to fix infinite recursion bug in creative
|
||||
void AbstractContainerMenu::loopClick(int slotIndex, int buttonNum, bool quickKeyHeld, shared_ptr<Player> player)
|
||||
{
|
||||
clicked(slotIndex, buttonNum, CLICK_QUICK_MOVE, player);
|
||||
while( clicked(slotIndex, buttonNum, CLICK_QUICK_MOVE, player, true) != NULL)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
bool AbstractContainerMenu::mayCombine(Slot *slot, shared_ptr<ItemInstance> item)
|
||||
@@ -460,7 +609,7 @@ bool AbstractContainerMenu::moveItemStackTo(shared_ptr<ItemInstance> itemStack,
|
||||
while (itemStack->count > 0 && ((!backwards && destSlot < endSlot) || (backwards && destSlot >= startSlot)))
|
||||
{
|
||||
|
||||
Slot *slot = slots->at(destSlot);
|
||||
Slot *slot = slots.at(destSlot);
|
||||
shared_ptr<ItemInstance> target = slot->getItem();
|
||||
if (target != NULL && target->id == itemStack->id && (!itemStack->isStackedByData() || itemStack->getAuxValue() == target->getAuxValue())
|
||||
&& ItemInstance::tagMatches(itemStack, target) )
|
||||
@@ -506,7 +655,7 @@ bool AbstractContainerMenu::moveItemStackTo(shared_ptr<ItemInstance> itemStack,
|
||||
}
|
||||
while ((!backwards && destSlot < endSlot) || (backwards && destSlot >= startSlot))
|
||||
{
|
||||
Slot *slot = slots->at(destSlot);
|
||||
Slot *slot = slots.at(destSlot);
|
||||
shared_ptr<ItemInstance> target = slot->getItem();
|
||||
|
||||
if (target == NULL)
|
||||
@@ -535,3 +684,88 @@ bool AbstractContainerMenu::isOverrideResultClick(int slotNum, int buttonNum)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int AbstractContainerMenu::getQuickcraftType(int mask)
|
||||
{
|
||||
return (mask >> 2) & 0x3;
|
||||
}
|
||||
|
||||
int AbstractContainerMenu::getQuickcraftHeader(int mask)
|
||||
{
|
||||
return mask & 0x3;
|
||||
}
|
||||
|
||||
int AbstractContainerMenu::getQuickcraftMask(int header, int type)
|
||||
{
|
||||
return (header & 0x3) | ((type & 0x3) << 2);
|
||||
}
|
||||
|
||||
bool AbstractContainerMenu::isValidQuickcraftType(int type)
|
||||
{
|
||||
return type == QUICKCRAFT_TYPE_CHARITABLE || type == QUICKCRAFT_TYPE_GREEDY;
|
||||
}
|
||||
|
||||
void AbstractContainerMenu::resetQuickCraft()
|
||||
{
|
||||
quickcraftStatus = QUICKCRAFT_HEADER_START;
|
||||
quickcraftSlots.clear();
|
||||
}
|
||||
|
||||
bool AbstractContainerMenu::canItemQuickReplace(Slot *slot, shared_ptr<ItemInstance> item, bool ignoreSize)
|
||||
{
|
||||
bool canReplace = slot == NULL || !slot->hasItem();
|
||||
|
||||
if (slot != NULL && slot->hasItem() && item != NULL && item->sameItem(slot->getItem()) && ItemInstance::tagMatches(slot->getItem(), item))
|
||||
{
|
||||
canReplace |= slot->getItem()->count + (ignoreSize ? 0 : item->count) <= item->getMaxStackSize();
|
||||
}
|
||||
|
||||
return canReplace;
|
||||
}
|
||||
|
||||
void AbstractContainerMenu::getQuickCraftSlotCount(unordered_set<Slot *> *quickCraftSlots, int quickCraftingType, shared_ptr<ItemInstance> item, int carry)
|
||||
{
|
||||
switch (quickCraftingType)
|
||||
{
|
||||
case QUICKCRAFT_TYPE_CHARITABLE:
|
||||
item->count = Mth::floor(item->count / (float) quickCraftSlots->size());
|
||||
break;
|
||||
case QUICKCRAFT_TYPE_GREEDY:
|
||||
item->count = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
item->count += carry;
|
||||
}
|
||||
|
||||
bool AbstractContainerMenu::canDragTo(Slot *slot)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int AbstractContainerMenu::getRedstoneSignalFromContainer(shared_ptr<Container> container)
|
||||
{
|
||||
if (container == NULL) return 0;
|
||||
int count = 0;
|
||||
float totalPct = 0;
|
||||
|
||||
for (int i = 0; i < container->getContainerSize(); i++)
|
||||
{
|
||||
shared_ptr<ItemInstance> item = container->getItem(i);
|
||||
|
||||
if (item != NULL)
|
||||
{
|
||||
totalPct += item->count / (float) min(container->getMaxStackSize(), item->getMaxStackSize());
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
totalPct /= container->getContainerSize();
|
||||
return Mth::floor(totalPct * (Redstone::SIGNAL_MAX - 1)) + (count > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
// 4J Added
|
||||
bool AbstractContainerMenu::isValidIngredient(shared_ptr<ItemInstance> item, int slotId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -14,28 +14,43 @@ class Container;
|
||||
class AbstractContainerMenu
|
||||
{
|
||||
public:
|
||||
static const int CLICKED_OUTSIDE = -999;
|
||||
static const int SLOT_CLICKED_OUTSIDE = -999;
|
||||
|
||||
static const int CLICK_PICKUP = 0;
|
||||
static const int CLICK_QUICK_MOVE = 1;
|
||||
static const int CLICK_SWAP = 2;
|
||||
static const int CLICK_CLONE = 3;
|
||||
static const int CLICK_THROW = 4;
|
||||
static const int CLICK_QUICK_CRAFT = 5;
|
||||
static const int CLICK_PICKUP_ALL = 6;
|
||||
|
||||
static const int QUICKCRAFT_TYPE_CHARITABLE = 0;
|
||||
static const int QUICKCRAFT_TYPE_GREEDY = 1;
|
||||
static const int QUICKCRAFT_HEADER_START = 0;
|
||||
static const int QUICKCRAFT_HEADER_CONTINUE = 1;
|
||||
static const int QUICKCRAFT_HEADER_END = 2;
|
||||
|
||||
// 4J Stu - Added these to fix problem with items picked up while in the creative menu replacing slots in the creative menu
|
||||
static const int CONTAINER_ID_CARRIED = -1;
|
||||
static const int CONTAINER_ID_INVENTORY = 0;
|
||||
static const int CONTAINER_ID_CREATIVE = -2;
|
||||
|
||||
vector<shared_ptr<ItemInstance> > *lastSlots;
|
||||
vector<Slot *> *slots;
|
||||
vector<shared_ptr<ItemInstance> > lastSlots;
|
||||
vector<Slot *> slots;
|
||||
int containerId;
|
||||
|
||||
private:
|
||||
short changeUid;
|
||||
|
||||
int quickcraftType;
|
||||
int quickcraftStatus;
|
||||
unordered_set<Slot *> quickcraftSlots;
|
||||
|
||||
private:
|
||||
bool m_bNeedsRendered; // 4J added
|
||||
|
||||
protected:
|
||||
vector<ContainerListener *> *containerListeners;
|
||||
vector<ContainerListener *> containerListeners;
|
||||
|
||||
// 4J Stu - The java does not have ctor here (being an abstract) but we need one to initialise the member variables
|
||||
// TODO Make sure all derived classes also call this
|
||||
@@ -46,18 +61,22 @@ protected:
|
||||
public:
|
||||
virtual ~AbstractContainerMenu();
|
||||
virtual void addSlotListener(ContainerListener *listener);
|
||||
vector<shared_ptr<ItemInstance> > *getItems();
|
||||
void sendData(int id, int value);
|
||||
virtual void removeSlotListener(ContainerListener *listener);
|
||||
virtual vector<shared_ptr<ItemInstance> > *getItems();
|
||||
virtual void sendData(int id, int value);
|
||||
virtual void broadcastChanges();
|
||||
virtual bool needsRendered();
|
||||
virtual bool clickMenuButton(shared_ptr<Player> player, int buttonId);
|
||||
Slot *getSlotFor(shared_ptr<Container> c, int index);
|
||||
Slot *getSlot(int index);
|
||||
virtual Slot *getSlotFor(shared_ptr<Container> c, int index);
|
||||
virtual Slot *getSlot(int index);
|
||||
virtual shared_ptr<ItemInstance> quickMoveStack(shared_ptr<Player> player, int slotIndex);
|
||||
virtual shared_ptr<ItemInstance> clicked(int slotIndex, int buttonNum, int clickType, shared_ptr<Player> player);
|
||||
virtual shared_ptr<ItemInstance> clicked(int slotIndex, int buttonNum, int clickType, shared_ptr<Player> player, bool looped = false); // 4J added looped param
|
||||
virtual bool mayCombine(Slot *slot, shared_ptr<ItemInstance> item);
|
||||
virtual bool canTakeItemForPickAll(shared_ptr<ItemInstance> carried, Slot *target);
|
||||
|
||||
protected:
|
||||
virtual void loopClick(int slotIndex, int buttonNum, bool quickKeyHeld, shared_ptr<Player> player);
|
||||
|
||||
public:
|
||||
virtual void removed(shared_ptr<Player> player);
|
||||
virtual void slotsChanged();// 4J used to take a shared_ptr<Container> container but wasn't using it, so removed to simplify things
|
||||
@@ -76,7 +95,7 @@ public:
|
||||
virtual bool stillValid(shared_ptr<Player> player) = 0;
|
||||
|
||||
// 4J Stu Added for UI
|
||||
unsigned int getSize() { return (unsigned int)slots->size(); }
|
||||
unsigned int getSize() { return (unsigned int)slots.size(); }
|
||||
|
||||
|
||||
protected:
|
||||
@@ -85,4 +104,21 @@ protected:
|
||||
|
||||
public:
|
||||
virtual bool isOverrideResultClick(int slotNum, int buttonNum);
|
||||
|
||||
static int getQuickcraftType(int mask);
|
||||
static int getQuickcraftHeader(int mask);
|
||||
static int getQuickcraftMask(int header, int type);
|
||||
static bool isValidQuickcraftType(int type);
|
||||
|
||||
protected:
|
||||
void resetQuickCraft();
|
||||
|
||||
public:
|
||||
static bool canItemQuickReplace(Slot *slot, shared_ptr<ItemInstance> item, bool ignoreSize);
|
||||
static void getQuickCraftSlotCount(unordered_set<Slot *> *quickCraftSlots, int quickCraftingType, shared_ptr<ItemInstance> item, int carry);
|
||||
bool canDragTo(Slot *slot);
|
||||
static int getRedstoneSignalFromContainer(shared_ptr<Container> container);
|
||||
|
||||
// 4J Added
|
||||
virtual bool isValidIngredient(shared_ptr<ItemInstance> item, int slotId);
|
||||
};
|
||||
|
||||
48
Minecraft.World/AbstractProjectileDispenseBehavior.cpp
Normal file
48
Minecraft.World/AbstractProjectileDispenseBehavior.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "AbstractProjectileDispenseBehavior.h"
|
||||
#include "DispenserTile.h"
|
||||
#include "Projectile.h"
|
||||
#include "Level.h"
|
||||
#include "LevelEvent.h"
|
||||
#include "ItemInstance.h"
|
||||
|
||||
shared_ptr<ItemInstance> AbstractProjectileDispenseBehavior::execute(BlockSource *source, shared_ptr<ItemInstance> dispensed, eOUTCOME &outcome)
|
||||
{
|
||||
Level *world = source->getWorld();
|
||||
if ( world->countInstanceOf(eTYPE_PROJECTILE, false) >= Level::MAX_DISPENSABLE_PROJECTILES )
|
||||
{
|
||||
return DefaultDispenseItemBehavior::execute(source, dispensed, outcome);
|
||||
}
|
||||
|
||||
Position *position = DispenserTile::getDispensePosition(source);
|
||||
FacingEnum *facing = DispenserTile::getFacing(source->getData());
|
||||
|
||||
shared_ptr<Projectile> projectile = getProjectile(world, position);
|
||||
|
||||
delete position;
|
||||
|
||||
projectile->shoot(facing->getStepX(), facing->getStepY() + .1f, facing->getStepZ(), getPower(), getUncertainty());
|
||||
world->addEntity(dynamic_pointer_cast<Entity>(projectile));
|
||||
|
||||
dispensed->remove(1);
|
||||
return dispensed;
|
||||
}
|
||||
|
||||
void AbstractProjectileDispenseBehavior::playSound(BlockSource *source, eOUTCOME outcome)
|
||||
{
|
||||
if (outcome != LEFT_ITEM)
|
||||
{
|
||||
source->getWorld()->levelEvent(LevelEvent::SOUND_LAUNCH, source->getBlockX(), source->getBlockY(), source->getBlockZ(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
float AbstractProjectileDispenseBehavior::getUncertainty()
|
||||
{
|
||||
return 6.0f;
|
||||
}
|
||||
|
||||
float AbstractProjectileDispenseBehavior::getPower()
|
||||
{
|
||||
return 1.1f;
|
||||
}
|
||||
17
Minecraft.World/AbstractProjectileDispenseBehavior.h
Normal file
17
Minecraft.World/AbstractProjectileDispenseBehavior.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "DefaultDispenseItemBehavior.h"
|
||||
|
||||
class Projectile;
|
||||
class Position;
|
||||
|
||||
class AbstractProjectileDispenseBehavior : public DefaultDispenseItemBehavior
|
||||
{
|
||||
public:
|
||||
virtual shared_ptr<ItemInstance> execute(BlockSource *source, shared_ptr<ItemInstance> dispensed, eOUTCOME &outcome);
|
||||
|
||||
protected:
|
||||
virtual void playSound(BlockSource *source, eOUTCOME outcome);
|
||||
virtual float getUncertainty();
|
||||
virtual float getPower();
|
||||
virtual shared_ptr<Projectile> getProjectile(Level *world, Position *position) = 0;
|
||||
};
|
||||
@@ -8,35 +8,34 @@ class AddEntityPacket : public Packet, public enable_shared_from_this<AddEntityP
|
||||
public:
|
||||
static const int BOAT = 1;
|
||||
static const int ITEM = 2;
|
||||
static const int MINECART_RIDEABLE = 10;
|
||||
static const int MINECART_CHEST = 11;
|
||||
static const int MINECART_FURNACE = 12;
|
||||
static const int PRIMED_TNT = 50;
|
||||
static const int MINECART = 10;
|
||||
static const int PRIMED_TNT = 50;
|
||||
static const int ENDER_CRYSTAL = 51;
|
||||
static const int ARROW = 60;
|
||||
static const int SNOWBALL = 61;
|
||||
static const int EGG = 62;
|
||||
static const int FIREBALL = 63;
|
||||
static const int ARROW = 60;
|
||||
static const int SNOWBALL = 61;
|
||||
static const int EGG = 62;
|
||||
static const int FIREBALL = 63;
|
||||
static const int SMALL_FIREBALL = 64;
|
||||
static const int THROWN_ENDERPEARL = 65;
|
||||
|
||||
static const int FALLING = 70;
|
||||
static const int WITHER_SKULL = 66;
|
||||
static const int FALLING = 70;
|
||||
static const int ITEM_FRAME = 71;
|
||||
static const int EYEOFENDERSIGNAL = 72;
|
||||
static const int THROWN_POTION = 73;
|
||||
static const int FALLING_EGG = 74;
|
||||
static const int THROWN_EXPBOTTLE = 75;
|
||||
|
||||
static const int FIREWORKS = 76;
|
||||
static const int LEASH_KNOT = 77;
|
||||
static const int FISH_HOOK = 90;
|
||||
|
||||
// 4J Added TU9
|
||||
static const int DRAGON_FIRE_BALL = 200;
|
||||
|
||||
int id;
|
||||
int x, y, z;
|
||||
int xa, ya, za;
|
||||
int type;
|
||||
int data;
|
||||
int id;
|
||||
int x, y, z;
|
||||
int xa, ya, za;
|
||||
int type;
|
||||
int data;
|
||||
byte yRot,xRot; // 4J added
|
||||
|
||||
private:
|
||||
@@ -44,7 +43,7 @@ private:
|
||||
|
||||
public:
|
||||
AddEntityPacket();
|
||||
AddEntityPacket(shared_ptr<Entity> e, int type, int yRotp, int xRotp, int xp, int yp, int zp);
|
||||
AddEntityPacket(shared_ptr<Entity> e, int type, int yRotp, int xRotp, int xp, int yp, int zp);
|
||||
AddEntityPacket(shared_ptr<Entity> e, int type, int data, int yRotp, int xRotp, int xp, int yp, int zp );
|
||||
|
||||
virtual void read(DataInputStream *dis);
|
||||
|
||||
@@ -26,13 +26,13 @@ AddGlobalEntityPacket::AddGlobalEntityPacket(shared_ptr<Entity> e)
|
||||
x = Mth::floor(e->x * 32);
|
||||
y = Mth::floor(e->y * 32);
|
||||
z = Mth::floor(e->z * 32);
|
||||
if (dynamic_pointer_cast<LightningBolt>(e) != NULL)
|
||||
if ( e->instanceof(eTYPE_LIGHTNINGBOLT) )
|
||||
{
|
||||
this->type = LIGHTNING;
|
||||
type = LIGHTNING;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->type = 0;
|
||||
type = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ AddMobPacket::~AddMobPacket()
|
||||
delete unpack;
|
||||
}
|
||||
|
||||
AddMobPacket::AddMobPacket(shared_ptr<Mob> mob, int yRotp, int xRotp, int xp, int yp, int zp, int yHeadRotp)
|
||||
AddMobPacket::AddMobPacket(shared_ptr<LivingEntity> mob, int yRotp, int xRotp, int xp, int yp, int zp, int yHeadRotp)
|
||||
{
|
||||
id = mob->entityId;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ using namespace std;
|
||||
#include "Packet.h"
|
||||
#include "SynchedEntityData.h"
|
||||
|
||||
class Mob;
|
||||
class LivingEntity;
|
||||
|
||||
class AddMobPacket : public Packet, public enable_shared_from_this<AddMobPacket>
|
||||
{
|
||||
@@ -22,7 +22,7 @@ private:
|
||||
public:
|
||||
AddMobPacket();
|
||||
~AddMobPacket();
|
||||
AddMobPacket(shared_ptr<Mob> mob, int yRotp, int xRotp, int xp, int yp, int zp, int yHeadRotp);
|
||||
AddMobPacket(shared_ptr<LivingEntity> mob, int yRotp, int xRotp, int xp, int yp, int zp, int yHeadRotp);
|
||||
|
||||
virtual void read(DataInputStream *dis);
|
||||
virtual void write(DataOutputStream *dos);
|
||||
|
||||
@@ -35,7 +35,7 @@ AddPlayerPacket::~AddPlayerPacket()
|
||||
AddPlayerPacket::AddPlayerPacket(shared_ptr<Player> player, PlayerUID xuid, PlayerUID OnlineXuid,int xp, int yp, int zp, int yRotp, int xRotp, int yHeadRotp)
|
||||
{
|
||||
id = player->entityId;
|
||||
name = player->name;
|
||||
name = player->getName();
|
||||
|
||||
// 4J Stu - Send "previously sent" value of position as well so that we stay in sync
|
||||
x = xp;//Mth::floor(player->x * 32);
|
||||
|
||||
@@ -13,40 +13,51 @@ AgableMob::AgableMob(Level *level) : PathfinderMob(level)
|
||||
registeredBBHeight = 0;
|
||||
}
|
||||
|
||||
bool AgableMob::interact(shared_ptr<Player> player)
|
||||
bool AgableMob::mobInteract(shared_ptr<Player> player)
|
||||
{
|
||||
shared_ptr<ItemInstance> item = player->inventory->getSelected();
|
||||
|
||||
if (item != NULL && item->id == Item::monsterPlacer_Id)
|
||||
if (item != NULL && item->id == Item::spawnEgg_Id)
|
||||
{
|
||||
if (!level->isClientSide)
|
||||
{
|
||||
eINSTANCEOF classToSpawn = EntityIO::getClass(item->getAuxValue());
|
||||
if (classToSpawn != eTYPE_NOTSET && (classToSpawn & eTYPE_AGABLE_MOB) == eTYPE_AGABLE_MOB && classToSpawn == GetType() ) // 4J Added GetType() check to only spawn same type
|
||||
{
|
||||
shared_ptr<AgableMob> offspring = getBreedOffspring(dynamic_pointer_cast<AgableMob>(shared_from_this()));
|
||||
if (offspring != NULL)
|
||||
int error;
|
||||
shared_ptr<Entity> result = SpawnEggItem::canSpawn(item->getAuxValue(), level, &error);
|
||||
|
||||
if (result != NULL)
|
||||
{
|
||||
offspring->setAge(-20 * 60 * 20);
|
||||
offspring->moveTo(x, y, z, 0, 0);
|
||||
|
||||
level->addEntity(offspring);
|
||||
|
||||
if (!player->abilities.instabuild)
|
||||
shared_ptr<AgableMob> offspring = getBreedOffspring(dynamic_pointer_cast<AgableMob>(shared_from_this()));
|
||||
if (offspring != NULL)
|
||||
{
|
||||
item->count--;
|
||||
offspring->setAge(BABY_START_AGE);
|
||||
offspring->moveTo(x, y, z, 0, 0);
|
||||
|
||||
if (item->count <= 0)
|
||||
level->addEntity(offspring);
|
||||
|
||||
if (!player->abilities.instabuild)
|
||||
{
|
||||
player->inventory->setItem(player->inventory->selected, nullptr);
|
||||
item->count--;
|
||||
|
||||
if (item->count <= 0)
|
||||
{
|
||||
player->inventory->setItem(player->inventory->selected, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SpawnEggItem::DisplaySpawnError(player, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return PathfinderMob::interact(player);
|
||||
return false;
|
||||
}
|
||||
|
||||
void AgableMob::defineSynchedData()
|
||||
@@ -60,6 +71,17 @@ int AgableMob::getAge()
|
||||
return entityData->getInteger(DATA_AGE_ID);
|
||||
}
|
||||
|
||||
void AgableMob::ageUp(int seconds)
|
||||
{
|
||||
int age = getAge();
|
||||
age += seconds * SharedConstants::TICKS_PER_SECOND;
|
||||
if (age > 0)
|
||||
{
|
||||
age = 0;
|
||||
}
|
||||
setAge(age);
|
||||
}
|
||||
|
||||
void AgableMob::setAge(int age)
|
||||
{
|
||||
entityData->set(DATA_AGE_ID, age);
|
||||
|
||||
@@ -7,13 +7,17 @@ class AgableMob : public PathfinderMob
|
||||
private:
|
||||
static const int DATA_AGE_ID = 12;
|
||||
|
||||
public:
|
||||
static const int BABY_START_AGE = -20 * 60 * 20;
|
||||
|
||||
private:
|
||||
float registeredBBWidth;
|
||||
float registeredBBHeight;
|
||||
|
||||
public:
|
||||
AgableMob(Level *level);
|
||||
|
||||
virtual bool interact(shared_ptr<Player> player);
|
||||
virtual bool mobInteract(shared_ptr<Player> player);
|
||||
|
||||
protected:
|
||||
virtual void defineSynchedData();
|
||||
@@ -21,6 +25,7 @@ protected:
|
||||
public:
|
||||
virtual shared_ptr<AgableMob> getBreedOffspring(shared_ptr<AgableMob> target) = 0;
|
||||
virtual int getAge();
|
||||
virtual void ageUp(int seconds);
|
||||
virtual void setAge(int age);
|
||||
virtual void addAdditonalSaveData(CompoundTag *tag);
|
||||
virtual void readAdditionalSaveData(CompoundTag *tag);
|
||||
|
||||
17
Minecraft.World/AmbientCreature.cpp
Normal file
17
Minecraft.World/AmbientCreature.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "AmbientCreature.h"
|
||||
|
||||
AmbientCreature::AmbientCreature(Level *level) : Mob(level)
|
||||
{
|
||||
}
|
||||
|
||||
bool AmbientCreature::canBeLeashed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AmbientCreature::mobInteract(shared_ptr<Player> player)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
16
Minecraft.World/AmbientCreature.h
Normal file
16
Minecraft.World/AmbientCreature.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "Mob.h"
|
||||
#include "Creature.h"
|
||||
|
||||
class AmbientCreature : public Mob, public Creature
|
||||
{
|
||||
|
||||
public:
|
||||
AmbientCreature(Level *level);
|
||||
|
||||
virtual bool canBeLeashed();
|
||||
|
||||
protected:
|
||||
virtual bool mobInteract(shared_ptr<Player> player);
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "com.mojang.nbt.h"
|
||||
#include "net.minecraft.world.level.tile.h"
|
||||
#include "net.minecraft.world.item.h"
|
||||
@@ -9,11 +10,11 @@
|
||||
#include "net.minecraft.world.entity.h"
|
||||
#include "net.minecraft.world.entity.projectile.h"
|
||||
#include "net.minecraft.world.damagesource.h"
|
||||
#include "net.minecraft.world.entity.monster.h"
|
||||
#include "net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "Random.h"
|
||||
#include "Animal.h"
|
||||
|
||||
|
||||
|
||||
Animal::Animal(Level *level) : AgableMob( level )
|
||||
{
|
||||
// inLove = 0; // 4J removed - now synched data
|
||||
@@ -64,7 +65,8 @@ void Animal::aiStep()
|
||||
|
||||
void Animal::checkHurtTarget(shared_ptr<Entity> target, float d)
|
||||
{
|
||||
if (dynamic_pointer_cast<Player>(target) != NULL)
|
||||
// 4J-JEV: Changed from dynamic cast to use eINSTANCEOF
|
||||
if ( target->instanceof(eTYPE_PLAYER) )
|
||||
{
|
||||
if (d < 3)
|
||||
{
|
||||
@@ -76,16 +78,14 @@ void Animal::checkHurtTarget(shared_ptr<Entity> target, float d)
|
||||
}
|
||||
|
||||
shared_ptr<Player> p = dynamic_pointer_cast<Player>(target);
|
||||
if (p->getSelectedItem() != NULL && this->isFood(p->getSelectedItem()))
|
||||
{
|
||||
}
|
||||
else
|
||||
if (p->getSelectedItem() == NULL || !isFood(p->getSelectedItem()))
|
||||
{
|
||||
attackTarget = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
else if (dynamic_pointer_cast<Animal>(target) != NULL)
|
||||
// 4J-JEV: Changed from dynamic cast to use eINSTANCEOF
|
||||
else if ( target->instanceof(eTYPE_ANIMAL) )
|
||||
{
|
||||
shared_ptr<Animal> a = dynamic_pointer_cast<Animal>(target);
|
||||
if (getAge() > 0 && a->getAge() < 0)
|
||||
@@ -166,21 +166,25 @@ float Animal::getWalkTargetValue(int x, int y, int z)
|
||||
return level->getBrightness(x, y, z) - 0.5f;
|
||||
}
|
||||
|
||||
bool Animal::hurt(DamageSource *dmgSource, int dmg)
|
||||
bool Animal::hurt(DamageSource *dmgSource, float dmg)
|
||||
{
|
||||
if (isInvulnerable()) return false;
|
||||
if (dynamic_cast<EntityDamageSource *>(dmgSource) != NULL)
|
||||
{
|
||||
shared_ptr<Entity> source = dmgSource->getDirectEntity();
|
||||
|
||||
if (dynamic_pointer_cast<Player>(source) != NULL && !dynamic_pointer_cast<Player>(source)->isAllowedToAttackAnimals() )
|
||||
// 4J-JEV: Changed from dynamic cast to use eINSTANCEOF
|
||||
if ( source->instanceof(eTYPE_PLAYER) && !dynamic_pointer_cast<Player>(source)->isAllowedToAttackAnimals() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (source != NULL && source->GetType() == eTYPE_ARROW)
|
||||
if ( (source != NULL) && source->instanceof(eTYPE_ARROW) )
|
||||
{
|
||||
shared_ptr<Arrow> arrow = dynamic_pointer_cast<Arrow>(source);
|
||||
if (dynamic_pointer_cast<Player>(arrow->owner) != NULL && ! dynamic_pointer_cast<Player>(arrow->owner)->isAllowedToAttackAnimals() )
|
||||
|
||||
// 4J: Check that the arrow's owner can attack animals (dispenser arrows are not owned)
|
||||
if (arrow->owner != NULL && arrow->owner->instanceof(eTYPE_PLAYER) && !dynamic_pointer_cast<Player>(arrow->owner)->isAllowedToAttackAnimals() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -188,6 +192,16 @@ bool Animal::hurt(DamageSource *dmgSource, int dmg)
|
||||
}
|
||||
|
||||
fleeTime = 20 * 3;
|
||||
|
||||
if (!useNewAi())
|
||||
{
|
||||
AttributeInstance *speed = getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED);
|
||||
if (speed->getModifier(eModifierId_MOB_FLEEING) == NULL)
|
||||
{
|
||||
speed->addModifier(new AttributeModifier(*Animal::SPEED_MODIFIER_FLEEING));
|
||||
}
|
||||
}
|
||||
|
||||
attackTarget = nullptr;
|
||||
setInLoveValue(0);
|
||||
|
||||
@@ -293,10 +307,10 @@ bool Animal::isFood(shared_ptr<ItemInstance> itemInstance)
|
||||
return itemInstance->id == Item::wheat_Id;
|
||||
}
|
||||
|
||||
bool Animal::interact(shared_ptr<Player> player)
|
||||
bool Animal::mobInteract(shared_ptr<Player> player)
|
||||
{
|
||||
shared_ptr<ItemInstance> item = player->inventory->getSelected();
|
||||
if (item != NULL && isFood(item) && getAge() == 0)
|
||||
if (item != NULL && isFood(item) && getAge() == 0 && getInLoveValue() <= 0)
|
||||
{
|
||||
if (!player->abilities.instabuild)
|
||||
{
|
||||
@@ -344,7 +358,7 @@ bool Animal::interact(shared_ptr<Player> player)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if( (GetType() & eTYPE_MONSTER) == eTYPE_MONSTER)
|
||||
else if( instanceof(eTYPE_MONSTER) )
|
||||
{
|
||||
|
||||
}
|
||||
@@ -352,20 +366,11 @@ bool Animal::interact(shared_ptr<Player> player)
|
||||
}
|
||||
setInLove(player);
|
||||
}
|
||||
|
||||
|
||||
attackTarget = nullptr;
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
double xa = random->nextGaussian() * 0.02;
|
||||
double ya = random->nextGaussian() * 0.02;
|
||||
double za = random->nextGaussian() * 0.02;
|
||||
level->addParticle(eParticleType_heart, x + random->nextFloat() * bbWidth * 2 - bbWidth, y + .5f + random->nextFloat() * bbHeight, z + random->nextFloat() * bbWidth * 2 - bbWidth, xa, ya, za);
|
||||
}
|
||||
setInLove();
|
||||
|
||||
return true;
|
||||
}
|
||||
return AgableMob::interact(player);
|
||||
return AgableMob::mobInteract(player);
|
||||
}
|
||||
|
||||
// 4J added
|
||||
@@ -391,6 +396,14 @@ shared_ptr<Player> Animal::getLoveCause()
|
||||
return loveCause.lock();
|
||||
}
|
||||
|
||||
void Animal::setInLove()
|
||||
{
|
||||
entityData->set(DATA_IN_LOVE, 20 * 30);
|
||||
|
||||
attackTarget = nullptr;
|
||||
level->broadcastEntityEvent(shared_from_this(), EntityEvent::IN_LOVE_HEARTS);
|
||||
}
|
||||
|
||||
bool Animal::isInLove()
|
||||
{
|
||||
return entityData->getInteger(DATA_IN_LOVE) > 0;
|
||||
@@ -407,6 +420,24 @@ bool Animal::canMate(shared_ptr<Animal> partner)
|
||||
return isInLove() && partner->isInLove();
|
||||
}
|
||||
|
||||
void Animal::handleEntityEvent(byte id)
|
||||
{
|
||||
if (id == EntityEvent::IN_LOVE_HEARTS)
|
||||
{
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
double xa = random->nextGaussian() * 0.02;
|
||||
double ya = random->nextGaussian() * 0.02;
|
||||
double za = random->nextGaussian() * 0.02;
|
||||
level->addParticle(eParticleType_heart, x + random->nextFloat() * bbWidth * 2 - bbWidth, y + .5f + random->nextFloat() * bbHeight, z + random->nextFloat() * bbWidth * 2 - bbWidth, xa, ya, za);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AgableMob::handleEntityEvent(id);
|
||||
}
|
||||
}
|
||||
|
||||
void Animal::updateDespawnProtectedState()
|
||||
{
|
||||
if( level->isClientSide ) return;
|
||||
@@ -455,4 +486,4 @@ void Animal::setDespawnProtected()
|
||||
m_maxWanderZ = zt;
|
||||
|
||||
m_isDespawnProtected = true;
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
virtual float getWalkTargetValue(int x, int y, int z);
|
||||
|
||||
public:
|
||||
virtual bool hurt(DamageSource *source, int dmg);
|
||||
virtual bool hurt(DamageSource *source, float dmg);
|
||||
virtual void addAdditonalSaveData(CompoundTag *tag);
|
||||
virtual void readAdditionalSaveData(CompoundTag *tag);
|
||||
|
||||
@@ -52,7 +52,7 @@ protected:
|
||||
|
||||
public:
|
||||
virtual bool isFood(shared_ptr<ItemInstance> itemInstance);
|
||||
virtual bool interact(shared_ptr<Player> player);
|
||||
virtual bool mobInteract(shared_ptr<Player> player);
|
||||
|
||||
protected:
|
||||
int getInLoveValue(); // 4J added
|
||||
@@ -60,10 +60,12 @@ protected:
|
||||
public:
|
||||
void setInLoveValue(int value); // 4J added
|
||||
void setInLove(shared_ptr<Player> player); // 4J added, then modified to match latest Java for XboxOne achievements
|
||||
virtual void setInLove();
|
||||
shared_ptr<Player> getLoveCause();
|
||||
bool isInLove();
|
||||
void resetLove();
|
||||
virtual bool canMate(shared_ptr<Animal> partner);
|
||||
virtual void handleEntityEvent(byte id);
|
||||
|
||||
// 4J added for determining whether animals are enclosed or not
|
||||
private:
|
||||
|
||||
11
Minecraft.World/AnimalChest.cpp
Normal file
11
Minecraft.World/AnimalChest.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "AnimalChest.h"
|
||||
|
||||
AnimalChest::AnimalChest(const wstring &name, int size) : SimpleContainer(IDS_CONTAINER_ANIMAL, name, false, size)
|
||||
{
|
||||
}
|
||||
|
||||
AnimalChest::AnimalChest(int iTitle, const wstring &name, bool hasCustomName, int size) : SimpleContainer(iTitle, name, hasCustomName, size)
|
||||
{
|
||||
}
|
||||
10
Minecraft.World/AnimalChest.h
Normal file
10
Minecraft.World/AnimalChest.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "SimpleContainer.h"
|
||||
|
||||
class AnimalChest : public SimpleContainer
|
||||
{
|
||||
public:
|
||||
AnimalChest(const wstring &name, int size);
|
||||
AnimalChest(int iTitle, const wstring &name, bool hasCustomName, int size); // 4J Added iTitle param
|
||||
};
|
||||
426
Minecraft.World/AnvilMenu.cpp
Normal file
426
Minecraft.World/AnvilMenu.cpp
Normal file
@@ -0,0 +1,426 @@
|
||||
#include "stdafx.h"
|
||||
#include "net.minecraft.world.inventory.h"
|
||||
#include "net.minecraft.world.entity.player.h"
|
||||
#include "net.minecraft.world.level.h"
|
||||
#include "net.minecraft.world.item.h"
|
||||
#include "net.minecraft.world.item.enchantment.h"
|
||||
#include "AnvilMenu.h"
|
||||
|
||||
AnvilMenu::AnvilMenu(shared_ptr<Inventory> inventory, Level *level, int xt, int yt, int zt, shared_ptr<Player> player)
|
||||
{
|
||||
resultSlots = shared_ptr<ResultContainer>( new ResultContainer() );
|
||||
repairSlots = shared_ptr<RepairContainer>( new RepairContainer(this,IDS_REPAIR_AND_NAME, true, 2) );
|
||||
cost = 0;
|
||||
repairItemCountCost = 0;
|
||||
|
||||
this->level = level;
|
||||
x = xt;
|
||||
y = yt;
|
||||
z = zt;
|
||||
this->player = player;
|
||||
|
||||
addSlot(new Slot(repairSlots, INPUT_SLOT, 27, 43 + 4));
|
||||
addSlot(new Slot(repairSlots, ADDITIONAL_SLOT, 76, 43 + 4));
|
||||
|
||||
// 4J Stu - Anonymous class here is now RepairResultSlot
|
||||
addSlot(new RepairResultSlot(this, xt, yt, zt, resultSlots, RESULT_SLOT, 134, 43 + 4));
|
||||
|
||||
for (int y = 0; y < 3; y++)
|
||||
{
|
||||
for (int x = 0; x < 9; x++)
|
||||
{
|
||||
addSlot(new Slot(inventory, x + y * 9 + 9, 8 + x * 18, 84 + y * 18));
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < 9; x++)
|
||||
{
|
||||
addSlot(new Slot(inventory, x, 8 + x * 18, 142));
|
||||
}
|
||||
}
|
||||
|
||||
void AnvilMenu::slotsChanged(shared_ptr<Container> container)
|
||||
{
|
||||
AbstractContainerMenu::slotsChanged();
|
||||
|
||||
if (container == repairSlots) createResult();
|
||||
}
|
||||
|
||||
void AnvilMenu::createResult()
|
||||
{
|
||||
shared_ptr<ItemInstance> input = repairSlots->getItem(INPUT_SLOT);
|
||||
cost = 0;
|
||||
int price = 0;
|
||||
int tax = 0;
|
||||
int namingCost = 0;
|
||||
|
||||
if (DEBUG_COST) app.DebugPrintf("----");
|
||||
|
||||
if (input == NULL)
|
||||
{
|
||||
resultSlots->setItem(0, nullptr);
|
||||
cost = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
shared_ptr<ItemInstance> result = input->copy();
|
||||
shared_ptr<ItemInstance> addition = repairSlots->getItem(ADDITIONAL_SLOT);
|
||||
unordered_map<int,int> *enchantments = EnchantmentHelper::getEnchantments(result);
|
||||
bool usingBook = false;
|
||||
|
||||
tax += input->getBaseRepairCost() + (addition == NULL ? 0 : addition->getBaseRepairCost());
|
||||
if (DEBUG_COST)
|
||||
{
|
||||
app.DebugPrintf("Starting with base repair tax of %d (%d + %d)\n", tax, input->getBaseRepairCost(), (addition == NULL ? 0 : addition->getBaseRepairCost()));
|
||||
}
|
||||
|
||||
repairItemCountCost = 0;
|
||||
|
||||
if (addition != NULL)
|
||||
{
|
||||
usingBook = addition->id == Item::enchantedBook_Id && Item::enchantedBook->getEnchantments(addition)->size() > 0;
|
||||
|
||||
if (result->isDamageableItem() && Item::items[result->id]->isValidRepairItem(input, addition))
|
||||
{
|
||||
int repairAmount = min(result->getDamageValue(), result->getMaxDamage() / 4);
|
||||
if (repairAmount <= 0)
|
||||
{
|
||||
resultSlots->setItem(0, nullptr);
|
||||
cost = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = 0;
|
||||
while (repairAmount > 0 && count < addition->count)
|
||||
{
|
||||
int resultDamage = result->getDamageValue() - repairAmount;
|
||||
result->setAuxValue(resultDamage);
|
||||
price += max(1, repairAmount / 100) + enchantments->size();
|
||||
|
||||
repairAmount = min(result->getDamageValue(), result->getMaxDamage() / 4);
|
||||
count++;
|
||||
}
|
||||
repairItemCountCost = count;
|
||||
}
|
||||
}
|
||||
else if (!usingBook && (result->id != addition->id || !result->isDamageableItem()))
|
||||
{
|
||||
resultSlots->setItem(0, nullptr);
|
||||
cost = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result->isDamageableItem() && !usingBook)
|
||||
{
|
||||
int remaining1 = input->getMaxDamage() - input->getDamageValue();
|
||||
int remaining2 = addition->getMaxDamage() - addition->getDamageValue();
|
||||
int additional = remaining2 + result->getMaxDamage() * 12 / 100;
|
||||
int remaining = remaining1 + additional;
|
||||
int resultDamage = result->getMaxDamage() - remaining;
|
||||
if (resultDamage < 0) resultDamage = 0;
|
||||
|
||||
if (resultDamage < result->getAuxValue())
|
||||
{
|
||||
result->setAuxValue(resultDamage);
|
||||
price += max(1, additional / 100);
|
||||
if (DEBUG_COST)
|
||||
{
|
||||
app.DebugPrintf("Repairing; price is now %d (went up by %d)\n", price, max(1, additional / 100) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unordered_map<int, int> *additionalEnchantments = EnchantmentHelper::getEnchantments(addition);
|
||||
|
||||
for(AUTO_VAR(it, additionalEnchantments->begin()); it != additionalEnchantments->end(); ++it)
|
||||
{
|
||||
int id = it->first;
|
||||
Enchantment *enchantment = Enchantment::enchantments[id];
|
||||
AUTO_VAR(localIt, enchantments->find(id));
|
||||
int current = localIt != enchantments->end() ? localIt->second : 0;
|
||||
int level = it->second;
|
||||
level = (current == level) ? level += 1 : max(level, current);
|
||||
int extra = level - current;
|
||||
bool compatible = enchantment->canEnchant(input);
|
||||
|
||||
if (player->abilities.instabuild || input->id == EnchantedBookItem::enchantedBook_Id) compatible = true;
|
||||
|
||||
for(AUTO_VAR(it2, enchantments->begin()); it2 != enchantments->end(); ++it2)
|
||||
{
|
||||
int other = it2->first;
|
||||
if (other != id && !enchantment->isCompatibleWith(Enchantment::enchantments[other]))
|
||||
{
|
||||
compatible = false;
|
||||
|
||||
price += extra;
|
||||
if (DEBUG_COST)
|
||||
{
|
||||
app.DebugPrintf("Enchantment incompatibility fee; price is now %d (went up by %d)\n", price, extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!compatible) continue;
|
||||
if (level > enchantment->getMaxLevel()) level = enchantment->getMaxLevel();
|
||||
(*enchantments)[id] = level;
|
||||
int fee = 0;
|
||||
|
||||
switch (enchantment->getFrequency())
|
||||
{
|
||||
case Enchantment::FREQ_COMMON:
|
||||
fee = 1;
|
||||
break;
|
||||
case Enchantment::FREQ_UNCOMMON:
|
||||
fee = 2;
|
||||
break;
|
||||
case Enchantment::FREQ_RARE:
|
||||
fee = 4;
|
||||
break;
|
||||
case Enchantment::FREQ_VERY_RARE:
|
||||
fee = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
if (usingBook) fee = max(1, fee / 2);
|
||||
|
||||
price += fee * extra;
|
||||
if (DEBUG_COST)
|
||||
{
|
||||
app.DebugPrintf("Enchantment increase fee; price is now %d (went up by %d)\n", price, fee*extra);
|
||||
}
|
||||
}
|
||||
delete additionalEnchantments;
|
||||
}
|
||||
}
|
||||
|
||||
if (itemName.empty())
|
||||
{
|
||||
if (input->hasCustomHoverName())
|
||||
{
|
||||
namingCost = input->isDamageableItem() ? 7 : input->count * 5;
|
||||
|
||||
price += namingCost;
|
||||
if (DEBUG_COST)
|
||||
{
|
||||
app.DebugPrintf("Un-naming cost; price is now %d (went up by %d)", price, namingCost);
|
||||
}
|
||||
result->resetHoverName();
|
||||
}
|
||||
}
|
||||
else if (itemName.length() > 0 && !equalsIgnoreCase(itemName, input->getHoverName()) && itemName.length() > 0)
|
||||
{
|
||||
namingCost = input->isDamageableItem() ? 7 : input->count * 5;
|
||||
|
||||
price += namingCost;
|
||||
if (DEBUG_COST)
|
||||
{
|
||||
app.DebugPrintf("Naming cost; price is now %d (went up by %d)", price, namingCost);
|
||||
}
|
||||
|
||||
if (input->hasCustomHoverName())
|
||||
{
|
||||
tax += namingCost / 2;
|
||||
|
||||
if (DEBUG_COST)
|
||||
{
|
||||
app.DebugPrintf("Already-named tax; tax is now %d (went up by %d)", tax, (namingCost / 2));
|
||||
}
|
||||
}
|
||||
|
||||
result->setHoverName(itemName);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for(AUTO_VAR(it, enchantments->begin()); it != enchantments->end(); ++it)
|
||||
{
|
||||
int id = it->first;
|
||||
Enchantment *enchantment = Enchantment::enchantments[id];
|
||||
int level = it->second;
|
||||
int fee = 0;
|
||||
|
||||
count++;
|
||||
|
||||
switch (enchantment->getFrequency())
|
||||
{
|
||||
case Enchantment::FREQ_COMMON:
|
||||
fee = 1;
|
||||
break;
|
||||
case Enchantment::FREQ_UNCOMMON:
|
||||
fee = 2;
|
||||
break;
|
||||
case Enchantment::FREQ_RARE:
|
||||
fee = 4;
|
||||
break;
|
||||
case Enchantment::FREQ_VERY_RARE:
|
||||
fee = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
if (usingBook) fee = max(1, fee / 2);
|
||||
|
||||
tax += count + level * fee;
|
||||
if (DEBUG_COST)
|
||||
{
|
||||
app.DebugPrintf("Enchantment tax; tax is now %d (went up by %d)", tax, (count + level * fee));
|
||||
}
|
||||
}
|
||||
|
||||
if (usingBook) tax = max(1, tax / 2);
|
||||
|
||||
cost = tax + price;
|
||||
if (price <= 0)
|
||||
{
|
||||
if (DEBUG_COST) app.DebugPrintf("No purchase, only tax; aborting");
|
||||
result = nullptr;
|
||||
}
|
||||
if (namingCost == price && namingCost > 0 && cost >= 40)
|
||||
{
|
||||
if (DEBUG_COST) app.DebugPrintf("Cost is too high; aborting");
|
||||
app.DebugPrintf("Naming an item only, cost too high; giving discount to cap cost to 39 levels");
|
||||
cost = 39;
|
||||
}
|
||||
if (cost >= 40 && !player->abilities.instabuild)
|
||||
{
|
||||
if (DEBUG_COST) app.DebugPrintf("Cost is too high; aborting");
|
||||
result = nullptr;
|
||||
}
|
||||
|
||||
if (result != NULL)
|
||||
{
|
||||
int baseCost = result->getBaseRepairCost();
|
||||
if (addition != NULL && baseCost < addition->getBaseRepairCost()) baseCost = addition->getBaseRepairCost();
|
||||
if (result->hasCustomHoverName()) baseCost -= 9;
|
||||
if (baseCost < 0) baseCost = 0;
|
||||
baseCost += 2;
|
||||
|
||||
result->setRepairCost(baseCost);
|
||||
EnchantmentHelper::setEnchantments(enchantments, result);
|
||||
}
|
||||
|
||||
resultSlots->setItem(0, result);
|
||||
}
|
||||
|
||||
broadcastChanges();
|
||||
|
||||
if (DEBUG_COST)
|
||||
{
|
||||
if (level->isClientSide)
|
||||
{
|
||||
app.DebugPrintf("CLIENT Cost is %d (%d price, %d tax)\n", cost, price, tax);
|
||||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("SERVER Cost is %d (%d price, %d tax)\n", cost, price, tax);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnvilMenu::sendData(int id, int value)
|
||||
{
|
||||
AbstractContainerMenu::sendData(id, value);
|
||||
}
|
||||
|
||||
void AnvilMenu::addSlotListener(ContainerListener *listener)
|
||||
{
|
||||
AbstractContainerMenu::addSlotListener(listener);
|
||||
listener->setContainerData(this, DATA_TOTAL_COST, cost);
|
||||
}
|
||||
|
||||
void AnvilMenu::setData(int id, int value)
|
||||
{
|
||||
if (id == DATA_TOTAL_COST) cost = value;
|
||||
}
|
||||
|
||||
void AnvilMenu::removed(shared_ptr<Player> player)
|
||||
{
|
||||
AbstractContainerMenu::removed(player);
|
||||
if (level->isClientSide) return;
|
||||
|
||||
for (int i = 0; i < repairSlots->getContainerSize(); i++)
|
||||
{
|
||||
shared_ptr<ItemInstance> item = repairSlots->removeItemNoUpdate(i);
|
||||
if (item != NULL)
|
||||
{
|
||||
player->drop(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AnvilMenu::stillValid(shared_ptr<Player> player)
|
||||
{
|
||||
if (level->getTile(x, y, z) != Tile::anvil_Id) return false;
|
||||
if (player->distanceToSqr(x + 0.5, y + 0.5, z + 0.5) > 8 * 8) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
shared_ptr<ItemInstance> AnvilMenu::quickMoveStack(shared_ptr<Player> player, int slotIndex)
|
||||
{
|
||||
shared_ptr<ItemInstance> clicked = nullptr;
|
||||
Slot *slot = slots.at(slotIndex);
|
||||
if (slot != NULL && slot->hasItem())
|
||||
{
|
||||
shared_ptr<ItemInstance> stack = slot->getItem();
|
||||
clicked = stack->copy();
|
||||
|
||||
if (slotIndex == RESULT_SLOT)
|
||||
{
|
||||
if (!moveItemStackTo(stack, INV_SLOT_START, USE_ROW_SLOT_END, true))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
slot->onQuickCraft(stack, clicked);
|
||||
}
|
||||
else if (slotIndex == INPUT_SLOT || slotIndex == ADDITIONAL_SLOT)
|
||||
{
|
||||
if (!moveItemStackTo(stack, INV_SLOT_START, USE_ROW_SLOT_END, false))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else if (slotIndex >= INV_SLOT_START && slotIndex < USE_ROW_SLOT_END)
|
||||
{
|
||||
if (!moveItemStackTo(stack, INPUT_SLOT, RESULT_SLOT, false))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (stack->count == 0)
|
||||
{
|
||||
slot->set(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
slot->setChanged();
|
||||
}
|
||||
if (stack->count == clicked->count)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
slot->onTake(player, stack);
|
||||
}
|
||||
}
|
||||
return clicked;
|
||||
}
|
||||
|
||||
void AnvilMenu::setItemName(const wstring &name)
|
||||
{
|
||||
itemName = name;
|
||||
if (getSlot(RESULT_SLOT)->hasItem())
|
||||
{
|
||||
shared_ptr<ItemInstance> item = getSlot(RESULT_SLOT)->getItem();
|
||||
|
||||
if (name.empty())
|
||||
{
|
||||
item->resetHoverName();
|
||||
}
|
||||
else
|
||||
{
|
||||
item->setHoverName(itemName);
|
||||
}
|
||||
}
|
||||
createResult();
|
||||
}
|
||||
55
Minecraft.World/AnvilMenu.h
Normal file
55
Minecraft.World/AnvilMenu.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include "AbstractContainerMenu.h"
|
||||
|
||||
class AnvilMenu : public AbstractContainerMenu
|
||||
{
|
||||
friend class RepairResultSlot;
|
||||
private:
|
||||
static const bool DEBUG_COST = false;
|
||||
|
||||
public:
|
||||
static const int INPUT_SLOT = 0;
|
||||
static const int ADDITIONAL_SLOT = 1;
|
||||
static const int RESULT_SLOT = 2;
|
||||
|
||||
static const int INV_SLOT_START = RESULT_SLOT + 1;
|
||||
static const int INV_SLOT_END = INV_SLOT_START + 9 * 3;
|
||||
static const int USE_ROW_SLOT_START = INV_SLOT_END;
|
||||
static const int USE_ROW_SLOT_END = USE_ROW_SLOT_START + 9;
|
||||
|
||||
public:
|
||||
static const int DATA_TOTAL_COST = 0;
|
||||
|
||||
private:
|
||||
shared_ptr<Container> resultSlots;
|
||||
|
||||
// 4J Stu - anonymous class here now RepairContainer
|
||||
shared_ptr<Container> repairSlots;
|
||||
|
||||
Level *level;
|
||||
int x, y, z;
|
||||
|
||||
public:
|
||||
int cost;
|
||||
|
||||
private:
|
||||
int repairItemCountCost;
|
||||
wstring itemName;
|
||||
shared_ptr<Player> player;
|
||||
|
||||
public:
|
||||
using AbstractContainerMenu::slotsChanged;
|
||||
|
||||
AnvilMenu(shared_ptr<Inventory> inventory, Level *level, int xt, int yt, int zt, shared_ptr<Player> player);
|
||||
|
||||
void slotsChanged(shared_ptr<Container> container);
|
||||
void createResult();
|
||||
void sendData(int id, int value);
|
||||
void addSlotListener(ContainerListener *listener);
|
||||
void setData(int id, int value);
|
||||
void removed(shared_ptr<Player> player);
|
||||
bool stillValid(shared_ptr<Player> player);
|
||||
shared_ptr<ItemInstance> quickMoveStack(shared_ptr<Player> player, int slotIndex);
|
||||
void setItemName(const wstring &name);
|
||||
};
|
||||
@@ -55,16 +55,16 @@ void AnvilTile::registerIcons(IconRegister *iconRegister)
|
||||
}
|
||||
}
|
||||
|
||||
void AnvilTile::setPlacedBy(Level *level, int x, int y, int z, shared_ptr<Mob> by)
|
||||
void AnvilTile::setPlacedBy(Level *level, int x, int y, int z, shared_ptr<LivingEntity> by, shared_ptr<ItemInstance> itemInstance)
|
||||
{
|
||||
int dir = (Mth::floor(by->yRot * 4 / (360) + 0.5)) & 3;
|
||||
int dmg = level->getData(x, y, z) >> 2;
|
||||
|
||||
dir = ++dir % 4;
|
||||
if (dir == 0) level->setData(x, y, z, Direction::NORTH | (dmg << 2));
|
||||
if (dir == 1) level->setData(x, y, z, Direction::EAST | (dmg << 2));
|
||||
if (dir == 2) level->setData(x, y, z, Direction::SOUTH | (dmg << 2));
|
||||
if (dir == 3) level->setData(x, y, z, Direction::WEST | (dmg << 2));
|
||||
if (dir == 0) level->setData(x, y, z, Direction::NORTH | (dmg << 2), Tile::UPDATE_CLIENTS);
|
||||
if (dir == 1) level->setData(x, y, z, Direction::EAST | (dmg << 2), Tile::UPDATE_CLIENTS);
|
||||
if (dir == 2) level->setData(x, y, z, Direction::SOUTH | (dmg << 2), Tile::UPDATE_CLIENTS);
|
||||
if (dir == 3) level->setData(x, y, z, Direction::WEST | (dmg << 2), Tile::UPDATE_CLIENTS);
|
||||
}
|
||||
|
||||
bool AnvilTile::use(Level *level, int x, int y, int z, shared_ptr<Player> player, int clickedFace, float clickX, float clickY, float clickZ, bool soundOnly)
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
bool isSolidRender(bool isServerLevel = false);
|
||||
Icon *getTexture(int face, int data);
|
||||
void registerIcons(IconRegister *iconRegister);
|
||||
void setPlacedBy(Level *level, int x, int y, int z, shared_ptr<Mob> by);
|
||||
void setPlacedBy(Level *level, int x, int y, int z, shared_ptr<LivingEntity> by, shared_ptr<ItemInstance> itemInstance);
|
||||
bool use(Level *level, int x, int y, int z, shared_ptr<Player> player, int clickedFace, float clickX, float clickY, float clickZ, bool soundOnly = false);
|
||||
int getRenderShape();
|
||||
int getSpawnResourcesAuxValue(int data);
|
||||
|
||||
@@ -43,10 +43,7 @@ bool ArmorDyeRecipe::matches(shared_ptr<CraftingContainer> craftSlots, Level *le
|
||||
shared_ptr<ItemInstance> ArmorDyeRecipe::assembleDyedArmor(shared_ptr<CraftingContainer> craftSlots)
|
||||
{
|
||||
shared_ptr<ItemInstance> target = nullptr;
|
||||
int colorTotals[3];
|
||||
colorTotals[0] = 0;
|
||||
colorTotals[1] = 0;
|
||||
colorTotals[2] = 0;
|
||||
int colorTotals[3] = {0,0,0};
|
||||
int intensityTotal = 0;
|
||||
int colourCounts = 0;
|
||||
ArmorItem *armor = NULL;
|
||||
@@ -64,6 +61,7 @@ shared_ptr<ItemInstance> ArmorDyeRecipe::assembleDyedArmor(shared_ptr<CraftingCo
|
||||
if (armor->getMaterial() == ArmorItem::ArmorMaterial::CLOTH && target == NULL)
|
||||
{
|
||||
target = item->copy();
|
||||
target->count = 1;
|
||||
|
||||
if (armor->hasCustomColor(item))
|
||||
{
|
||||
@@ -87,7 +85,7 @@ shared_ptr<ItemInstance> ArmorDyeRecipe::assembleDyedArmor(shared_ptr<CraftingCo
|
||||
}
|
||||
else if (item->id == Item::dye_powder_Id)
|
||||
{
|
||||
int tileData = ClothTile::getTileDataForItemAuxValue(item->getAuxValue());
|
||||
int tileData = ColoredTile::getTileDataForItemAuxValue(item->getAuxValue());
|
||||
int red = (int) (Sheep::COLOR[tileData][0] * 0xFF);
|
||||
int green = (int) (Sheep::COLOR[tileData][1] * 0xFF);
|
||||
int blue = (int) (Sheep::COLOR[tileData][2] * 0xFF);
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#include "stdafx.h"
|
||||
#include "..\Minecraft.Client\Minecraft.h"
|
||||
#include "net.minecraft.world.h"
|
||||
#include "net.minecraft.world.level.tile.h"
|
||||
#include "net.minecraft.world.entity.player.h"
|
||||
#include "net.minecraft.world.entity.h"
|
||||
#include "net.minecraft.world.phys.h"
|
||||
#include "net.minecraft.world.level.h"
|
||||
#include "com.mojang.nbt.h"
|
||||
#include "ArmorItem.h"
|
||||
|
||||
@@ -17,6 +21,41 @@ const wstring ArmorItem::TEXTURE_EMPTY_SLOTS[] = {
|
||||
L"slot_empty_helmet", L"slot_empty_chestplate", L"slot_empty_leggings", L"slot_empty_boots"
|
||||
};
|
||||
|
||||
|
||||
shared_ptr<ItemInstance> ArmorItem::ArmorDispenseItemBehavior::execute(BlockSource *source, shared_ptr<ItemInstance> dispensed, eOUTCOME &outcome)
|
||||
{
|
||||
FacingEnum *facing = DispenserTile::getFacing(source->getData());
|
||||
int x = source->getBlockX() + facing->getStepX();
|
||||
int y = source->getBlockY() + facing->getStepY();
|
||||
int z = source->getBlockZ() + facing->getStepZ();
|
||||
AABB *bb = AABB::newTemp(x, y, z, x + 1, y + 1, z + 1);
|
||||
EntitySelector *selector = new MobCanWearArmourEntitySelector(dispensed);
|
||||
vector<shared_ptr<Entity> > *entities = source->getWorld()->getEntitiesOfClass(typeid(LivingEntity), bb, selector);
|
||||
delete selector;
|
||||
|
||||
if (entities->size() > 0)
|
||||
{
|
||||
shared_ptr<LivingEntity> target = dynamic_pointer_cast<LivingEntity>( entities->at(0) );
|
||||
int offset = target->instanceof(eTYPE_PLAYER) ? 1 : 0;
|
||||
int slot = Mob::getEquipmentSlotForItem(dispensed);
|
||||
shared_ptr<ItemInstance> equip = dispensed->copy();
|
||||
equip->count = 1;
|
||||
target->setEquippedSlot(slot - offset, equip);
|
||||
if (target->instanceof(eTYPE_MOB)) dynamic_pointer_cast<Mob>(target)->setDropChance(slot, 2);
|
||||
dispensed->count--;
|
||||
|
||||
outcome = ACTIVATED_ITEM;
|
||||
|
||||
delete entities;
|
||||
return dispensed;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete entities;
|
||||
return DefaultDispenseItemBehavior::execute(source, dispensed, outcome);
|
||||
}
|
||||
}
|
||||
|
||||
typedef ArmorItem::ArmorMaterial _ArmorMaterial;
|
||||
|
||||
const int _ArmorMaterial::clothArray[] = {1,3,2,1};
|
||||
@@ -86,6 +125,7 @@ ArmorItem::ArmorItem(int id, const ArmorMaterial *armorType, int icon, int slot)
|
||||
{
|
||||
setMaxDamage(armorType->getHealthForSlot(slot));
|
||||
maxStackSize = 1;
|
||||
DispenserTile::REGISTRY.add(this, new ArmorDispenseItemBehavior());
|
||||
}
|
||||
|
||||
int ArmorItem::getColor(shared_ptr<ItemInstance> item, int spriteLayer)
|
||||
@@ -100,7 +140,6 @@ int ArmorItem::getColor(shared_ptr<ItemInstance> item, int spriteLayer)
|
||||
return color;
|
||||
}
|
||||
|
||||
//@Override
|
||||
bool ArmorItem::hasMultipleSpriteLayers()
|
||||
{
|
||||
return armorType == ArmorMaterial::CLOTH;
|
||||
@@ -145,7 +184,6 @@ int ArmorItem::getColor(shared_ptr<ItemInstance> item)
|
||||
}
|
||||
}
|
||||
|
||||
//@Override
|
||||
Icon *ArmorItem::getLayerIcon(int auxValue, int spriteLayer)
|
||||
{
|
||||
if (spriteLayer == 1)
|
||||
@@ -198,7 +236,6 @@ bool ArmorItem::isValidRepairItem(shared_ptr<ItemInstance> source, shared_ptr<It
|
||||
return Item::isValidRepairItem(source, repairItem);
|
||||
}
|
||||
|
||||
//@Override
|
||||
void ArmorItem::registerIcons(IconRegister *iconRegister)
|
||||
{
|
||||
Item::registerIcons(iconRegister);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Item.h"
|
||||
#include "DefaultDispenseItemBehavior.h"
|
||||
|
||||
class ArmorItem : public Item
|
||||
{
|
||||
@@ -18,6 +19,13 @@ private:
|
||||
public:
|
||||
static const wstring TEXTURE_EMPTY_SLOTS[];
|
||||
|
||||
private:
|
||||
class ArmorDispenseItemBehavior : public DefaultDispenseItemBehavior
|
||||
{
|
||||
protected:
|
||||
virtual shared_ptr<ItemInstance> execute(BlockSource *source, shared_ptr<ItemInstance> dispensed, eOUTCOME &outcome);
|
||||
};
|
||||
|
||||
public:
|
||||
class ArmorMaterial
|
||||
{
|
||||
@@ -64,27 +72,20 @@ private:
|
||||
public:
|
||||
ArmorItem(int id, const ArmorMaterial *armorType, int icon, int slot);
|
||||
|
||||
//@Override
|
||||
int getColor(shared_ptr<ItemInstance> item, int spriteLayer);
|
||||
|
||||
//@Override
|
||||
bool hasMultipleSpriteLayers();
|
||||
|
||||
virtual int getColor(shared_ptr<ItemInstance> item, int spriteLayer);
|
||||
virtual bool hasMultipleSpriteLayers();
|
||||
virtual int getEnchantmentValue();
|
||||
virtual const ArmorMaterial *getMaterial();
|
||||
virtual bool hasCustomColor(shared_ptr<ItemInstance> item);
|
||||
virtual int getColor(shared_ptr<ItemInstance> item);
|
||||
|
||||
const ArmorMaterial *getMaterial();
|
||||
bool hasCustomColor(shared_ptr<ItemInstance> item);
|
||||
int getColor(shared_ptr<ItemInstance> item);
|
||||
virtual Icon *getLayerIcon(int auxValue, int spriteLayer);
|
||||
virtual void clearColor(shared_ptr<ItemInstance> item);
|
||||
virtual void setColor(shared_ptr<ItemInstance> item, int color);
|
||||
|
||||
//@Override
|
||||
Icon *getLayerIcon(int auxValue, int spriteLayer);
|
||||
void clearColor(shared_ptr<ItemInstance> item);
|
||||
void setColor(shared_ptr<ItemInstance> item, int color);
|
||||
|
||||
bool isValidRepairItem(shared_ptr<ItemInstance> source, shared_ptr<ItemInstance> repairItem);
|
||||
|
||||
//@Override
|
||||
void registerIcons(IconRegister *iconRegister);
|
||||
virtual bool isValidRepairItem(shared_ptr<ItemInstance> source, shared_ptr<ItemInstance> repairItem);
|
||||
virtual void registerIcons(IconRegister *iconRegister);
|
||||
|
||||
static Icon *getEmptyIcon(int slot);
|
||||
};
|
||||
@@ -49,25 +49,25 @@ void ArmorRecipes::_init()
|
||||
ADD_OBJECT(map[0],Item::diamond);
|
||||
ADD_OBJECT(map[0],Item::goldIngot);
|
||||
|
||||
ADD_OBJECT(map[1],Item::helmet_cloth);
|
||||
ADD_OBJECT(map[1],Item::helmet_leather);
|
||||
// ADD_OBJECT(map[1],Item::helmet_chain);
|
||||
ADD_OBJECT(map[1],Item::helmet_iron);
|
||||
ADD_OBJECT(map[1],Item::helmet_diamond);
|
||||
ADD_OBJECT(map[1],Item::helmet_gold);
|
||||
|
||||
ADD_OBJECT(map[2],Item::chestplate_cloth);
|
||||
ADD_OBJECT(map[2],Item::chestplate_leather);
|
||||
// ADD_OBJECT(map[2],Item::chestplate_chain);
|
||||
ADD_OBJECT(map[2],Item::chestplate_iron);
|
||||
ADD_OBJECT(map[2],Item::chestplate_diamond);
|
||||
ADD_OBJECT(map[2],Item::chestplate_gold);
|
||||
|
||||
ADD_OBJECT(map[3],Item::leggings_cloth);
|
||||
ADD_OBJECT(map[3],Item::leggings_leather);
|
||||
// ADD_OBJECT(map[3],Item::leggings_chain);
|
||||
ADD_OBJECT(map[3],Item::leggings_iron);
|
||||
ADD_OBJECT(map[3],Item::leggings_diamond);
|
||||
ADD_OBJECT(map[3],Item::leggings_gold);
|
||||
|
||||
ADD_OBJECT(map[4],Item::boots_cloth);
|
||||
ADD_OBJECT(map[4],Item::boots_leather);
|
||||
// ADD_OBJECT(map[4],Item::boots_chain);
|
||||
ADD_OBJECT(map[4],Item::boots_iron);
|
||||
ADD_OBJECT(map[4],Item::boots_diamond);
|
||||
@@ -79,7 +79,7 @@ ArmorRecipes::_eArmorType ArmorRecipes::GetArmorType(int iId)
|
||||
{
|
||||
switch(iId)
|
||||
{
|
||||
case Item::helmet_cloth_Id:
|
||||
case Item::helmet_leather_Id:
|
||||
case Item::helmet_chain_Id:
|
||||
case Item::helmet_iron_Id:
|
||||
case Item::helmet_diamond_Id:
|
||||
@@ -87,7 +87,7 @@ ArmorRecipes::_eArmorType ArmorRecipes::GetArmorType(int iId)
|
||||
return eArmorType_Helmet;
|
||||
break;
|
||||
|
||||
case Item::chestplate_cloth_Id:
|
||||
case Item::chestplate_leather_Id:
|
||||
case Item::chestplate_chain_Id:
|
||||
case Item::chestplate_iron_Id:
|
||||
case Item::chestplate_diamond_Id:
|
||||
@@ -95,7 +95,7 @@ ArmorRecipes::_eArmorType ArmorRecipes::GetArmorType(int iId)
|
||||
return eArmorType_Chestplate;
|
||||
break;
|
||||
|
||||
case Item::leggings_cloth_Id:
|
||||
case Item::leggings_leather_Id:
|
||||
case Item::leggings_chain_Id:
|
||||
case Item::leggings_iron_Id:
|
||||
case Item::leggings_diamond_Id:
|
||||
@@ -103,7 +103,7 @@ ArmorRecipes::_eArmorType ArmorRecipes::GetArmorType(int iId)
|
||||
return eArmorType_Leggings;
|
||||
break;
|
||||
|
||||
case Item::boots_cloth_Id:
|
||||
case Item::boots_leather_Id:
|
||||
case Item::boots_chain_Id:
|
||||
case Item::boots_iron_Id:
|
||||
case Item::boots_diamond_Id:
|
||||
|
||||
@@ -12,13 +12,17 @@ ArmorSlot::ArmorSlot(int slotNum, shared_ptr<Container> container, int id, int x
|
||||
{
|
||||
}
|
||||
|
||||
int ArmorSlot::getMaxStackSize()
|
||||
int ArmorSlot::getMaxStackSize() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool ArmorSlot::mayPlace(shared_ptr<ItemInstance> item)
|
||||
{
|
||||
if (item == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ( dynamic_cast<ArmorItem *>( item->getItem() ) != NULL)
|
||||
{
|
||||
return dynamic_cast<ArmorItem *>( item->getItem() )->slot == slotNum;
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
ArmorSlot(int slotNum, shared_ptr<Container> container, int id, int x, int y);
|
||||
virtual ~ArmorSlot() {}
|
||||
|
||||
virtual int getMaxStackSize();
|
||||
virtual int getMaxStackSize() const;
|
||||
virtual bool mayPlace(shared_ptr<ItemInstance> item);
|
||||
Icon *getNoItemIcon();
|
||||
//virtual bool mayCombine(shared_ptr<ItemInstance> item); // 4J Added
|
||||
|
||||
@@ -83,6 +83,7 @@ class Enchantment;
|
||||
class ClipChunk;
|
||||
|
||||
typedef arrayWithLength<double> doubleArray;
|
||||
typedef array2DWithLength<double> coords2DArray;
|
||||
typedef arrayWithLength<byte> byteArray;
|
||||
typedef arrayWithLength<char> charArray;
|
||||
typedef arrayWithLength<short> shortArray;
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include "net.minecraft.world.item.h"
|
||||
#include "net.minecraft.world.damagesource.h"
|
||||
#include "net.minecraft.world.item.enchantment.h"
|
||||
#include "net.minecraft.network.packet.h"
|
||||
#include "..\Minecraft.Client\ServerPlayer.h"
|
||||
#include "..\Minecraft.Client\PlayerConnection.h"
|
||||
#include "com.mojang.nbt.h"
|
||||
#include "Arrow.h"
|
||||
|
||||
@@ -48,16 +51,18 @@ void Arrow::_init()
|
||||
Arrow::Arrow(Level *level) : Entity( level )
|
||||
{
|
||||
_init();
|
||||
|
||||
this->setSize(0.5f, 0.5f);
|
||||
|
||||
viewScale = 10;
|
||||
setSize(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
Arrow::Arrow(Level *level, shared_ptr<Mob> mob, shared_ptr<Mob> target, float power, float uncertainty) : Entity( level )
|
||||
Arrow::Arrow(Level *level, shared_ptr<LivingEntity> mob, shared_ptr<LivingEntity> target, float power, float uncertainty) : Entity( level )
|
||||
{
|
||||
_init();
|
||||
|
||||
this->owner = mob;
|
||||
if ( dynamic_pointer_cast<Player>( mob ) != NULL) pickup = PICKUP_ALLOWED;
|
||||
|
||||
viewScale = 10;
|
||||
owner = mob;
|
||||
if ( mob->instanceof(eTYPE_PLAYER) ) pickup = PICKUP_ALLOWED;
|
||||
|
||||
y = mob->y + mob->getHeadHeight() - 0.1f;
|
||||
|
||||
@@ -82,29 +87,31 @@ Arrow::Arrow(Level *level, shared_ptr<Mob> mob, shared_ptr<Mob> target, float po
|
||||
Arrow::Arrow(Level *level, double x, double y, double z) : Entity( level )
|
||||
{
|
||||
_init();
|
||||
|
||||
viewScale = 10;
|
||||
setSize(0.5f, 0.5f);
|
||||
|
||||
this->setSize(0.5f, 0.5f);
|
||||
|
||||
this->setPos(x, y, z);
|
||||
this->heightOffset = 0;
|
||||
setPos(x, y, z);
|
||||
heightOffset = 0;
|
||||
}
|
||||
|
||||
Arrow::Arrow(Level *level, shared_ptr<Mob> mob, float power) : Entity( level )
|
||||
Arrow::Arrow(Level *level, shared_ptr<LivingEntity> mob, float power) : Entity( level )
|
||||
{
|
||||
_init();
|
||||
|
||||
this->owner = mob;
|
||||
if ( dynamic_pointer_cast<Player>( mob ) != NULL) pickup = PICKUP_ALLOWED;
|
||||
viewScale = 10;
|
||||
owner = mob;
|
||||
if ( mob->instanceof(eTYPE_PLAYER) ) pickup = PICKUP_ALLOWED;
|
||||
|
||||
setSize(0.5f, 0.5f);
|
||||
|
||||
this->moveTo(mob->x, mob->y + mob->getHeadHeight(), mob->z, mob->yRot, mob->xRot);
|
||||
moveTo(mob->x, mob->y + mob->getHeadHeight(), mob->z, mob->yRot, mob->xRot);
|
||||
|
||||
x -= Mth::cos(yRot / 180 * PI) * 0.16f;
|
||||
y -= 0.1f;
|
||||
z -= Mth::sin(yRot / 180 * PI) * 0.16f;
|
||||
this->setPos(x, y, z);
|
||||
this->heightOffset = 0;
|
||||
setPos(x, y, z);
|
||||
heightOffset = 0;
|
||||
|
||||
xd = -Mth::sin(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI);
|
||||
zd = Mth::cos(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI);
|
||||
@@ -128,9 +135,9 @@ void Arrow::shoot(double xd, double yd, double zd, float pow, float uncertainty)
|
||||
yd /= dist;
|
||||
zd /= dist;
|
||||
|
||||
xd += (random->nextGaussian()) * 0.0075f * uncertainty;
|
||||
yd += (random->nextGaussian()) * 0.0075f * uncertainty;
|
||||
zd += (random->nextGaussian()) * 0.0075f * uncertainty;
|
||||
xd += (random->nextGaussian() * (random->nextBoolean() ? -1 : 1)) * 0.0075f * uncertainty;
|
||||
yd += (random->nextGaussian() * (random->nextBoolean() ? -1 : 1)) * 0.0075f * uncertainty;
|
||||
zd += (random->nextGaussian() * (random->nextBoolean() ? -1 : 1)) * 0.0075f * uncertainty;
|
||||
|
||||
xd *= pow;
|
||||
yd *= pow;
|
||||
@@ -142,8 +149,8 @@ void Arrow::shoot(double xd, double yd, double zd, float pow, float uncertainty)
|
||||
|
||||
double sd = sqrt(xd * xd + zd * zd);
|
||||
|
||||
yRotO = this->yRot = (float) (atan2(xd, zd) * 180 / PI);
|
||||
xRotO = this->xRot = (float) (atan2(yd, sd) * 180 / PI);
|
||||
yRotO = yRot = (float) (atan2(xd, zd) * 180 / PI);
|
||||
xRotO = xRot = (float) (atan2(yd, sd) * 180 / PI);
|
||||
life = 0;
|
||||
}
|
||||
|
||||
@@ -161,8 +168,8 @@ void Arrow::lerpMotion(double xd, double yd, double zd)
|
||||
if (xRotO == 0 && yRotO == 0)
|
||||
{
|
||||
double sd = sqrt(xd * xd + zd * zd);
|
||||
yRotO = this->yRot = (float) (atan2( xd, zd) * 180 / PI);
|
||||
xRotO = this->xRot = (float) (atan2( yd, sd) * 180 / PI);
|
||||
yRotO = yRot = (float) (atan2( xd, zd) * 180 / PI);
|
||||
xRotO = xRot = (float) (atan2( yd, sd) * 180 / PI);
|
||||
xRotO = xRot;
|
||||
yRotO = yRot;
|
||||
app.DebugPrintf("%f %f : 0x%x\n",xRot,yRot,&yRot);
|
||||
@@ -179,8 +186,8 @@ void Arrow::tick()
|
||||
if (xRotO == 0 && yRotO == 0)
|
||||
{
|
||||
double sd = sqrt(xd * xd + zd * zd);
|
||||
yRotO = this->yRot = (float) (atan2(xd, zd) * 180 / PI);
|
||||
xRotO = this->xRot = (float) (atan2(yd, sd) * 180 / PI);
|
||||
yRotO = yRot = (float) (atan2(xd, zd) * 180 / PI);
|
||||
xRotO = xRot = (float) (atan2(yd, sd) * 180 / PI);
|
||||
}
|
||||
|
||||
|
||||
@@ -269,6 +276,16 @@ void Arrow::tick()
|
||||
res = new HitResult(hitEntity);
|
||||
}
|
||||
|
||||
if ( (res != NULL) && (res->entity != NULL) && res->entity->instanceof(eTYPE_PLAYER))
|
||||
{
|
||||
shared_ptr<Player> player = dynamic_pointer_cast<Player>(res->entity);
|
||||
// 4J: Check for owner being null
|
||||
if ( player->abilities.invulnerable || ((owner != NULL) && (owner->instanceof(eTYPE_PLAYER) && !dynamic_pointer_cast<Player>(owner)->canHarmPlayer(player))))
|
||||
{
|
||||
res = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (res != NULL)
|
||||
{
|
||||
if (res->entity != NULL)
|
||||
@@ -294,15 +311,19 @@ void Arrow::tick()
|
||||
// 4J Stu - We should not set the entity on fire unless we can cause some damage (this doesn't necessarily mean that the arrow hit lowered their health)
|
||||
// set targets on fire first because we want cooked
|
||||
// pork/chicken/steak
|
||||
if (this->isOnFire())
|
||||
if (isOnFire() && res->entity->GetType() != eTYPE_ENDERMAN)
|
||||
{
|
||||
res->entity->setOnFire(5);
|
||||
}
|
||||
|
||||
shared_ptr<Mob> mob = dynamic_pointer_cast<Mob>(res->entity);
|
||||
if (mob != NULL)
|
||||
if (res->entity->instanceof(eTYPE_LIVINGENTITY))
|
||||
{
|
||||
mob->arrowCount++;
|
||||
shared_ptr<LivingEntity> mob = dynamic_pointer_cast<LivingEntity>(res->entity);
|
||||
|
||||
if (!level->isClientSide)
|
||||
{
|
||||
mob->setArrowCount(mob->getArrowCount() + 1);
|
||||
}
|
||||
if (knockback > 0)
|
||||
{
|
||||
float pushLen = sqrt(xd * xd + zd * zd);
|
||||
@@ -316,12 +337,17 @@ void Arrow::tick()
|
||||
{
|
||||
ThornsEnchantment::doThornsAfterAttack(owner, mob, random);
|
||||
}
|
||||
|
||||
if (owner != NULL && res->entity != owner && owner->GetType() == eTYPE_SERVERPLAYER)
|
||||
{
|
||||
dynamic_pointer_cast<ServerPlayer>(owner)->connection->send( shared_ptr<GameEventPacket>( new GameEventPacket(GameEventPacket::SUCCESSFUL_BOW_HIT, 0)) );
|
||||
}
|
||||
}
|
||||
|
||||
// 4J : WESTY : For award, need to track if creeper was killed by arrow from the player.
|
||||
if ( (dynamic_pointer_cast<Player>(owner) != NULL ) && // arrow owner is a player
|
||||
( res->entity->isAlive() == false ) && // target is now dead
|
||||
( dynamic_pointer_cast<Creeper>( res->entity ) != NULL ) ) // target is a creeper
|
||||
if (owner != NULL && owner->instanceof(eTYPE_PLAYER) // arrow owner is a player
|
||||
&& !res->entity->isAlive() // target is now dead
|
||||
&& (res->entity->GetType() == eTYPE_CREEPER)) // target is a creeper
|
||||
|
||||
{
|
||||
dynamic_pointer_cast<Player>(owner)->awardStat(
|
||||
@@ -330,9 +356,8 @@ void Arrow::tick()
|
||||
);
|
||||
}
|
||||
|
||||
// 4J - sound change brought forward from 1.2.3
|
||||
level->playSound(shared_from_this(), eSoundType_RANDOM_BOW_HIT, 1.0f, 1.2f / (random->nextFloat() * 0.2f + 0.9f));
|
||||
remove();
|
||||
playSound( eSoundType_RANDOM_BOW_HIT, 1.0f, 1.2f / (random->nextFloat() * 0.2f + 0.9f));
|
||||
if (res->entity->GetType() != eTYPE_ENDERDRAGON) remove();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -365,11 +390,15 @@ void Arrow::tick()
|
||||
z -= (zd / dd) * 0.05f;
|
||||
}
|
||||
|
||||
// 4J - sound change brought forward from 1.2.3
|
||||
level->playSound(shared_from_this(), eSoundType_RANDOM_BOW_HIT, 1.0f, 1.2f / (random->nextFloat() * 0.2f + 0.9f));
|
||||
playSound(eSoundType_RANDOM_BOW_HIT, 1.0f, 1.2f / (random->nextFloat() * 0.2f + 0.9f));
|
||||
inGround = true;
|
||||
shakeTime = 7;
|
||||
setCritArrow(false);
|
||||
|
||||
if (lastTile != 0)
|
||||
{
|
||||
Tile::tiles[lastTile]->entityInside(level, xTile, yTile, zTile, shared_from_this() );
|
||||
}
|
||||
}
|
||||
}
|
||||
delete res;
|
||||
@@ -480,12 +509,17 @@ void Arrow::playerTouch(shared_ptr<Player> player)
|
||||
|
||||
if (bRemove)
|
||||
{
|
||||
level->playSound(shared_from_this(), eSoundType_RANDOM_POP, 0.2f, ((random->nextFloat() - random->nextFloat()) * 0.7f + 1.0f) * 2.0f);
|
||||
playSound(eSoundType_RANDOM_POP, 0.2f, ((random->nextFloat() - random->nextFloat()) * 0.7f + 1.0f) * 2.0f);
|
||||
player->take(shared_from_this(), 1);
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
bool Arrow::makeStepSound()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float Arrow::getShadowHeightOffs()
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
using namespace std;
|
||||
|
||||
#include "Entity.h"
|
||||
#include "Projectile.h"
|
||||
|
||||
class Level;
|
||||
class CompoundTag;
|
||||
|
||||
class Arrow : public Entity
|
||||
class Arrow : public Entity, public Projectile
|
||||
{
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_ARROW; }
|
||||
@@ -26,35 +27,35 @@ private:
|
||||
static const int FLAG_CRIT = 1;
|
||||
|
||||
private:
|
||||
int xTile;
|
||||
int yTile;
|
||||
int zTile;
|
||||
int lastTile;
|
||||
int lastData;
|
||||
bool inGround;
|
||||
int xTile;
|
||||
int yTile;
|
||||
int zTile;
|
||||
int lastTile;
|
||||
int lastData;
|
||||
bool inGround;
|
||||
|
||||
public:
|
||||
int pickup;
|
||||
int shakeTime;
|
||||
shared_ptr<Entity> owner;
|
||||
int shakeTime;
|
||||
shared_ptr<Entity> owner;
|
||||
|
||||
private:
|
||||
double baseDamage;
|
||||
|
||||
int knockback;
|
||||
int knockback;
|
||||
|
||||
private:
|
||||
int life;
|
||||
int flightTime;
|
||||
int flightTime;
|
||||
|
||||
// 4J - added common ctor code.
|
||||
void _init();
|
||||
|
||||
public:
|
||||
Arrow(Level *level);
|
||||
Arrow(Level *level, shared_ptr<Mob> mob, shared_ptr<Mob> target, float power, float uncertainty);
|
||||
Arrow(Level *level, double x, double y, double z);
|
||||
Arrow(Level *level, shared_ptr<Mob> mob, float power);
|
||||
Arrow(Level *level, shared_ptr<LivingEntity> mob, shared_ptr<LivingEntity> target, float power, float uncertainty);
|
||||
Arrow(Level *level, double x, double y, double z);
|
||||
Arrow(Level *level, shared_ptr<LivingEntity> mob, float power);
|
||||
|
||||
protected:
|
||||
virtual void defineSynchedData();
|
||||
@@ -63,11 +64,16 @@ public:
|
||||
void shoot(double xd, double yd, double zd, float pow, float uncertainty);
|
||||
virtual void lerpTo(double x, double y, double z, float yRot, float xRot, int steps);
|
||||
virtual void lerpMotion(double xd, double yd, double zd);
|
||||
virtual void tick();
|
||||
virtual void addAdditonalSaveData(CompoundTag *tag);
|
||||
virtual void readAdditionalSaveData(CompoundTag *tag);
|
||||
virtual void playerTouch(shared_ptr<Player> player);
|
||||
virtual float getShadowHeightOffs();
|
||||
virtual void tick();
|
||||
virtual void addAdditonalSaveData(CompoundTag *tag);
|
||||
virtual void readAdditionalSaveData(CompoundTag *tag);
|
||||
virtual void playerTouch(shared_ptr<Player> player);
|
||||
|
||||
protected:
|
||||
virtual bool makeStepSound();
|
||||
|
||||
public:
|
||||
virtual float getShadowHeightOffs();
|
||||
|
||||
void setBaseDamage(double baseDamage);
|
||||
double getBaseDamage();
|
||||
|
||||
19
Minecraft.World/AttackDamageMobEffect.cpp
Normal file
19
Minecraft.World/AttackDamageMobEffect.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "AttackDamageMobEffect.h"
|
||||
|
||||
AttackDamageMobEffect::AttackDamageMobEffect(int id, bool isHarmful, eMinecraftColour color) : MobEffect(id, isHarmful, color)
|
||||
{
|
||||
}
|
||||
|
||||
double AttackDamageMobEffect::getAttributeModifierValue(int amplifier, AttributeModifier *original)
|
||||
{
|
||||
if (id == MobEffect::weakness->id)
|
||||
{
|
||||
return -0.5f * (amplifier + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1.3 * (amplifier + 1);
|
||||
}
|
||||
}
|
||||
13
Minecraft.World/AttackDamageMobEffect.h
Normal file
13
Minecraft.World/AttackDamageMobEffect.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "MobEffect.h"
|
||||
|
||||
class AttributeModifier;
|
||||
|
||||
class AttackDamageMobEffect : public MobEffect
|
||||
{
|
||||
public:
|
||||
AttackDamageMobEffect(int id, bool isHarmful, eMinecraftColour color);
|
||||
|
||||
double getAttributeModifierValue(int amplifier, AttributeModifier *original);
|
||||
};
|
||||
18
Minecraft.World/Attribute.cpp
Normal file
18
Minecraft.World/Attribute.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "stdafx.h"
|
||||
#include "Attribute.h"
|
||||
|
||||
const int Attribute::AttributeNames [] =
|
||||
{
|
||||
IDS_ATTRIBUTE_NAME_GENERIC_MAXHEALTH,
|
||||
IDS_ATTRIBUTE_NAME_GENERIC_FOLLOWRANGE,
|
||||
IDS_ATTRIBUTE_NAME_GENERIC_KNOCKBACKRESISTANCE,
|
||||
IDS_ATTRIBUTE_NAME_GENERIC_MOVEMENTSPEED,
|
||||
IDS_ATTRIBUTE_NAME_GENERIC_ATTACKDAMAGE,
|
||||
IDS_ATTRIBUTE_NAME_HORSE_JUMPSTRENGTH,
|
||||
IDS_ATTRIBUTE_NAME_ZOMBIE_SPAWNREINFORCEMENTS,
|
||||
};
|
||||
|
||||
int Attribute::getName(eATTRIBUTE_ID id)
|
||||
{
|
||||
return AttributeNames[id];
|
||||
}
|
||||
71
Minecraft.World/Attribute.h
Normal file
71
Minecraft.World/Attribute.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
class AttributeModifier;
|
||||
|
||||
// 4J: This ID is serialised into save data so new attributes must always be added after existing ones
|
||||
enum eATTRIBUTE_ID
|
||||
{
|
||||
// 1.6.4
|
||||
eAttributeId_GENERIC_MAXHEALTH,
|
||||
eAttributeId_GENERIC_FOLLOWRANGE,
|
||||
eAttributeId_GENERIC_KNOCKBACKRESISTANCE,
|
||||
eAttributeId_GENERIC_MOVEMENTSPEED,
|
||||
eAttributeId_GENERIC_ATTACKDAMAGE,
|
||||
eAttributeId_HORSE_JUMPSTRENGTH,
|
||||
eAttributeId_ZOMBIE_SPAWNREINFORCEMENTS,
|
||||
|
||||
// 1.8+
|
||||
// New attributes go here
|
||||
|
||||
eAttributeId_COUNT
|
||||
};
|
||||
|
||||
class Attribute
|
||||
{
|
||||
public:
|
||||
static const int MAX_NAME_LENGTH = 64;
|
||||
|
||||
/**
|
||||
* 4J: Changed this from a string name to an ID
|
||||
* Gets the ID of this attribute, for serialization.
|
||||
*
|
||||
* @return Name of this attribute.
|
||||
*/
|
||||
virtual eATTRIBUTE_ID getId() = 0;
|
||||
|
||||
/**
|
||||
* Sanitizes an attribute value, making sure it's not out of range and is an acceptable amount.
|
||||
*
|
||||
*
|
||||
* @param value Value to sanitize.
|
||||
* @return Sanitized value, safe for use.
|
||||
*/
|
||||
virtual double sanitizeValue(double value) = 0;
|
||||
|
||||
/**
|
||||
* Get the default value of this attribute, to be used upon creation.
|
||||
*
|
||||
* @return Default value.
|
||||
*/
|
||||
virtual double getDefaultValue() = 0;
|
||||
|
||||
/**
|
||||
* Checks if this attribute should be synced to the client.
|
||||
*
|
||||
* Attributes should be serverside only unless the client needs to know about it.
|
||||
*
|
||||
* @return True if the client should know about this attribute.
|
||||
*/
|
||||
virtual bool isClientSyncable() = 0;
|
||||
|
||||
// 4J: Added to retrieve string ID for attribute
|
||||
static int getName(eATTRIBUTE_ID id);
|
||||
|
||||
protected:
|
||||
static const int AttributeNames [];
|
||||
};
|
||||
|
||||
#ifdef __ORBIS__
|
||||
typedef unordered_map<eATTRIBUTE_ID, AttributeModifier *, std::hash<int>> attrAttrModMap;
|
||||
#else
|
||||
typedef unordered_map<eATTRIBUTE_ID, AttributeModifier *> attrAttrModMap;
|
||||
#endif
|
||||
22
Minecraft.World/AttributeInstance.h
Normal file
22
Minecraft.World/AttributeInstance.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "AttributeModifier.h"
|
||||
|
||||
class AttributeInstance
|
||||
{
|
||||
public:
|
||||
virtual ~AttributeInstance() {}
|
||||
|
||||
virtual Attribute *getAttribute() = 0;
|
||||
virtual double getBaseValue() = 0;
|
||||
virtual void setBaseValue(double baseValue) = 0;
|
||||
virtual double getValue() = 0;
|
||||
|
||||
virtual unordered_set<AttributeModifier *> *getModifiers(int operation) = 0;
|
||||
virtual void getModifiers(unordered_set<AttributeModifier *>& result) = 0;
|
||||
virtual AttributeModifier *getModifier(eMODIFIER_ID id) = 0;
|
||||
virtual void addModifiers(unordered_set<AttributeModifier *> *modifiers) = 0;
|
||||
virtual void addModifier(AttributeModifier *modifier) = 0;
|
||||
virtual void removeModifier(AttributeModifier *modifier) = 0;
|
||||
virtual void removeModifier(eMODIFIER_ID id) = 0;
|
||||
virtual void removeModifiers() = 0;
|
||||
};
|
||||
129
Minecraft.World/AttributeModifier.cpp
Normal file
129
Minecraft.World/AttributeModifier.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "AttributeModifier.h"
|
||||
#include "HtmlString.h"
|
||||
|
||||
void AttributeModifier::_init(eMODIFIER_ID id, const wstring name, double amount, int operation)
|
||||
{
|
||||
assert(operation < TOTAL_OPERATIONS);
|
||||
this->amount = amount;
|
||||
this->operation = operation;
|
||||
this->name = name;
|
||||
this->id = id;
|
||||
this->serialize = true;
|
||||
}
|
||||
|
||||
AttributeModifier::AttributeModifier(double amount, int operation)
|
||||
{
|
||||
// Create an anonymous attribute
|
||||
_init(eModifierId_ANONYMOUS, name, amount, operation);
|
||||
}
|
||||
|
||||
AttributeModifier::AttributeModifier(eMODIFIER_ID id, double amount, int operation)
|
||||
{
|
||||
_init(id, name, amount, operation);
|
||||
|
||||
//Validate.notEmpty(name, "Modifier name cannot be empty");
|
||||
//Validate.inclusiveBetween(0, TOTAL_OPERATIONS - 1, operation, "Invalid operation");
|
||||
}
|
||||
|
||||
eMODIFIER_ID AttributeModifier::getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
wstring AttributeModifier::getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
int AttributeModifier::getOperation()
|
||||
{
|
||||
return operation;
|
||||
}
|
||||
|
||||
double AttributeModifier::getAmount()
|
||||
{
|
||||
return amount;
|
||||
}
|
||||
|
||||
bool AttributeModifier::isSerializable()
|
||||
{
|
||||
return serialize;
|
||||
}
|
||||
|
||||
AttributeModifier *AttributeModifier::setSerialize(bool serialize)
|
||||
{
|
||||
this->serialize = serialize;
|
||||
return this;
|
||||
}
|
||||
|
||||
bool AttributeModifier::equals(AttributeModifier *modifier)
|
||||
{
|
||||
if (this == modifier) return true;
|
||||
if (modifier == NULL) return false; //|| getClass() != o.getClass()) return false;
|
||||
|
||||
if (id != modifier->id) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
wstring AttributeModifier::toString()
|
||||
{
|
||||
return L"";
|
||||
|
||||
/*return L"AttributeModifier{" +
|
||||
L"amount=" + amount +
|
||||
L", operation=" + operation +
|
||||
L", name='" + name + '\'' +
|
||||
L", id=" + id +
|
||||
L", serialize=" + serialize +
|
||||
L'}';*/
|
||||
}
|
||||
|
||||
HtmlString AttributeModifier::getHoverText(eATTRIBUTE_ID attribute)
|
||||
{
|
||||
double amount = getAmount();
|
||||
double displayAmount;
|
||||
|
||||
if (getOperation() == AttributeModifier::OPERATION_MULTIPLY_BASE || getOperation() == AttributeModifier::OPERATION_MULTIPLY_TOTAL)
|
||||
{
|
||||
displayAmount = getAmount() * 100.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
displayAmount = getAmount();
|
||||
}
|
||||
|
||||
eMinecraftColour color;
|
||||
|
||||
if (amount > 0)
|
||||
{
|
||||
color = eHTMLColor_9;
|
||||
}
|
||||
else if (amount < 0)
|
||||
{
|
||||
displayAmount *= -1;
|
||||
color = eHTMLColor_c;
|
||||
}
|
||||
|
||||
bool percentage = false;
|
||||
switch(getOperation())
|
||||
{
|
||||
case AttributeModifier::OPERATION_ADDITION:
|
||||
percentage = false;
|
||||
break;
|
||||
case AttributeModifier::OPERATION_MULTIPLY_BASE:
|
||||
case AttributeModifier::OPERATION_MULTIPLY_TOTAL:
|
||||
percentage = true;
|
||||
break;
|
||||
default:
|
||||
// No other operations
|
||||
assert(0);
|
||||
}
|
||||
|
||||
wchar_t formatted[256];
|
||||
swprintf(formatted, 256, L"%ls%d%ls %ls", (amount > 0 ? L"+" : L"-"), (int) displayAmount, (percentage ? L"%" : L""), app.GetString(Attribute::getName(attribute)));
|
||||
|
||||
return HtmlString(formatted, color);
|
||||
}
|
||||
69
Minecraft.World/AttributeModifier.h
Normal file
69
Minecraft.World/AttributeModifier.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
4J - Both modifier uuid and name have been replaced by an id enum. Note that we have special value
|
||||
"eModifierId_ANONYMOUS" for attribute modifiers that previously didn't have a fixed UUID and are never removed.
|
||||
|
||||
To all intents and purposes anonymous modifiers don't have an ID and so are handled differently in some cases, for instance:
|
||||
1. You can have multiple modifiers with the anonymous ID on a single attribute instance
|
||||
2. Anonymous modifiers can't be removed from attribute instance by ID
|
||||
|
||||
IMPORTANT: Saved out to file so don't change order. All new values should be added at the end.
|
||||
*/
|
||||
|
||||
class HtmlString;
|
||||
|
||||
enum eMODIFIER_ID
|
||||
{
|
||||
eModifierId_ANONYMOUS = 0,
|
||||
|
||||
eModifierId_ITEM_BASEDAMAGE,
|
||||
|
||||
eModifierId_MOB_FLEEING,
|
||||
eModifierId_MOB_SPRINTING,
|
||||
|
||||
eModifierId_MOB_ENDERMAN_ATTACKSPEED,
|
||||
eModifierId_MOB_PIG_ATTACKSPEED,
|
||||
eModifierId_MOB_WITCH_DRINKSPEED,
|
||||
eModifierId_MOB_ZOMBIE_BABYSPEED,
|
||||
|
||||
eModifierId_POTION_DAMAGEBOOST,
|
||||
eModifierId_POTION_HEALTHBOOST,
|
||||
eModifierId_POTION_MOVESPEED,
|
||||
eModifierId_POTION_MOVESLOWDOWN,
|
||||
eModifierId_POTION_WEAKNESS,
|
||||
|
||||
eModifierId_COUNT,
|
||||
};
|
||||
|
||||
class AttributeModifier
|
||||
{
|
||||
public:
|
||||
static const int OPERATION_ADDITION = 0;
|
||||
static const int OPERATION_MULTIPLY_BASE = 1;
|
||||
static const int OPERATION_MULTIPLY_TOTAL = 2;
|
||||
static const int TOTAL_OPERATIONS = 3;
|
||||
|
||||
private:
|
||||
double amount;
|
||||
int operation;
|
||||
wstring name;
|
||||
eMODIFIER_ID id;
|
||||
bool serialize;
|
||||
|
||||
void _init(eMODIFIER_ID id, const wstring name, double amount, int operation);
|
||||
|
||||
public:
|
||||
AttributeModifier(double amount, int operation);
|
||||
AttributeModifier(eMODIFIER_ID id, double amount, int operation);
|
||||
|
||||
eMODIFIER_ID getId();
|
||||
wstring getName();
|
||||
int getOperation();
|
||||
double getAmount();
|
||||
bool isSerializable();
|
||||
AttributeModifier *setSerialize(bool serialize);
|
||||
bool equals(AttributeModifier *modifier);
|
||||
wstring toString();
|
||||
HtmlString getHoverText(eATTRIBUTE_ID attribute); // 4J: Added to keep modifier readable string creation in one place
|
||||
};
|
||||
@@ -10,16 +10,28 @@
|
||||
#include "net.minecraft.world.phys.h"
|
||||
#include "AvoidPlayerGoal.h"
|
||||
|
||||
AvoidPlayerGoal::AvoidPlayerGoal(PathfinderMob *mob, const type_info& avoidType, float maxDist, float walkSpeed, float sprintSpeed) : avoidType(avoidType)
|
||||
AvoidPlayerGoalEntitySelector::AvoidPlayerGoalEntitySelector(AvoidPlayerGoal *parent)
|
||||
{
|
||||
m_parent = parent;
|
||||
}
|
||||
|
||||
bool AvoidPlayerGoalEntitySelector::matches(shared_ptr<Entity> entity) const
|
||||
{
|
||||
return entity->isAlive() && m_parent->mob->getSensing()->canSee(entity);
|
||||
}
|
||||
|
||||
AvoidPlayerGoal::AvoidPlayerGoal(PathfinderMob *mob, const type_info& avoidType, float maxDist, double walkSpeedModifier, double sprintSpeedModifier) : avoidType(avoidType)
|
||||
{
|
||||
this->mob = mob;
|
||||
//this->avoidType = avoidType;
|
||||
this->maxDist = maxDist;
|
||||
this->walkSpeed = walkSpeed;
|
||||
this->sprintSpeed = sprintSpeed;
|
||||
this->walkSpeedModifier = walkSpeedModifier;
|
||||
this->sprintSpeedModifier = sprintSpeedModifier;
|
||||
this->pathNav = mob->getNavigation();
|
||||
setRequiredControlFlags(Control::MoveControlFlag);
|
||||
|
||||
entitySelector = new AvoidPlayerGoalEntitySelector(this);
|
||||
|
||||
toAvoid = weak_ptr<Entity>();
|
||||
path = NULL;
|
||||
}
|
||||
@@ -27,6 +39,7 @@ AvoidPlayerGoal::AvoidPlayerGoal(PathfinderMob *mob, const type_info& avoidType,
|
||||
AvoidPlayerGoal::~AvoidPlayerGoal()
|
||||
{
|
||||
if(path != NULL) delete path;
|
||||
delete entitySelector;
|
||||
}
|
||||
|
||||
bool AvoidPlayerGoal::canUse()
|
||||
@@ -40,7 +53,7 @@ bool AvoidPlayerGoal::canUse()
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<shared_ptr<Entity> > *entities = mob->level->getEntitiesOfClass(avoidType, mob->bb->grow(maxDist, 3, maxDist));
|
||||
vector<shared_ptr<Entity> > *entities = mob->level->getEntitiesOfClass(avoidType, mob->bb->grow(maxDist, 3, maxDist), entitySelector);
|
||||
if (entities->empty())
|
||||
{
|
||||
delete entities;
|
||||
@@ -50,8 +63,6 @@ bool AvoidPlayerGoal::canUse()
|
||||
delete entities;
|
||||
}
|
||||
|
||||
if (!mob->getSensing()->canSee(toAvoid.lock())) return false;
|
||||
|
||||
Vec3 *pos = RandomPos::getPosAvoid(dynamic_pointer_cast<PathfinderMob>(mob->shared_from_this()), 16, 7, Vec3::newTemp(toAvoid.lock()->x, toAvoid.lock()->y, toAvoid.lock()->z));
|
||||
if (pos == NULL) return false;
|
||||
if (toAvoid.lock()->distanceToSqr(pos->x, pos->y, pos->z) < toAvoid.lock()->distanceToSqr(mob->shared_from_this())) return false;
|
||||
@@ -69,7 +80,7 @@ bool AvoidPlayerGoal::canContinueToUse()
|
||||
|
||||
void AvoidPlayerGoal::start()
|
||||
{
|
||||
pathNav->moveTo(path, walkSpeed);
|
||||
pathNav->moveTo(path, walkSpeedModifier);
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
@@ -80,6 +91,6 @@ void AvoidPlayerGoal::stop()
|
||||
|
||||
void AvoidPlayerGoal::tick()
|
||||
{
|
||||
if (mob->distanceToSqr(toAvoid.lock()) < 7 * 7) mob->getNavigation()->setSpeed(sprintSpeed);
|
||||
else mob->getNavigation()->setSpeed(walkSpeed);
|
||||
if (mob->distanceToSqr(toAvoid.lock()) < 7 * 7) mob->getNavigation()->setSpeedModifier(sprintSpeedModifier);
|
||||
else mob->getNavigation()->setSpeedModifier(walkSpeedModifier);
|
||||
}
|
||||
@@ -1,24 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "Goal.h"
|
||||
#include "EntitySelector.h"
|
||||
|
||||
class PathNavigation;
|
||||
class PathfinderMob;
|
||||
class Path;
|
||||
class AvoidPlayerGoal;
|
||||
|
||||
class AvoidPlayerGoalEntitySelector : public EntitySelector
|
||||
{
|
||||
private:
|
||||
AvoidPlayerGoal *m_parent;
|
||||
|
||||
public:
|
||||
AvoidPlayerGoalEntitySelector(AvoidPlayerGoal *parent);
|
||||
bool matches(shared_ptr<Entity> entity) const;
|
||||
};
|
||||
|
||||
class AvoidPlayerGoal : public Goal
|
||||
{
|
||||
friend class AvoidPlayerGoalEntitySelector;
|
||||
private:
|
||||
PathfinderMob *mob; // Owner of this goal
|
||||
float walkSpeed, sprintSpeed;
|
||||
double walkSpeedModifier, sprintSpeedModifier;
|
||||
weak_ptr<Entity> toAvoid;
|
||||
float maxDist;
|
||||
Path *path;
|
||||
PathNavigation *pathNav;
|
||||
const type_info& avoidType;
|
||||
EntitySelector *entitySelector;
|
||||
|
||||
public:
|
||||
AvoidPlayerGoal(PathfinderMob *mob, const type_info& avoidType, float maxDist, float walkSpeed, float sprintSpeed);
|
||||
AvoidPlayerGoal(PathfinderMob *mob, const type_info& avoidType, float maxDist, double walkSpeedModifier, double sprintSpeedModifier);
|
||||
~AvoidPlayerGoal();
|
||||
|
||||
virtual bool canUse();
|
||||
|
||||
31
Minecraft.World/BaseAttribute.cpp
Normal file
31
Minecraft.World/BaseAttribute.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "BaseAttribute.h"
|
||||
|
||||
BaseAttribute::BaseAttribute(eATTRIBUTE_ID id, double defaultValue)
|
||||
{
|
||||
this->id = id;
|
||||
this->defaultValue = defaultValue;
|
||||
syncable = false;
|
||||
}
|
||||
|
||||
eATTRIBUTE_ID BaseAttribute::getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
double BaseAttribute::getDefaultValue()
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
bool BaseAttribute::isClientSyncable()
|
||||
{
|
||||
return syncable;
|
||||
}
|
||||
|
||||
BaseAttribute *BaseAttribute::setSyncable(bool syncable)
|
||||
{
|
||||
this->syncable = syncable;
|
||||
return this;
|
||||
}
|
||||
20
Minecraft.World/BaseAttribute.h
Normal file
20
Minecraft.World/BaseAttribute.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "Attribute.h"
|
||||
|
||||
class BaseAttribute : public Attribute
|
||||
{
|
||||
private:
|
||||
eATTRIBUTE_ID id;
|
||||
double defaultValue;
|
||||
bool syncable;
|
||||
|
||||
protected:
|
||||
BaseAttribute(eATTRIBUTE_ID id, double defaultValue);
|
||||
|
||||
public:
|
||||
virtual eATTRIBUTE_ID getId();
|
||||
virtual double getDefaultValue();
|
||||
virtual bool isClientSyncable();
|
||||
virtual BaseAttribute *setSyncable(bool syncable);
|
||||
};
|
||||
82
Minecraft.World/BaseAttributeMap.cpp
Normal file
82
Minecraft.World/BaseAttributeMap.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include "stdafx.h"
|
||||
#include "net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "BaseAttributeMap.h"
|
||||
|
||||
BaseAttributeMap::~BaseAttributeMap()
|
||||
{
|
||||
for(AUTO_VAR(it,attributesById.begin()); it != attributesById.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
AttributeInstance *BaseAttributeMap::getInstance(Attribute *attribute)
|
||||
{
|
||||
return getInstance(attribute->getId());
|
||||
}
|
||||
|
||||
AttributeInstance *BaseAttributeMap::getInstance(eATTRIBUTE_ID id)
|
||||
{
|
||||
AUTO_VAR(it,attributesById.find(id));
|
||||
if(it != attributesById.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseAttributeMap::getAttributes(vector<AttributeInstance *>& atts)
|
||||
{
|
||||
for(AUTO_VAR(it,attributesById.begin()); it != attributesById.end(); ++it)
|
||||
{
|
||||
atts.push_back(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseAttributeMap::onAttributeModified(ModifiableAttributeInstance *attributeInstance)
|
||||
{
|
||||
}
|
||||
|
||||
void BaseAttributeMap::removeItemModifiers(shared_ptr<ItemInstance> item)
|
||||
{
|
||||
attrAttrModMap *modifiers = item->getAttributeModifiers();
|
||||
|
||||
for(AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it)
|
||||
{
|
||||
AttributeInstance *attribute = getInstance(it->first);
|
||||
AttributeModifier *modifier = it->second;
|
||||
|
||||
if (attribute != NULL)
|
||||
{
|
||||
attribute->removeModifier(modifier);
|
||||
}
|
||||
|
||||
delete modifier;
|
||||
}
|
||||
|
||||
delete modifiers;
|
||||
}
|
||||
|
||||
void BaseAttributeMap::addItemModifiers(shared_ptr<ItemInstance> item)
|
||||
{
|
||||
attrAttrModMap *modifiers = item->getAttributeModifiers();
|
||||
|
||||
for(AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it)
|
||||
{
|
||||
AttributeInstance *attribute = getInstance(it->first);
|
||||
AttributeModifier *modifier = it->second;
|
||||
|
||||
if (attribute != NULL)
|
||||
{
|
||||
attribute->removeModifier(modifier);
|
||||
attribute->addModifier(new AttributeModifier(*modifier));
|
||||
}
|
||||
|
||||
delete modifier;
|
||||
}
|
||||
|
||||
delete modifiers;
|
||||
}
|
||||
29
Minecraft.World/BaseAttributeMap.h
Normal file
29
Minecraft.World/BaseAttributeMap.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
class ModifiableAttributeInstance;
|
||||
|
||||
class BaseAttributeMap
|
||||
{
|
||||
protected:
|
||||
//unordered_map<Attribute *, AttributeInstance *> attributesByObject;
|
||||
#ifdef __ORBIS__
|
||||
unordered_map<eATTRIBUTE_ID, AttributeInstance *, std::hash<int> > attributesById;
|
||||
#else
|
||||
unordered_map<eATTRIBUTE_ID, AttributeInstance *> attributesById;
|
||||
#endif
|
||||
|
||||
public :
|
||||
virtual ~BaseAttributeMap();
|
||||
|
||||
virtual AttributeInstance *getInstance(Attribute *attribute);
|
||||
virtual AttributeInstance *getInstance(eATTRIBUTE_ID name);
|
||||
|
||||
virtual AttributeInstance *registerAttribute(Attribute *attribute) = 0;
|
||||
|
||||
virtual void getAttributes(vector<AttributeInstance *>& atts);
|
||||
virtual void onAttributeModified(ModifiableAttributeInstance *attributeInstance);
|
||||
|
||||
// 4J: Changed these into specialised functions for adding/removing the modifiers of an item (it's cleaner)
|
||||
virtual void removeItemModifiers(shared_ptr<ItemInstance> item);
|
||||
virtual void addItemModifiers(shared_ptr<ItemInstance> item);
|
||||
};
|
||||
33
Minecraft.World/BaseEntityTile.cpp
Normal file
33
Minecraft.World/BaseEntityTile.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "stdafx.h"
|
||||
#include "net.minecraft.world.level.h"
|
||||
#include "net.minecraft.world.entity.h"
|
||||
#include "TileEntity.h"
|
||||
#include "BaseEntityTile.h"
|
||||
|
||||
BaseEntityTile::BaseEntityTile(int id, Material *material, bool isSolidRender /*= true*/) : Tile(id, material, isSolidRender)
|
||||
{
|
||||
_isEntityTile = true;
|
||||
}
|
||||
|
||||
void BaseEntityTile::onPlace(Level *level, int x, int y, int z)
|
||||
{
|
||||
Tile::onPlace(level, x, y, z);
|
||||
//level->setTileEntity(x, y, z, newTileEntity(level));
|
||||
}
|
||||
|
||||
void BaseEntityTile::onRemove(Level *level, int x, int y, int z, int id, int data)
|
||||
{
|
||||
Tile::onRemove(level, x, y, z, id, data);
|
||||
level->removeTileEntity(x, y, z);
|
||||
}
|
||||
|
||||
bool BaseEntityTile::triggerEvent(Level *level, int x, int y, int z, int b0, int b1)
|
||||
{
|
||||
Tile::triggerEvent(level, x, y, z, b0, b1);
|
||||
shared_ptr<TileEntity> te = level->getTileEntity(x, y, z);
|
||||
if (te != NULL)
|
||||
{
|
||||
return te->triggerEvent(b0, b1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
15
Minecraft.World/BaseEntityTile.h
Normal file
15
Minecraft.World/BaseEntityTile.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "Tile.h"
|
||||
#include "EntityTile.h"
|
||||
|
||||
class TileEntity;
|
||||
|
||||
class BaseEntityTile : public Tile, public EntityTile
|
||||
{
|
||||
protected:
|
||||
BaseEntityTile(int id, Material *material, bool isSolidRender = true);
|
||||
public:
|
||||
virtual void onPlace(Level *level, int x, int y, int z);
|
||||
virtual void onRemove(Level *level, int x, int y, int z, int id, int data);
|
||||
virtual bool triggerEvent(Level *level, int x, int y, int z, int b0, int b1);
|
||||
};
|
||||
401
Minecraft.World/BaseMobSpawner.cpp
Normal file
401
Minecraft.World/BaseMobSpawner.cpp
Normal file
@@ -0,0 +1,401 @@
|
||||
#include "stdafx.h"
|
||||
#include "net.minecraft.world.entity.h"
|
||||
#include "net.minecraft.world.entity.item.h"
|
||||
#include "net.minecraft.world.level.h"
|
||||
#include "net.minecraft.world.level.tile.h"
|
||||
#include "net.minecraft.world.phys.h"
|
||||
#include "BaseMobSpawner.h"
|
||||
|
||||
BaseMobSpawner::BaseMobSpawner()
|
||||
{
|
||||
spawnPotentials = NULL;
|
||||
spawnDelay = 20;
|
||||
entityId = L"Pig";
|
||||
nextSpawnData = NULL;
|
||||
spin = oSpin = 0.0;
|
||||
|
||||
minSpawnDelay = SharedConstants::TICKS_PER_SECOND * 10;
|
||||
maxSpawnDelay = SharedConstants::TICKS_PER_SECOND * 40;
|
||||
spawnCount = 4;
|
||||
displayEntity = nullptr;
|
||||
maxNearbyEntities = 6;
|
||||
requiredPlayerRange = 16;
|
||||
spawnRange = 4;
|
||||
}
|
||||
|
||||
BaseMobSpawner::~BaseMobSpawner()
|
||||
{
|
||||
if(spawnPotentials)
|
||||
{
|
||||
for(AUTO_VAR(it,spawnPotentials->begin()); it != spawnPotentials->end(); ++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
delete spawnPotentials;
|
||||
}
|
||||
}
|
||||
|
||||
wstring BaseMobSpawner::getEntityId()
|
||||
{
|
||||
if (getNextSpawnData() == NULL)
|
||||
{
|
||||
if (entityId.compare(L"Minecart") == 0)
|
||||
{
|
||||
entityId = L"MinecartRideable";
|
||||
}
|
||||
return entityId;
|
||||
}
|
||||
else
|
||||
{
|
||||
return getNextSpawnData()->type;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseMobSpawner::setEntityId(const wstring &entityId)
|
||||
{
|
||||
this->entityId = entityId;
|
||||
}
|
||||
|
||||
bool BaseMobSpawner::isNearPlayer()
|
||||
{
|
||||
return getLevel()->getNearestPlayer(getX() + 0.5, getY() + 0.5, getZ() + 0.5, requiredPlayerRange) != NULL;
|
||||
}
|
||||
|
||||
void BaseMobSpawner::tick()
|
||||
{
|
||||
if (!isNearPlayer())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (getLevel()->isClientSide)
|
||||
{
|
||||
double xP = getX() + getLevel()->random->nextFloat();
|
||||
double yP = getY() + getLevel()->random->nextFloat();
|
||||
double zP = getZ() + getLevel()->random->nextFloat();
|
||||
getLevel()->addParticle(eParticleType_smoke, xP, yP, zP, 0, 0, 0);
|
||||
getLevel()->addParticle(eParticleType_flame, xP, yP, zP, 0, 0, 0);
|
||||
|
||||
if (spawnDelay > 0) spawnDelay--;
|
||||
oSpin = spin;
|
||||
spin = (int)(spin + 1000 / (spawnDelay + 200.0f)) % 360;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spawnDelay == -1) delay();
|
||||
|
||||
if (spawnDelay > 0)
|
||||
{
|
||||
spawnDelay--;
|
||||
return;
|
||||
}
|
||||
|
||||
bool _delay = false;
|
||||
|
||||
for (int c = 0; c < spawnCount; c++)
|
||||
{
|
||||
shared_ptr<Entity> entity = EntityIO::newEntity(getEntityId(), getLevel());
|
||||
if (entity == NULL) return;
|
||||
|
||||
int nearBy = getLevel()->getEntitiesOfClass( typeid(entity.get()), AABB::newTemp(getX(), getY(), getZ(), getX() + 1, getY() + 1, getZ() + 1)->grow(spawnRange * 2, 4, spawnRange * 2))->size();
|
||||
if (nearBy >= maxNearbyEntities)
|
||||
{
|
||||
delay();
|
||||
return;
|
||||
}
|
||||
|
||||
double xp = getX() + (getLevel()->random->nextDouble() - getLevel()->random->nextDouble()) * spawnRange;
|
||||
double yp = getY() + getLevel()->random->nextInt(3) - 1;
|
||||
double zp = getZ() + (getLevel()->random->nextDouble() - getLevel()->random->nextDouble()) * spawnRange;
|
||||
shared_ptr<Mob> mob = entity->instanceof(eTYPE_MOB) ? dynamic_pointer_cast<Mob>( entity ) : nullptr;
|
||||
|
||||
entity->moveTo(xp, yp, zp, getLevel()->random->nextFloat() * 360, 0);
|
||||
|
||||
if (mob == NULL || mob->canSpawn())
|
||||
{
|
||||
loadDataAndAddEntity(entity);
|
||||
getLevel()->levelEvent(LevelEvent::PARTICLES_MOBTILE_SPAWN, getX(), getY(), getZ(), 0);
|
||||
|
||||
if (mob != NULL)
|
||||
{
|
||||
mob->spawnAnim();
|
||||
}
|
||||
|
||||
_delay = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_delay) delay();
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<Entity> BaseMobSpawner::loadDataAndAddEntity(shared_ptr<Entity> entity)
|
||||
{
|
||||
if (getNextSpawnData() != NULL)
|
||||
{
|
||||
CompoundTag *data = new CompoundTag();
|
||||
entity->save(data);
|
||||
|
||||
vector<Tag *> *tags = getNextSpawnData()->tag->getAllTags();
|
||||
for (AUTO_VAR(it, tags->begin()); it != tags->end(); ++it)
|
||||
{
|
||||
Tag *tag = *it;
|
||||
data->put(tag->getName(), tag->copy());
|
||||
}
|
||||
delete tags;
|
||||
|
||||
entity->load(data);
|
||||
if (entity->level != NULL) entity->level->addEntity(entity);
|
||||
|
||||
// add mounts
|
||||
shared_ptr<Entity> rider = entity;
|
||||
while (data->contains(Entity::RIDING_TAG))
|
||||
{
|
||||
CompoundTag *ridingTag = data->getCompound(Entity::RIDING_TAG);
|
||||
shared_ptr<Entity> mount = EntityIO::newEntity(ridingTag->getString(L"id"), entity->level);
|
||||
if (mount != NULL)
|
||||
{
|
||||
CompoundTag *mountData = new CompoundTag();
|
||||
mount->save(mountData);
|
||||
|
||||
vector<Tag *> *ridingTags = ridingTag->getAllTags();
|
||||
for (AUTO_VAR(it, ridingTags->begin()); it != ridingTags->end(); ++it)
|
||||
{
|
||||
Tag *tag = *it;
|
||||
mountData->put(tag->getName(), tag->copy());
|
||||
}
|
||||
delete ridingTags;
|
||||
mount->load(mountData);
|
||||
mount->moveTo(rider->x, rider->y, rider->z, rider->yRot, rider->xRot);
|
||||
|
||||
if (entity->level != NULL) entity->level->addEntity(mount);
|
||||
rider->ride(mount);
|
||||
}
|
||||
rider = mount;
|
||||
data = ridingTag;
|
||||
}
|
||||
|
||||
}
|
||||
else if (entity->instanceof(eTYPE_LIVINGENTITY) && entity->level != NULL)
|
||||
{
|
||||
dynamic_pointer_cast<Mob>( entity )->finalizeMobSpawn(NULL);
|
||||
getLevel()->addEntity(entity);
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
void BaseMobSpawner::delay()
|
||||
{
|
||||
if (maxSpawnDelay <= minSpawnDelay)
|
||||
{
|
||||
spawnDelay = minSpawnDelay;
|
||||
}
|
||||
else
|
||||
{
|
||||
spawnDelay = minSpawnDelay + getLevel()->random->nextInt(maxSpawnDelay - minSpawnDelay);
|
||||
}
|
||||
|
||||
if ( (spawnPotentials != NULL) && (spawnPotentials->size() > 0) )
|
||||
{
|
||||
setNextSpawnData( (SpawnData*) WeighedRandom::getRandomItem((Random*)getLevel()->random, (vector<WeighedRandomItem*>*)spawnPotentials) );
|
||||
}
|
||||
|
||||
broadcastEvent(EVENT_SPAWN);
|
||||
}
|
||||
|
||||
void BaseMobSpawner::load(CompoundTag *tag)
|
||||
{
|
||||
entityId = tag->getString(L"EntityId");
|
||||
spawnDelay = tag->getShort(L"Delay");
|
||||
|
||||
if (tag->contains(L"SpawnPotentials"))
|
||||
{
|
||||
spawnPotentials = new vector<SpawnData *>();
|
||||
ListTag<CompoundTag> *potentials = (ListTag<CompoundTag> *) tag->getList(L"SpawnPotentials");
|
||||
|
||||
for (int i = 0; i < potentials->size(); i++)
|
||||
{
|
||||
spawnPotentials->push_back(new SpawnData(potentials->get(i)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
spawnPotentials = NULL;
|
||||
}
|
||||
|
||||
if (tag->contains(L"SpawnData"))
|
||||
{
|
||||
setNextSpawnData(new SpawnData(tag->getCompound(L"SpawnData"), entityId));
|
||||
}
|
||||
else
|
||||
{
|
||||
setNextSpawnData(NULL);
|
||||
}
|
||||
|
||||
if (tag->contains(L"MinSpawnDelay"))
|
||||
{
|
||||
minSpawnDelay = tag->getShort(L"MinSpawnDelay");
|
||||
maxSpawnDelay = tag->getShort(L"MaxSpawnDelay");
|
||||
spawnCount = tag->getShort(L"SpawnCount");
|
||||
}
|
||||
|
||||
if (tag->contains(L"MaxNearbyEntities"))
|
||||
{
|
||||
maxNearbyEntities = tag->getShort(L"MaxNearbyEntities");
|
||||
requiredPlayerRange = tag->getShort(L"RequiredPlayerRange");
|
||||
}
|
||||
|
||||
if (tag->contains(L"SpawnRange")) spawnRange = tag->getShort(L"SpawnRange");
|
||||
|
||||
if (getLevel() != NULL && getLevel()->isClientSide)
|
||||
{
|
||||
displayEntity = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseMobSpawner::save(CompoundTag *tag)
|
||||
{
|
||||
tag->putString(L"EntityId", getEntityId());
|
||||
tag->putShort(L"Delay", (short) spawnDelay);
|
||||
tag->putShort(L"MinSpawnDelay", (short) minSpawnDelay);
|
||||
tag->putShort(L"MaxSpawnDelay", (short) maxSpawnDelay);
|
||||
tag->putShort(L"SpawnCount", (short) spawnCount);
|
||||
tag->putShort(L"MaxNearbyEntities", (short) maxNearbyEntities);
|
||||
tag->putShort(L"RequiredPlayerRange", (short) requiredPlayerRange);
|
||||
tag->putShort(L"SpawnRange", (short) spawnRange);
|
||||
|
||||
if (getNextSpawnData() != NULL)
|
||||
{
|
||||
tag->putCompound(L"SpawnData", (CompoundTag *) getNextSpawnData()->tag->copy());
|
||||
}
|
||||
|
||||
if (getNextSpawnData() != NULL || (spawnPotentials != NULL && spawnPotentials->size() > 0))
|
||||
{
|
||||
ListTag<CompoundTag> *list = new ListTag<CompoundTag>();
|
||||
|
||||
if (spawnPotentials != NULL && spawnPotentials->size() > 0)
|
||||
{
|
||||
for (AUTO_VAR(it, spawnPotentials->begin()); it != spawnPotentials->end(); ++it)
|
||||
{
|
||||
SpawnData *data = *it;
|
||||
list->add(data->save());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
list->add(getNextSpawnData()->save());
|
||||
}
|
||||
|
||||
tag->put(L"SpawnPotentials", list);
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<Entity> BaseMobSpawner::getDisplayEntity()
|
||||
{
|
||||
if (displayEntity == NULL)
|
||||
{
|
||||
shared_ptr<Entity> e = EntityIO::newEntity(getEntityId(), NULL);
|
||||
e = loadDataAndAddEntity(e);
|
||||
displayEntity = e;
|
||||
}
|
||||
|
||||
return displayEntity;
|
||||
}
|
||||
|
||||
bool BaseMobSpawner::onEventTriggered(int id)
|
||||
{
|
||||
if (id == EVENT_SPAWN && getLevel()->isClientSide)
|
||||
{
|
||||
spawnDelay = minSpawnDelay;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
BaseMobSpawner::SpawnData *BaseMobSpawner::getNextSpawnData()
|
||||
{
|
||||
return nextSpawnData;
|
||||
}
|
||||
|
||||
void BaseMobSpawner::setNextSpawnData(SpawnData *nextSpawnData)
|
||||
{
|
||||
this->nextSpawnData = nextSpawnData;
|
||||
}
|
||||
|
||||
BaseMobSpawner::SpawnData::SpawnData(CompoundTag *base) : WeighedRandomItem(base->getInt(L"Weight"))
|
||||
{
|
||||
CompoundTag *tag = base->getCompound(L"Properties");
|
||||
wstring _type = base->getString(L"Type");
|
||||
|
||||
if (_type.compare(L"Minecart") == 0)
|
||||
{
|
||||
if (tag != NULL)
|
||||
{
|
||||
switch (tag->getInt(L"Type"))
|
||||
{
|
||||
case Minecart::TYPE_CHEST:
|
||||
type = L"MinecartChest";
|
||||
break;
|
||||
case Minecart::TYPE_FURNACE:
|
||||
type = L"MinecartFurnace";
|
||||
break;
|
||||
case Minecart::TYPE_RIDEABLE:
|
||||
type = L"MinecartRideable";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
type = L"MinecartRideable";
|
||||
}
|
||||
}
|
||||
|
||||
this->tag = tag;
|
||||
this->type = _type;
|
||||
}
|
||||
|
||||
BaseMobSpawner::SpawnData::SpawnData(CompoundTag *tag, wstring _type) : WeighedRandomItem(1)
|
||||
{
|
||||
if (_type.compare(L"Minecart") == 0)
|
||||
{
|
||||
if (tag != NULL)
|
||||
{
|
||||
switch (tag->getInt(L"Type"))
|
||||
{
|
||||
case Minecart::TYPE_CHEST:
|
||||
_type = L"MinecartChest";
|
||||
break;
|
||||
case Minecart::TYPE_FURNACE:
|
||||
_type = L"MinecartFurnace";
|
||||
break;
|
||||
case Minecart::TYPE_RIDEABLE:
|
||||
_type = L"MinecartRideable";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_type = L"MinecartRideable";
|
||||
}
|
||||
}
|
||||
|
||||
this->tag = tag;
|
||||
this->type = _type;
|
||||
}
|
||||
|
||||
BaseMobSpawner::SpawnData::~SpawnData()
|
||||
{
|
||||
delete tag;
|
||||
}
|
||||
|
||||
CompoundTag *BaseMobSpawner::SpawnData::save()
|
||||
{
|
||||
CompoundTag *result = new CompoundTag();
|
||||
|
||||
result->putCompound(L"Properties", tag);
|
||||
result->putString(L"Type", type);
|
||||
result->putInt(L"Weight", randomWeight);
|
||||
|
||||
return result;
|
||||
}
|
||||
70
Minecraft.World/BaseMobSpawner.h
Normal file
70
Minecraft.World/BaseMobSpawner.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include "WeighedRandom.h"
|
||||
|
||||
class BaseMobSpawner
|
||||
{
|
||||
public:
|
||||
class SpawnData : public WeighedRandomItem
|
||||
{
|
||||
public:
|
||||
CompoundTag *tag;
|
||||
wstring type;
|
||||
|
||||
SpawnData(CompoundTag *base);
|
||||
SpawnData(CompoundTag *tag, wstring type);
|
||||
~SpawnData();
|
||||
|
||||
virtual CompoundTag *save();
|
||||
};
|
||||
|
||||
private:
|
||||
static const int EVENT_SPAWN = 1;
|
||||
|
||||
public:
|
||||
int spawnDelay;
|
||||
|
||||
private:
|
||||
wstring entityId;
|
||||
vector<SpawnData *> *spawnPotentials;
|
||||
SpawnData *nextSpawnData;
|
||||
|
||||
public:
|
||||
double spin, oSpin;
|
||||
|
||||
private:
|
||||
int minSpawnDelay;
|
||||
int maxSpawnDelay;
|
||||
int spawnCount;
|
||||
shared_ptr<Entity> displayEntity;
|
||||
int maxNearbyEntities;
|
||||
int requiredPlayerRange;
|
||||
int spawnRange;
|
||||
|
||||
public:
|
||||
BaseMobSpawner();
|
||||
~BaseMobSpawner();
|
||||
|
||||
virtual wstring getEntityId();
|
||||
virtual void setEntityId(const wstring &entityId);
|
||||
virtual bool isNearPlayer();
|
||||
virtual void tick();
|
||||
virtual shared_ptr<Entity> loadDataAndAddEntity(shared_ptr<Entity> entity);
|
||||
|
||||
private:
|
||||
virtual void delay();
|
||||
|
||||
public:
|
||||
virtual void load(CompoundTag *tag);
|
||||
virtual void save(CompoundTag *tag);
|
||||
virtual shared_ptr<Entity> getDisplayEntity();
|
||||
virtual bool onEventTriggered(int id);
|
||||
virtual SpawnData *getNextSpawnData();
|
||||
virtual void setNextSpawnData(SpawnData *nextSpawnData);
|
||||
|
||||
virtual void broadcastEvent(int id) = 0;
|
||||
virtual Level *getLevel() = 0;
|
||||
virtual int getX() = 0;
|
||||
virtual int getY() = 0;
|
||||
virtual int getZ() = 0;
|
||||
};
|
||||
189
Minecraft.World/BasePressurePlateTile.cpp
Normal file
189
Minecraft.World/BasePressurePlateTile.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
#include "stdafx.h"
|
||||
#include "net.minecraft.world.level.h"
|
||||
#include "net.minecraft.world.level.redstone.h"
|
||||
#include "net.minecraft.world.level.tile.h"
|
||||
#include "net.minecraft.world.phys.h"
|
||||
#include "net.minecraft.h"
|
||||
#include "net.minecraft.world.h"
|
||||
#include "BasePressurePlateTile.h"
|
||||
|
||||
BasePressurePlateTile::BasePressurePlateTile(int id, const wstring &tex, Material *material) : Tile(id, material, isSolidRender())
|
||||
{
|
||||
texture = tex;
|
||||
setTicking(true);
|
||||
|
||||
// 4J Stu - Move this to derived classes
|
||||
//updateShape(getDataForSignal(Redstone::SIGNAL_MAX));
|
||||
}
|
||||
|
||||
void BasePressurePlateTile::updateShape(LevelSource *level, int x, int y, int z, int forceData, shared_ptr<TileEntity> forceEntity)
|
||||
{
|
||||
updateShape(level->getData(x, y, z));
|
||||
}
|
||||
|
||||
void BasePressurePlateTile::updateShape(int data)
|
||||
{
|
||||
bool pressed = getSignalForData(data) > Redstone::SIGNAL_NONE;
|
||||
float o = 1 / 16.0f;
|
||||
|
||||
if (pressed)
|
||||
{
|
||||
setShape(o, 0, o, 1 - o, 0.5f / 16.0f, 1 - o);
|
||||
}
|
||||
else
|
||||
{
|
||||
setShape(o, 0, o, 1 - o, 1 / 16.0f, 1 - o);
|
||||
}
|
||||
}
|
||||
|
||||
int BasePressurePlateTile::getTickDelay(Level *level)
|
||||
{
|
||||
return SharedConstants::TICKS_PER_SECOND;
|
||||
}
|
||||
|
||||
AABB *BasePressurePlateTile::getAABB(Level *level, int x, int y, int z)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool BasePressurePlateTile::isSolidRender(bool isServerLevel)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BasePressurePlateTile::blocksLight()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BasePressurePlateTile::isCubeShaped()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BasePressurePlateTile::isPathfindable(LevelSource *level, int x, int y, int z)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BasePressurePlateTile::mayPlace(Level *level, int x, int y, int z)
|
||||
{
|
||||
return level->isTopSolidBlocking(x, y - 1, z) || FenceTile::isFence(level->getTile(x, y - 1, z));
|
||||
}
|
||||
|
||||
void BasePressurePlateTile::neighborChanged(Level *level, int x, int y, int z, int type)
|
||||
{
|
||||
bool replace = false;
|
||||
|
||||
if (!level->isTopSolidBlocking(x, y - 1, z) && !FenceTile::isFence(level->getTile(x, y - 1, z))) replace = true;
|
||||
|
||||
if (replace)
|
||||
{
|
||||
spawnResources(level, x, y, z, level->getData(x, y, z), 0);
|
||||
level->removeTile(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
void BasePressurePlateTile::tick(Level *level, int x, int y, int z, Random *random)
|
||||
{
|
||||
if (level->isClientSide) return;
|
||||
int signal = getSignalForData(level->getData(x, y, z));
|
||||
if (signal > Redstone::SIGNAL_NONE) checkPressed(level, x, y, z, signal);
|
||||
}
|
||||
|
||||
void BasePressurePlateTile::entityInside(Level *level, int x, int y, int z, shared_ptr<Entity> entity)
|
||||
{
|
||||
if (level->isClientSide) return;
|
||||
int signal = getSignalForData(level->getData(x, y, z));
|
||||
if (signal == Redstone::SIGNAL_NONE) checkPressed(level, x, y, z, signal);
|
||||
}
|
||||
|
||||
void BasePressurePlateTile::checkPressed(Level *level, int x, int y, int z, int oldSignal)
|
||||
{
|
||||
int signal = getSignalStrength(level, x, y, z);
|
||||
bool wasPressed = oldSignal > Redstone::SIGNAL_NONE;
|
||||
bool shouldBePressed = signal > Redstone::SIGNAL_NONE;
|
||||
|
||||
if (oldSignal != signal)
|
||||
{
|
||||
level->setData(x, y, z, getDataForSignal(signal), Tile::UPDATE_CLIENTS);
|
||||
updateNeighbours(level, x, y, z);
|
||||
level->setTilesDirty(x, y, z, x, y, z);
|
||||
}
|
||||
|
||||
if (!shouldBePressed && wasPressed)
|
||||
{
|
||||
level->playSound(x + 0.5, y + 0.1, z + 0.5, eSoundType_RANDOM_CLICK, 0.3f, 0.5f);
|
||||
}
|
||||
else if (shouldBePressed && !wasPressed)
|
||||
{
|
||||
level->playSound(x + 0.5, y + 0.1, z + 0.5, eSoundType_RANDOM_CLICK, 0.3f, 0.6f);
|
||||
}
|
||||
|
||||
if (shouldBePressed)
|
||||
{
|
||||
level->addToTickNextTick(x, y, z, id, getTickDelay(level));
|
||||
}
|
||||
}
|
||||
|
||||
AABB *BasePressurePlateTile::getSensitiveAABB(int x, int y, int z)
|
||||
{
|
||||
float b = 2 / 16.0f;
|
||||
return AABB::newTemp(x + b, y, z + b, x + 1 - b, y + 0.25, z + 1 - b);
|
||||
}
|
||||
|
||||
void BasePressurePlateTile::onRemove(Level *level, int x, int y, int z, int id, int data)
|
||||
{
|
||||
if (getSignalForData(data) > 0)
|
||||
{
|
||||
updateNeighbours(level, x, y, z);
|
||||
}
|
||||
|
||||
Tile::onRemove(level, x, y, z, id, data);
|
||||
}
|
||||
|
||||
void BasePressurePlateTile::updateNeighbours(Level *level, int x, int y, int z)
|
||||
{
|
||||
level->updateNeighborsAt(x, y, z, id);
|
||||
level->updateNeighborsAt(x, y - 1, z, id);
|
||||
}
|
||||
|
||||
int BasePressurePlateTile::getSignal(LevelSource *level, int x, int y, int z, int dir)
|
||||
{
|
||||
return getSignalForData(level->getData(x, y, z));
|
||||
}
|
||||
|
||||
int BasePressurePlateTile::getDirectSignal(LevelSource *level, int x, int y, int z, int dir)
|
||||
{
|
||||
if (dir == Facing::UP)
|
||||
{
|
||||
return getSignalForData(level->getData(x, y, z));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Redstone::SIGNAL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
bool BasePressurePlateTile::isSignalSource()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void BasePressurePlateTile::updateDefaultShape()
|
||||
{
|
||||
float x = 8 / 16.0f;
|
||||
float y = 2 / 16.0f;
|
||||
float z = 8 / 16.0f;
|
||||
setShape(0.5f - x, 0.5f - y, 0.5f - z, 0.5f + x, 0.5f + y, 0.5f + z);
|
||||
}
|
||||
|
||||
int BasePressurePlateTile::getPistonPushReaction()
|
||||
{
|
||||
return Material::PUSH_DESTROY;
|
||||
}
|
||||
|
||||
void BasePressurePlateTile::registerIcons(IconRegister *iconRegister)
|
||||
{
|
||||
icon = iconRegister->registerIcon(texture);
|
||||
}
|
||||
55
Minecraft.World/BasePressurePlateTile.h
Normal file
55
Minecraft.World/BasePressurePlateTile.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include "Tile.h"
|
||||
|
||||
class BasePressurePlateTile : public Tile
|
||||
{
|
||||
private:
|
||||
wstring texture;
|
||||
|
||||
protected:
|
||||
BasePressurePlateTile(int id, const wstring &tex, Material *material);
|
||||
|
||||
public:
|
||||
virtual void updateShape(LevelSource *level, int x, int y, int z, int forceData = -1, shared_ptr<TileEntity> forceEntity = shared_ptr<TileEntity>());
|
||||
|
||||
protected:
|
||||
virtual void updateShape(int data);
|
||||
|
||||
public:
|
||||
virtual int getTickDelay(Level *level);
|
||||
virtual AABB *getAABB(Level *level, int x, int y, int z);
|
||||
virtual bool isSolidRender(bool isServerLevel = false);
|
||||
virtual bool blocksLight();
|
||||
virtual bool isCubeShaped();
|
||||
virtual bool isPathfindable(LevelSource *level, int x, int y, int z);
|
||||
virtual bool mayPlace(Level *level, int x, int y, int z);
|
||||
virtual void neighborChanged(Level *level, int x, int y, int z, int type);
|
||||
virtual void tick(Level *level, int x, int y, int z, Random *random);
|
||||
virtual void entityInside(Level *level, int x, int y, int z, shared_ptr<Entity> entity);
|
||||
|
||||
protected:
|
||||
virtual void checkPressed(Level *level, int x, int y, int z, int oldSignal);
|
||||
virtual AABB *getSensitiveAABB(int x, int y, int z);
|
||||
|
||||
public:
|
||||
virtual void onRemove(Level *level, int x, int y, int z, int id, int data);
|
||||
|
||||
protected:
|
||||
virtual void updateNeighbours(Level *level, int x, int y, int z);
|
||||
|
||||
public:
|
||||
virtual int getSignal(LevelSource *level, int x, int y, int z, int dir);
|
||||
virtual int getDirectSignal(LevelSource *level, int x, int y, int z, int dir);
|
||||
virtual bool isSignalSource();
|
||||
virtual void updateDefaultShape();
|
||||
virtual int getPistonPushReaction();
|
||||
|
||||
protected:
|
||||
virtual int getSignalStrength(Level *level, int x, int y, int z) = 0;
|
||||
virtual int getSignalForData(int data) = 0;
|
||||
virtual int getDataForSignal(int signal) = 0;
|
||||
|
||||
public:
|
||||
virtual void registerIcons(IconRegister *iconRegister);
|
||||
};
|
||||
511
Minecraft.World/BaseRailTile.cpp
Normal file
511
Minecraft.World/BaseRailTile.cpp
Normal file
@@ -0,0 +1,511 @@
|
||||
#include "stdafx.h"
|
||||
#include "net.minecraft.world.phys.h"
|
||||
#include "net.minecraft.world.level.h"
|
||||
#include "net.minecraft.world.h"
|
||||
#include "BaseRailTile.h"
|
||||
|
||||
BaseRailTile::Rail::Rail(Level *level, int x, int y, int z)
|
||||
{
|
||||
this->level = level;
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
|
||||
int id = level->getTile(x, y, z);
|
||||
|
||||
// 4J Stu - We saw a random crash near the end of development on XboxOne orignal version where the id here isn't a tile any more
|
||||
// Adding this check in to avoid that crash
|
||||
m_bValidRail = isRail(id);
|
||||
if(m_bValidRail)
|
||||
{
|
||||
int direction = level->getData(x, y, z);
|
||||
if (((BaseRailTile *) Tile::tiles[id])->usesDataBit)
|
||||
{
|
||||
usesDataBit = true;
|
||||
direction = direction & ~RAIL_DATA_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
usesDataBit = false;
|
||||
}
|
||||
updateConnections(direction);
|
||||
}
|
||||
}
|
||||
|
||||
BaseRailTile::Rail::~Rail()
|
||||
{
|
||||
for( int i = 0; i < connections.size(); i++ )
|
||||
{
|
||||
delete connections[i];
|
||||
}
|
||||
}
|
||||
|
||||
void BaseRailTile::Rail::updateConnections(int direction)
|
||||
{
|
||||
if(m_bValidRail)
|
||||
{
|
||||
for( int i = 0; i < connections.size(); i++ )
|
||||
{
|
||||
delete connections[i];
|
||||
}
|
||||
connections.clear();
|
||||
MemSect(50);
|
||||
if (direction == DIR_FLAT_Z)
|
||||
{
|
||||
connections.push_back(new TilePos(x, y, z - 1));
|
||||
connections.push_back(new TilePos(x, y, z + 1));
|
||||
} else if (direction == DIR_FLAT_X)
|
||||
{
|
||||
connections.push_back(new TilePos(x - 1, y, z));
|
||||
connections.push_back(new TilePos(x + 1, y, z));
|
||||
} else if (direction == 2)
|
||||
{
|
||||
connections.push_back(new TilePos(x - 1, y, z));
|
||||
connections.push_back(new TilePos(x + 1, y + 1, z));
|
||||
} else if (direction == 3)
|
||||
{
|
||||
connections.push_back(new TilePos(x - 1, y + 1, z));
|
||||
connections.push_back(new TilePos(x + 1, y, z));
|
||||
} else if (direction == 4)
|
||||
{
|
||||
connections.push_back(new TilePos(x, y + 1, z - 1));
|
||||
connections.push_back(new TilePos(x, y, z + 1));
|
||||
} else if (direction == 5)
|
||||
{
|
||||
connections.push_back(new TilePos(x, y, z - 1));
|
||||
connections.push_back(new TilePos(x, y + 1, z + 1));
|
||||
} else if (direction == 6)
|
||||
{
|
||||
connections.push_back(new TilePos(x + 1, y, z));
|
||||
connections.push_back(new TilePos(x, y, z + 1));
|
||||
} else if (direction == 7)
|
||||
{
|
||||
connections.push_back(new TilePos(x - 1, y, z));
|
||||
connections.push_back(new TilePos(x, y, z + 1));
|
||||
} else if (direction == 8)
|
||||
{
|
||||
connections.push_back(new TilePos(x - 1, y, z));
|
||||
connections.push_back(new TilePos(x, y, z - 1));
|
||||
} else if (direction == 9)
|
||||
{
|
||||
connections.push_back(new TilePos(x + 1, y, z));
|
||||
connections.push_back(new TilePos(x, y, z - 1));
|
||||
}
|
||||
MemSect(0);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseRailTile::Rail::removeSoftConnections()
|
||||
{
|
||||
if(m_bValidRail)
|
||||
{
|
||||
for (unsigned int i = 0; i < connections.size(); i++)
|
||||
{
|
||||
Rail *rail = getRail(connections[i]);
|
||||
if (rail == NULL || !rail->connectsTo(this))
|
||||
{
|
||||
delete connections[i];
|
||||
connections.erase(connections.begin()+i);
|
||||
i--;
|
||||
} else
|
||||
{
|
||||
delete connections[i];
|
||||
MemSect(50);
|
||||
connections[i] =new TilePos(rail->x, rail->y, rail->z);
|
||||
MemSect(0);
|
||||
}
|
||||
delete rail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BaseRailTile::Rail::hasRail(int x, int y, int z)
|
||||
{
|
||||
if(!m_bValidRail) return false;
|
||||
if (isRail(level, x, y, z)) return true;
|
||||
if (isRail(level, x, y + 1, z)) return true;
|
||||
if (isRail(level, x, y - 1, z)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
BaseRailTile::Rail *BaseRailTile::Rail::getRail(TilePos *p)
|
||||
{
|
||||
if(!m_bValidRail) return NULL;
|
||||
if (isRail(level, p->x, p->y, p->z)) return new Rail(level, p->x, p->y, p->z);
|
||||
if (isRail(level, p->x, p->y + 1, p->z)) return new Rail(level, p->x, p->y + 1, p->z);
|
||||
if (isRail(level, p->x, p->y - 1, p->z)) return new Rail(level, p->x, p->y - 1, p->z);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool BaseRailTile::Rail::connectsTo(Rail *rail)
|
||||
{
|
||||
if(m_bValidRail)
|
||||
{
|
||||
AUTO_VAR(itEnd, connections.end());
|
||||
for (AUTO_VAR(it, connections.begin()); it != itEnd; it++)
|
||||
{
|
||||
TilePos *p = *it; //connections[i];
|
||||
if (p->x == rail->x && p->z == rail->z)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BaseRailTile::Rail::hasConnection(int x, int y, int z)
|
||||
{
|
||||
if(m_bValidRail)
|
||||
{
|
||||
AUTO_VAR(itEnd, connections.end());
|
||||
for (AUTO_VAR(it, connections.begin()); it != itEnd; it++)
|
||||
{
|
||||
TilePos *p = *it; //connections[i];
|
||||
if (p->x == x && p->z == z)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int BaseRailTile::Rail::countPotentialConnections()
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if(m_bValidRail)
|
||||
{
|
||||
if (hasRail(x, y, z - 1)) count++;
|
||||
if (hasRail(x, y, z + 1)) count++;
|
||||
if (hasRail(x - 1, y, z)) count++;
|
||||
if (hasRail(x + 1, y, z)) count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool BaseRailTile::Rail::canConnectTo(Rail *rail)
|
||||
{
|
||||
if(!m_bValidRail) return false;
|
||||
if (connectsTo(rail)) return true;
|
||||
if (connections.size() == 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (connections.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BaseRailTile::Rail::connectTo(Rail *rail)
|
||||
{
|
||||
if(m_bValidRail)
|
||||
{
|
||||
MemSect(50);
|
||||
connections.push_back(new TilePos(rail->x, rail->y, rail->z));
|
||||
MemSect(0);
|
||||
|
||||
bool n = hasConnection(x, y, z - 1);
|
||||
bool s = hasConnection(x, y, z + 1);
|
||||
bool w = hasConnection(x - 1, y, z);
|
||||
bool e = hasConnection(x + 1, y, z);
|
||||
|
||||
int dir = -1;
|
||||
|
||||
if (n || s) dir = DIR_FLAT_Z;
|
||||
if (w || e) dir = DIR_FLAT_X;
|
||||
|
||||
if (!usesDataBit)
|
||||
{
|
||||
if (s && e && !n && !w) dir = 6;
|
||||
if (s && w && !n && !e) dir = 7;
|
||||
if (n && w && !s && !e) dir = 8;
|
||||
if (n && e && !s && !w) dir = 9;
|
||||
}
|
||||
if (dir == DIR_FLAT_Z)
|
||||
{
|
||||
if (isRail(level, x, y + 1, z - 1)) dir = 4;
|
||||
if (isRail(level, x, y + 1, z + 1)) dir = 5;
|
||||
}
|
||||
if (dir == DIR_FLAT_X)
|
||||
{
|
||||
if (isRail(level, x + 1, y + 1, z)) dir = 2;
|
||||
if (isRail(level, x - 1, y + 1, z)) dir = 3;
|
||||
}
|
||||
|
||||
if (dir < 0) dir = DIR_FLAT_Z;
|
||||
|
||||
int data = dir;
|
||||
if (usesDataBit)
|
||||
{
|
||||
data = (level->getData(x, y, z) & RAIL_DATA_BIT) | dir;
|
||||
}
|
||||
|
||||
level->setData(x, y, z, data, Tile::UPDATE_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
bool BaseRailTile::Rail::hasNeighborRail(int x, int y, int z)
|
||||
{
|
||||
if(!m_bValidRail) return false;
|
||||
TilePos tp(x,y,z);
|
||||
Rail *neighbor = getRail( &tp );
|
||||
if (neighbor == NULL) return false;
|
||||
neighbor->removeSoftConnections();
|
||||
bool retval = neighbor->canConnectTo(this);
|
||||
delete neighbor;
|
||||
return retval;
|
||||
}
|
||||
|
||||
void BaseRailTile::Rail::place(bool hasSignal, bool first)
|
||||
{
|
||||
if(m_bValidRail)
|
||||
{
|
||||
bool n = hasNeighborRail(x, y, z - 1);
|
||||
bool s = hasNeighborRail(x, y, z + 1);
|
||||
bool w = hasNeighborRail(x - 1, y, z);
|
||||
bool e = hasNeighborRail(x + 1, y, z);
|
||||
|
||||
int dir = -1;
|
||||
|
||||
if ((n || s) && !w && !e) dir = DIR_FLAT_Z;
|
||||
if ((w || e) && !n && !s) dir = DIR_FLAT_X;
|
||||
|
||||
if (!usesDataBit)
|
||||
{
|
||||
if (s && e && !n && !w) dir = 6;
|
||||
if (s && w && !n && !e) dir = 7;
|
||||
if (n && w && !s && !e) dir = 8;
|
||||
if (n && e && !s && !w) dir = 9;
|
||||
}
|
||||
if (dir == -1)
|
||||
{
|
||||
if (n || s) dir = DIR_FLAT_Z;
|
||||
if (w || e) dir = DIR_FLAT_X;
|
||||
|
||||
if (!usesDataBit)
|
||||
{
|
||||
if (hasSignal)
|
||||
{
|
||||
if (s && e) dir = 6;
|
||||
if (w && s) dir = 7;
|
||||
if (e && n) dir = 9;
|
||||
if (n && w) dir = 8;
|
||||
} else {
|
||||
if (n && w) dir = 8;
|
||||
if (e && n) dir = 9;
|
||||
if (w && s) dir = 7;
|
||||
if (s && e) dir = 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dir == DIR_FLAT_Z)
|
||||
{
|
||||
if (isRail(level, x, y + 1, z - 1)) dir = 4;
|
||||
if (isRail(level, x, y + 1, z + 1)) dir = 5;
|
||||
}
|
||||
if (dir == DIR_FLAT_X)
|
||||
{
|
||||
if (isRail(level, x + 1, y + 1, z)) dir = 2;
|
||||
if (isRail(level, x - 1, y + 1, z)) dir = 3;
|
||||
}
|
||||
|
||||
if (dir < 0) dir = DIR_FLAT_Z;
|
||||
|
||||
updateConnections(dir);
|
||||
|
||||
int data = dir;
|
||||
if (usesDataBit)
|
||||
{
|
||||
data = (level->getData(x, y, z) & RAIL_DATA_BIT) | dir;
|
||||
}
|
||||
|
||||
if (first || level->getData(x, y, z) != data)
|
||||
{
|
||||
level->setData(x, y, z, data, Tile::UPDATE_ALL);
|
||||
|
||||
AUTO_VAR(itEnd, connections.end());
|
||||
for (AUTO_VAR(it, connections.begin()); it != itEnd; it++)
|
||||
{
|
||||
Rail *neighbor = getRail(*it);
|
||||
if (neighbor == NULL) continue;
|
||||
neighbor->removeSoftConnections();
|
||||
|
||||
if (neighbor->canConnectTo(this))
|
||||
{
|
||||
neighbor->connectTo(this);
|
||||
}
|
||||
delete neighbor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BaseRailTile::isRail(Level *level, int x, int y, int z)
|
||||
{
|
||||
return isRail(level->getTile(x, y, z));
|
||||
}
|
||||
|
||||
bool BaseRailTile::isRail(int id)
|
||||
{
|
||||
return id == Tile::rail_Id || id == Tile::goldenRail_Id || id == Tile::detectorRail_Id || id == Tile::activatorRail_Id;
|
||||
}
|
||||
|
||||
BaseRailTile::BaseRailTile(int id, bool usesDataBit) : Tile(id, Material::decoration, isSolidRender())
|
||||
{
|
||||
this->usesDataBit = usesDataBit;
|
||||
setShape(0, 0, 0, 1, 2 / 16.0f, 1);
|
||||
|
||||
iconTurn = NULL;
|
||||
}
|
||||
|
||||
bool BaseRailTile::isUsesDataBit()
|
||||
{
|
||||
return usesDataBit;
|
||||
}
|
||||
|
||||
AABB *BaseRailTile::getAABB(Level *level, int x, int y, int z)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool BaseRailTile::blocksLight()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BaseRailTile::isSolidRender(bool isServerLevel)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HitResult *BaseRailTile::clip(Level *level, int xt, int yt, int zt, Vec3 *a, Vec3 *b)
|
||||
{
|
||||
updateShape(level, xt, yt, zt);
|
||||
return Tile::clip(level, xt, yt, zt, a, b);
|
||||
}
|
||||
|
||||
void BaseRailTile::updateShape(LevelSource *level, int x, int y, int z, int forceData, shared_ptr<TileEntity> forceEntity) // 4J added forceData, forceEntity param
|
||||
{
|
||||
int data = level->getData(x, y, z);
|
||||
if (data >= 2 && data <= 5)
|
||||
{
|
||||
setShape(0, 0, 0, 1, 2 / 16.0f + 0.5f, 1);
|
||||
} else
|
||||
{
|
||||
setShape(0, 0, 0, 1, 2 / 16.0f, 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool BaseRailTile::isCubeShaped()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int BaseRailTile::getRenderShape()
|
||||
{
|
||||
return Tile::SHAPE_RAIL;
|
||||
}
|
||||
|
||||
int BaseRailTile::getResourceCount(Random random)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool BaseRailTile::mayPlace(Level *level, int x, int y, int z)
|
||||
{
|
||||
if (level->isTopSolidBlocking(x, y - 1, z))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BaseRailTile::onPlace(Level *level, int x, int y, int z)
|
||||
{
|
||||
if (!level->isClientSide)
|
||||
{
|
||||
updateDir(level, x, y, z, true);
|
||||
|
||||
if (usesDataBit)
|
||||
{
|
||||
neighborChanged(level, x, y, z, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BaseRailTile::neighborChanged(Level *level, int x, int y, int z, int type)
|
||||
{
|
||||
if (level->isClientSide) return;
|
||||
|
||||
int data = level->getData(x, y, z);
|
||||
int dir = data;
|
||||
if (usesDataBit) {
|
||||
dir = dir & RAIL_DIRECTION_MASK;
|
||||
}
|
||||
bool remove = false;
|
||||
|
||||
if (!level->isTopSolidBlocking(x, y - 1, z)) remove = true;
|
||||
if (dir == 2 && !level->isTopSolidBlocking(x + 1, y, z)) remove = true;
|
||||
if (dir == 3 && !level->isTopSolidBlocking(x - 1, y, z)) remove = true;
|
||||
if (dir == 4 && !level->isTopSolidBlocking(x, y, z - 1)) remove = true;
|
||||
if (dir == 5 && !level->isTopSolidBlocking(x, y, z + 1)) remove = true;
|
||||
|
||||
if (remove)
|
||||
{
|
||||
spawnResources(level, x, y, z, level->getData(x, y, z), 0);
|
||||
level->removeTile(x, y, z);
|
||||
}
|
||||
else
|
||||
{
|
||||
updateState(level, x, y, z, data, dir, type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BaseRailTile::updateState(Level *level, int x, int y, int z, int data, int dir, int type)
|
||||
{
|
||||
}
|
||||
|
||||
void BaseRailTile::updateDir(Level *level, int x, int y, int z, bool first)
|
||||
{
|
||||
if (level->isClientSide) return;
|
||||
Rail *rail = new Rail(level, x, y, z);
|
||||
rail->place(level->hasNeighborSignal(x, y, z), first);
|
||||
delete rail;
|
||||
}
|
||||
|
||||
int BaseRailTile::getPistonPushReaction()
|
||||
{
|
||||
// override the decoration material's reaction
|
||||
return Material::PUSH_NORMAL;
|
||||
}
|
||||
|
||||
void BaseRailTile::onRemove(Level *level, int x, int y, int z, int id, int data)
|
||||
{
|
||||
int dir = data;
|
||||
if (usesDataBit)
|
||||
{
|
||||
dir &= RAIL_DIRECTION_MASK;
|
||||
}
|
||||
|
||||
Tile::onRemove(level, x, y, z, id, data);
|
||||
|
||||
if (dir == 2 || dir == 3 || dir == 4 || dir == 5)
|
||||
{
|
||||
level->updateNeighborsAt(x, y + 1, z, id);
|
||||
}
|
||||
if (usesDataBit)
|
||||
{
|
||||
level->updateNeighborsAt(x, y, z, id);
|
||||
level->updateNeighborsAt(x, y - 1, z, id);
|
||||
}
|
||||
}
|
||||
89
Minecraft.World/BaseRailTile.h
Normal file
89
Minecraft.World/BaseRailTile.h
Normal file
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
#include "Tile.h"
|
||||
#include "TilePos.h"
|
||||
#include "Definitions.h"
|
||||
|
||||
class Random;
|
||||
class HitResult;
|
||||
class ChunkRebuildData;
|
||||
|
||||
using namespace std;
|
||||
|
||||
class BaseRailTile : public Tile
|
||||
{
|
||||
friend class Tile;
|
||||
friend class ChunkRebuildData;
|
||||
public:
|
||||
static const int DIR_FLAT_Z = 0;
|
||||
static const int DIR_FLAT_X = 1;
|
||||
// the data bit is used by boosters and detectors, so they can't turn
|
||||
static const int RAIL_DATA_BIT = 8;
|
||||
static const int RAIL_DIRECTION_MASK = 7;
|
||||
|
||||
private:
|
||||
Icon *iconTurn;
|
||||
|
||||
protected:
|
||||
bool usesDataBit;
|
||||
|
||||
class Rail
|
||||
{
|
||||
friend class BaseRailTile;
|
||||
friend class RailTile;
|
||||
private:
|
||||
Level *level;
|
||||
int x, y, z;
|
||||
bool usesDataBit;
|
||||
vector<TilePos *> connections;
|
||||
bool m_bValidRail; // 4J added
|
||||
|
||||
public:
|
||||
Rail(Level *level, int x, int y, int z);
|
||||
~Rail();
|
||||
private:
|
||||
void updateConnections(int direction);
|
||||
void removeSoftConnections();
|
||||
bool hasRail(int x, int y, int z);
|
||||
Rail *getRail(TilePos *p);
|
||||
bool connectsTo(Rail *rail);
|
||||
bool hasConnection(int x, int y, int z);
|
||||
|
||||
protected:
|
||||
int countPotentialConnections();
|
||||
|
||||
private:
|
||||
bool canConnectTo(Rail *rail);
|
||||
void connectTo(Rail *rail);
|
||||
bool hasNeighborRail(int x, int y, int z);
|
||||
public:
|
||||
void place(bool hasSignal, bool first);
|
||||
};
|
||||
public:
|
||||
static bool isRail(Level *level, int x, int y, int z);
|
||||
static bool isRail(int id);
|
||||
protected:
|
||||
BaseRailTile(int id, bool usesDataBit);
|
||||
public:
|
||||
using Tile::getResourceCount;
|
||||
|
||||
bool isUsesDataBit();
|
||||
virtual AABB *getAABB(Level *level, int x, int y, int z);
|
||||
virtual bool blocksLight();
|
||||
virtual bool isSolidRender(bool isServerLevel = false);
|
||||
virtual HitResult *clip(Level *level, int xt, int yt, int zt, Vec3 *a, Vec3 *b);
|
||||
virtual void updateShape(LevelSource *level, int x, int y, int z, int forceData = -1, shared_ptr<TileEntity> forceEntity = shared_ptr<TileEntity>()); // 4J added forceData, forceEntity param
|
||||
virtual bool isCubeShaped();
|
||||
virtual int getRenderShape();
|
||||
virtual int getResourceCount(Random random);
|
||||
virtual bool mayPlace(Level *level, int x, int y, int z);
|
||||
virtual void onPlace(Level *level, int x, int y, int z);
|
||||
virtual void neighborChanged(Level *level, int x, int y, int z, int type);
|
||||
|
||||
protected:
|
||||
virtual void updateState(Level *level, int x, int y, int z, int data, int dir, int type);
|
||||
virtual void updateDir(Level *level, int x, int y, int z, bool first);
|
||||
|
||||
public:
|
||||
int getPistonPushReaction();
|
||||
void onRemove(Level *level, int x, int y, int z, int id, int data);
|
||||
};
|
||||
@@ -14,6 +14,8 @@ const float Float::MAX_VALUE = FLT_MAX;
|
||||
|
||||
const double Double::MAX_VALUE = DBL_MAX;
|
||||
|
||||
const double Double::MIN_NORMAL = DBL_MIN;
|
||||
|
||||
int Integer::parseInt(wstring &str, int radix /* = 10*/)
|
||||
{
|
||||
return wcstol( str.c_str(), NULL, radix );
|
||||
|
||||
@@ -47,6 +47,7 @@ class Double
|
||||
{
|
||||
public:
|
||||
static const double MAX_VALUE;
|
||||
static const double MIN_NORMAL;
|
||||
|
||||
static bool isNaN( double a ) {
|
||||
#ifdef __PS3__
|
||||
|
||||
258
Minecraft.World/Bat.cpp
Normal file
258
Minecraft.World/Bat.cpp
Normal file
@@ -0,0 +1,258 @@
|
||||
#include "stdafx.h"
|
||||
#include "net.minecraft.world.entity.h"
|
||||
#include "net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "net.minecraft.world.entity.monster.h"
|
||||
#include "net.minecraft.world.level.h"
|
||||
#include "net.minecraft.world.level.tile.h"
|
||||
#include "net.minecraft.world.phys.h"
|
||||
#include "Bat.h"
|
||||
|
||||
Bat::Bat(Level *level) : AmbientCreature(level)
|
||||
{
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to ensure that
|
||||
// the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
registerAttributes();
|
||||
setHealth(getMaxHealth());
|
||||
|
||||
targetPosition = NULL;
|
||||
|
||||
setSize(.5f, .9f);
|
||||
setResting(true);
|
||||
}
|
||||
|
||||
void Bat::defineSynchedData()
|
||||
{
|
||||
AmbientCreature::defineSynchedData();
|
||||
|
||||
entityData->define(DATA_ID_FLAGS, (char) 0);
|
||||
}
|
||||
|
||||
float Bat::getSoundVolume()
|
||||
{
|
||||
return 0.1f;
|
||||
}
|
||||
|
||||
float Bat::getVoicePitch()
|
||||
{
|
||||
return AmbientCreature::getVoicePitch() * .95f;
|
||||
}
|
||||
|
||||
int Bat::getAmbientSound()
|
||||
{
|
||||
if (isResting() && random->nextInt(4) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return eSoundType_MOB_BAT_IDLE; //"mob.bat.idle";
|
||||
}
|
||||
|
||||
int Bat::getHurtSound()
|
||||
{
|
||||
return eSoundType_MOB_BAT_HURT; //"mob.bat.hurt";
|
||||
}
|
||||
|
||||
int Bat::getDeathSound()
|
||||
{
|
||||
return eSoundType_MOB_BAT_DEATH; //"mob.bat.death";
|
||||
}
|
||||
|
||||
bool Bat::isPushable()
|
||||
{
|
||||
// bats can't be pushed by other mobs
|
||||
return false;
|
||||
}
|
||||
|
||||
void Bat::doPush(shared_ptr<Entity> e)
|
||||
{
|
||||
// bats don't push other mobs
|
||||
}
|
||||
|
||||
void Bat::pushEntities()
|
||||
{
|
||||
// bats don't push other mobs
|
||||
}
|
||||
|
||||
void Bat::registerAttributes()
|
||||
{
|
||||
AmbientCreature::registerAttributes();
|
||||
|
||||
getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(6);
|
||||
}
|
||||
|
||||
bool Bat::isResting()
|
||||
{
|
||||
return (entityData->getByte(DATA_ID_FLAGS) & FLAG_RESTING) != 0;
|
||||
}
|
||||
|
||||
void Bat::setResting(bool value)
|
||||
{
|
||||
char current = entityData->getByte(DATA_ID_FLAGS);
|
||||
if (value)
|
||||
{
|
||||
entityData->set(DATA_ID_FLAGS, (char) (current | FLAG_RESTING));
|
||||
}
|
||||
else
|
||||
{
|
||||
entityData->set(DATA_ID_FLAGS, (char) (current & ~FLAG_RESTING));
|
||||
}
|
||||
}
|
||||
|
||||
bool Bat::useNewAi()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Bat::tick()
|
||||
{
|
||||
|
||||
AmbientCreature::tick();
|
||||
|
||||
if (isResting())
|
||||
{
|
||||
xd = yd = zd = 0;
|
||||
y = Mth::floor(y) + 1.0 - bbHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
yd *= .6f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline int signum(double x) { return (x > 0) - (x < 0); }
|
||||
|
||||
void Bat::newServerAiStep()
|
||||
{
|
||||
AmbientCreature::newServerAiStep();
|
||||
|
||||
if (isResting())
|
||||
{
|
||||
if (!level->isSolidBlockingTile(Mth::floor(x), (int) y + 1, Mth::floor(z)))
|
||||
{
|
||||
setResting(false);
|
||||
level->levelEvent(nullptr, LevelEvent::SOUND_BAT_LIFTOFF, (int) x, (int) y, (int) z, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (random->nextInt(200) == 0)
|
||||
{
|
||||
yHeadRot = random->nextInt(360);
|
||||
}
|
||||
|
||||
if (level->getNearestPlayer(shared_from_this(), 4.0f) != NULL)
|
||||
{
|
||||
setResting(false);
|
||||
level->levelEvent(nullptr, LevelEvent::SOUND_BAT_LIFTOFF, (int) x, (int) y, (int) z, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (targetPosition != NULL && (!level->isEmptyTile(targetPosition->x, targetPosition->y, targetPosition->z) || targetPosition->y < 1))
|
||||
{
|
||||
delete targetPosition;
|
||||
targetPosition = NULL;
|
||||
}
|
||||
if (targetPosition == NULL || random->nextInt(30) == 0 || targetPosition->distSqr((int) x, (int) y, (int) z) < 4)
|
||||
{
|
||||
delete targetPosition;
|
||||
targetPosition = new Pos((int) x + random->nextInt(7) - random->nextInt(7), (int) y + random->nextInt(6) - 2, (int) z + random->nextInt(7) - random->nextInt(7));
|
||||
}
|
||||
|
||||
double dx = (targetPosition->x + .5) - x;
|
||||
double dy = (targetPosition->y + .1) - y;
|
||||
double dz = (targetPosition->z + .5) - z;
|
||||
|
||||
xd = xd + (signum(dx) * .5f - xd) * .1f;
|
||||
yd = yd + (signum(dy) * .7f - yd) * .1f;
|
||||
zd = zd + (signum(dz) * .5f - zd) * .1f;
|
||||
|
||||
float yRotD = (float) (atan2(zd, xd) * 180 / PI) - 90;
|
||||
float rotDiff = Mth::wrapDegrees(yRotD - yRot);
|
||||
yya = .5f;
|
||||
yRot += rotDiff;
|
||||
|
||||
if (random->nextInt(100) == 0 && level->isSolidBlockingTile(Mth::floor(x), (int) y + 1, Mth::floor(z)))
|
||||
{
|
||||
setResting(true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool Bat::makeStepSound()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Bat::causeFallDamage(float distance)
|
||||
{
|
||||
}
|
||||
|
||||
void Bat::checkFallDamage(double ya, bool onGround)
|
||||
{
|
||||
// this method is empty because flying creatures should
|
||||
// not trigger the "fallOn" tile calls (such as trampling crops)
|
||||
}
|
||||
|
||||
bool Bat::isIgnoringTileTriggers()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bat::hurt(DamageSource *source, float dmg)
|
||||
{
|
||||
if (isInvulnerable()) return false;
|
||||
if (!level->isClientSide)
|
||||
{
|
||||
if (isResting())
|
||||
{
|
||||
setResting(false);
|
||||
}
|
||||
}
|
||||
|
||||
return AmbientCreature::hurt(source, dmg);
|
||||
}
|
||||
|
||||
void Bat::readAdditionalSaveData(CompoundTag *tag)
|
||||
{
|
||||
AmbientCreature::readAdditionalSaveData(tag);
|
||||
|
||||
entityData->set(DATA_ID_FLAGS, tag->getByte(L"BatFlags"));
|
||||
}
|
||||
|
||||
void Bat::addAdditonalSaveData(CompoundTag *entityTag)
|
||||
{
|
||||
AmbientCreature::addAdditonalSaveData(entityTag);
|
||||
|
||||
entityTag->putByte(L"BatFlags", entityData->getByte(DATA_ID_FLAGS));
|
||||
}
|
||||
|
||||
|
||||
bool Bat::canSpawn()
|
||||
{
|
||||
int yt = Mth::floor(bb->y0);
|
||||
if (yt >= level->seaLevel) return false;
|
||||
|
||||
int xt = Mth::floor(x);
|
||||
int zt = Mth::floor(z);
|
||||
|
||||
int br = level->getRawBrightness(xt, yt, zt);
|
||||
int maxLight = 4;
|
||||
|
||||
if ((Calendar::GetDayOfMonth() + 1 == 10 && Calendar::GetDayOfMonth() >= 20) || (Calendar::GetMonth() + 1 == 11 && Calendar::GetMonth() <= 3))
|
||||
{
|
||||
maxLight = 7;
|
||||
}
|
||||
else if (random->nextBoolean())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (br > random->nextInt(maxLight)) return false;
|
||||
|
||||
return AmbientCreature::canSpawn();
|
||||
}
|
||||
58
Minecraft.World/Bat.h
Normal file
58
Minecraft.World/Bat.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "AmbientCreature.h"
|
||||
|
||||
class Bat : public AmbientCreature
|
||||
{
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_BAT; }
|
||||
static Entity *create(Level *level) { return new Bat(level); }
|
||||
|
||||
private:
|
||||
static const int DATA_ID_FLAGS = 16;
|
||||
static const int FLAG_RESTING = 1;
|
||||
|
||||
Pos *targetPosition;
|
||||
|
||||
public:
|
||||
Bat(Level *level);
|
||||
|
||||
protected:
|
||||
virtual void defineSynchedData();
|
||||
virtual float getSoundVolume();
|
||||
virtual float getVoicePitch();
|
||||
virtual int getAmbientSound();
|
||||
virtual int getHurtSound();
|
||||
virtual int getDeathSound();
|
||||
|
||||
public:
|
||||
virtual bool isPushable();
|
||||
|
||||
protected:
|
||||
virtual void doPush(shared_ptr<Entity> e);
|
||||
virtual void pushEntities();
|
||||
virtual void registerAttributes();
|
||||
|
||||
public:
|
||||
virtual bool isResting();
|
||||
virtual void setResting(bool value);
|
||||
|
||||
protected:
|
||||
virtual bool useNewAi();
|
||||
|
||||
public:
|
||||
virtual void tick();
|
||||
|
||||
protected:
|
||||
virtual void newServerAiStep();
|
||||
virtual bool makeStepSound();
|
||||
virtual void causeFallDamage(float distance);
|
||||
virtual void checkFallDamage(double ya, bool onGround);
|
||||
virtual bool isIgnoringTileTriggers();
|
||||
|
||||
public:
|
||||
virtual bool hurt(DamageSource *source, float dmg);
|
||||
virtual void readAdditionalSaveData(CompoundTag *tag);
|
||||
virtual void addAdditonalSaveData(CompoundTag *entityTag);
|
||||
virtual bool canSpawn();
|
||||
};
|
||||
@@ -8,8 +8,8 @@ BeachBiome::BeachBiome(int id) : Biome(id)
|
||||
// remove default mob spawn settings
|
||||
friendlies.clear();
|
||||
friendlies_chicken.clear(); // 4J added
|
||||
this->topMaterial = (byte) Tile::sand_Id;
|
||||
this->material = (byte) Tile::sand_Id;
|
||||
topMaterial = (byte) Tile::sand_Id;
|
||||
material = (byte) Tile::sand_Id;
|
||||
|
||||
decorator->treeCount = -999;
|
||||
decorator->deadBushCount = 0;
|
||||
|
||||
140
Minecraft.World/BeaconMenu.cpp
Normal file
140
Minecraft.World/BeaconMenu.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
#include "stdafx.h"
|
||||
#include "net.minecraft.world.item.h"
|
||||
#include "net.minecraft.world.level.tile.entity.h"
|
||||
#include "BeaconMenu.h"
|
||||
|
||||
BeaconMenu::BeaconMenu(shared_ptr<Container> inventory, shared_ptr<BeaconTileEntity> beacon)
|
||||
{
|
||||
this->beacon = beacon;
|
||||
|
||||
addSlot(paymentSlot = new BeaconMenu::PaymentSlot(beacon, PAYMENT_SLOT, 136, 110));
|
||||
|
||||
int xo = 36;
|
||||
int yo = 137;
|
||||
|
||||
for (int y = 0; y < 3; y++)
|
||||
{
|
||||
for (int x = 0; x < 9; x++)
|
||||
{
|
||||
addSlot(new Slot(inventory, x + y * 9 + 9, xo + x * 18, yo + y * 18));
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < 9; x++)
|
||||
{
|
||||
addSlot(new Slot(inventory, x, xo + x * 18, 58 + yo));
|
||||
}
|
||||
|
||||
levels = beacon->getLevels();
|
||||
primaryPower = beacon->getPrimaryPower();
|
||||
secondaryPower = beacon->getSecondaryPower();
|
||||
}
|
||||
|
||||
|
||||
void BeaconMenu::addSlotListener(ContainerListener *listener)
|
||||
{
|
||||
AbstractContainerMenu::addSlotListener(listener);
|
||||
|
||||
listener->setContainerData(this, 0, levels);
|
||||
listener->setContainerData(this, 1, primaryPower);
|
||||
listener->setContainerData(this, 2, secondaryPower);
|
||||
}
|
||||
|
||||
void BeaconMenu::setData(int id, int value)
|
||||
{
|
||||
if (id == 0) beacon->setLevels(value);
|
||||
if (id == 1) beacon->setPrimaryPower(value);
|
||||
if (id == 2) beacon->setSecondaryPower(value);
|
||||
}
|
||||
|
||||
shared_ptr<BeaconTileEntity> BeaconMenu::getBeacon()
|
||||
{
|
||||
return beacon;
|
||||
}
|
||||
|
||||
bool BeaconMenu::stillValid(shared_ptr<Player> player)
|
||||
{
|
||||
return beacon->stillValid(player);
|
||||
}
|
||||
|
||||
shared_ptr<ItemInstance> BeaconMenu::quickMoveStack(shared_ptr<Player> player, int slotIndex)
|
||||
{
|
||||
shared_ptr<ItemInstance> clicked = nullptr;
|
||||
Slot *slot = slots.at(slotIndex);
|
||||
if (slot != NULL && slot->hasItem())
|
||||
{
|
||||
shared_ptr<ItemInstance> stack = slot->getItem();
|
||||
clicked = stack->copy();
|
||||
|
||||
if (slotIndex == PAYMENT_SLOT)
|
||||
{
|
||||
if (!moveItemStackTo(stack, INV_SLOT_START, USE_ROW_SLOT_END, true))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
slot->onQuickCraft(stack, clicked);
|
||||
}
|
||||
else if (!paymentSlot->hasItem() && paymentSlot->mayPlace(stack) && stack->count == 1)
|
||||
{
|
||||
if (!moveItemStackTo(stack, PAYMENT_SLOT, PAYMENT_SLOT + 1, false))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else if (slotIndex >= INV_SLOT_START && slotIndex < INV_SLOT_END)
|
||||
{
|
||||
if (!moveItemStackTo(stack, USE_ROW_SLOT_START, USE_ROW_SLOT_END, false))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else if (slotIndex >= USE_ROW_SLOT_START && slotIndex < USE_ROW_SLOT_END)
|
||||
{
|
||||
if (!moveItemStackTo(stack, INV_SLOT_START, INV_SLOT_END, false))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!moveItemStackTo(stack, INV_SLOT_START, USE_ROW_SLOT_END, false))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (stack->count == 0)
|
||||
{
|
||||
slot->set(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
slot->setChanged();
|
||||
}
|
||||
if (stack->count == clicked->count)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
slot->onTake(player, stack);
|
||||
}
|
||||
}
|
||||
return clicked;
|
||||
}
|
||||
|
||||
BeaconMenu::PaymentSlot::PaymentSlot(shared_ptr<Container> container, int slot, int x, int y) : Slot(container, slot, x, y)
|
||||
{
|
||||
}
|
||||
|
||||
bool BeaconMenu::PaymentSlot::mayPlace(shared_ptr<ItemInstance> item)
|
||||
{
|
||||
if (item != NULL)
|
||||
{
|
||||
return (item->id == Item::emerald_Id || item->id == Item::diamond_Id || item->id == Item::goldIngot_Id || item->id == Item::ironIngot_Id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int BeaconMenu::PaymentSlot::getMaxStackSize() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
44
Minecraft.World/BeaconMenu.h
Normal file
44
Minecraft.World/BeaconMenu.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "AbstractContainerMenu.h"
|
||||
#include "Slot.h"
|
||||
|
||||
class BeaconTileEntity;
|
||||
|
||||
class BeaconMenu : public AbstractContainerMenu
|
||||
{
|
||||
private:
|
||||
class PaymentSlot : public Slot
|
||||
{
|
||||
public:
|
||||
PaymentSlot(shared_ptr<Container> container, int slot, int x, int y);
|
||||
|
||||
bool mayPlace(shared_ptr<ItemInstance> item);
|
||||
int getMaxStackSize() const;
|
||||
};
|
||||
|
||||
public:
|
||||
static const int PAYMENT_SLOT = 0;
|
||||
static const int INV_SLOT_START = PAYMENT_SLOT + 1;
|
||||
static const int INV_SLOT_END = INV_SLOT_START + 9 * 3;
|
||||
static const int USE_ROW_SLOT_START = INV_SLOT_END;
|
||||
static const int USE_ROW_SLOT_END = USE_ROW_SLOT_START + 9;
|
||||
|
||||
private:
|
||||
shared_ptr<BeaconTileEntity> beacon;
|
||||
PaymentSlot *paymentSlot;
|
||||
|
||||
// copied values because container/client system is retarded
|
||||
int levels;
|
||||
int primaryPower;
|
||||
int secondaryPower;
|
||||
|
||||
public:
|
||||
BeaconMenu(shared_ptr<Container> inventory, shared_ptr<BeaconTileEntity> beacon);
|
||||
|
||||
void addSlotListener(ContainerListener *listener);
|
||||
void setData(int id, int value);
|
||||
shared_ptr<BeaconTileEntity> getBeacon();
|
||||
bool stillValid(shared_ptr<Player> player);
|
||||
shared_ptr<ItemInstance> quickMoveStack(shared_ptr<Player> player, int slotIndex);
|
||||
};
|
||||
64
Minecraft.World/BeaconTile.cpp
Normal file
64
Minecraft.World/BeaconTile.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "stdafx.h"
|
||||
#include "net.minecraft.world.entity.player.h"
|
||||
#include "net.minecraft.world.level.h"
|
||||
#include "net.minecraft.world.level.tile.entity.h"
|
||||
#include "BeaconTile.h"
|
||||
|
||||
BeaconTile::BeaconTile(int id) : BaseEntityTile(id, Material::glass, isSolidRender())
|
||||
{
|
||||
setDestroyTime(3.0f);
|
||||
}
|
||||
|
||||
shared_ptr<TileEntity> BeaconTile::newTileEntity(Level *level)
|
||||
{
|
||||
return shared_ptr<BeaconTileEntity>( new BeaconTileEntity() );
|
||||
}
|
||||
|
||||
bool BeaconTile::use(Level *level, int x, int y, int z, shared_ptr<Player> player, int clickedFace, float clickX, float clickY, float clickZ, bool soundOnly)
|
||||
{
|
||||
if (level->isClientSide) return true;
|
||||
|
||||
shared_ptr<BeaconTileEntity> beacon = dynamic_pointer_cast<BeaconTileEntity>( level->getTileEntity(x, y, z) );
|
||||
if (beacon != NULL) player->openBeacon(beacon);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BeaconTile::isSolidRender(bool isServerLevel)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BeaconTile::isCubeShaped()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BeaconTile::blocksLight()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int BeaconTile::getRenderShape()
|
||||
{
|
||||
return SHAPE_BEACON;
|
||||
}
|
||||
|
||||
void BeaconTile::registerIcons(IconRegister *iconRegister)
|
||||
{
|
||||
BaseEntityTile::registerIcons(iconRegister);
|
||||
}
|
||||
|
||||
void BeaconTile::setPlacedBy(Level *level, int x, int y, int z, shared_ptr<LivingEntity> by, shared_ptr<ItemInstance> itemInstance)
|
||||
{
|
||||
BaseEntityTile::setPlacedBy(level, x, y, z, by, itemInstance);
|
||||
if (itemInstance->hasCustomHoverName())
|
||||
{
|
||||
dynamic_pointer_cast<BeaconTileEntity>( level->getTileEntity(x, y, z))->setCustomName(itemInstance->getHoverName());
|
||||
}
|
||||
}
|
||||
|
||||
bool BeaconTile::TestUse()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
19
Minecraft.World/BeaconTile.h
Normal file
19
Minecraft.World/BeaconTile.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "BaseEntityTile.h"
|
||||
|
||||
class BeaconTile : public BaseEntityTile
|
||||
{
|
||||
public:
|
||||
BeaconTile(int id);
|
||||
|
||||
shared_ptr<TileEntity> newTileEntity(Level *level);
|
||||
bool use(Level *level, int x, int y, int z, shared_ptr<Player> player, int clickedFace, float clickX, float clickY, float clickZ, bool soundOnly = false);
|
||||
bool isSolidRender(bool isServerLevel = false);
|
||||
bool isCubeShaped();
|
||||
bool blocksLight();
|
||||
int getRenderShape();
|
||||
void registerIcons(IconRegister *iconRegister);
|
||||
void setPlacedBy(Level *level, int x, int y, int z, shared_ptr<LivingEntity> by, shared_ptr<ItemInstance> itemInstance);
|
||||
virtual bool TestUse();
|
||||
};
|
||||
372
Minecraft.World/BeaconTileEntity.cpp
Normal file
372
Minecraft.World/BeaconTileEntity.cpp
Normal file
@@ -0,0 +1,372 @@
|
||||
#include "stdafx.h"
|
||||
#include "net.minecraft.network.packet.h"
|
||||
#include "net.minecraft.world.effect.h"
|
||||
#include "net.minecraft.world.entity.player.h"
|
||||
#include "net.minecraft.world.item.h"
|
||||
#include "net.minecraft.world.level.h"
|
||||
#include "net.minecraft.world.level.tile.h"
|
||||
#include "net.minecraft.world.phys.h"
|
||||
#include "BeaconTileEntity.h"
|
||||
|
||||
shared_ptr<TileEntity> BeaconTileEntity::clone()
|
||||
{
|
||||
shared_ptr<BeaconTileEntity> result = shared_ptr<BeaconTileEntity>( new BeaconTileEntity() );
|
||||
TileEntity::clone(result);
|
||||
|
||||
result->primaryPower = primaryPower;
|
||||
result->secondaryPower = secondaryPower;
|
||||
result->levels = levels;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MobEffect *BeaconTileEntity::BEACON_EFFECTS[BeaconTileEntity::BEACON_EFFECTS_TIERS][BeaconTileEntity::BEACON_EFFECTS_EFFECTS];
|
||||
|
||||
void BeaconTileEntity::staticCtor()
|
||||
{
|
||||
for(unsigned int tier = 0; tier < BEACON_EFFECTS_TIERS; ++tier)
|
||||
{
|
||||
for(unsigned int effect = 0; effect < BEACON_EFFECTS_EFFECTS; ++effect)
|
||||
{
|
||||
BEACON_EFFECTS[tier][effect] = NULL;
|
||||
}
|
||||
}
|
||||
BEACON_EFFECTS[0][0] = MobEffect::movementSpeed;
|
||||
BEACON_EFFECTS[0][1] = MobEffect::digSpeed;
|
||||
BEACON_EFFECTS[1][0] = MobEffect::damageResistance;
|
||||
BEACON_EFFECTS[1][1] = MobEffect::jump;
|
||||
BEACON_EFFECTS[2][0] = MobEffect::damageBoost;
|
||||
BEACON_EFFECTS[3][0] = MobEffect::regeneration;
|
||||
}
|
||||
|
||||
BeaconTileEntity::BeaconTileEntity()
|
||||
{
|
||||
clientSideRenderTick = 0;
|
||||
clientSideRenderScale = 0.0f;
|
||||
|
||||
isActive = false;
|
||||
levels = -1;
|
||||
|
||||
primaryPower = 0;
|
||||
secondaryPower = 0;
|
||||
|
||||
paymentItem = nullptr;
|
||||
name = L"";
|
||||
}
|
||||
|
||||
void BeaconTileEntity::tick()
|
||||
{
|
||||
// 4J Stu - Added levels check to force an initial tick
|
||||
if ( (!level->isClientSide && levels < 0) || (level->getGameTime() % (SharedConstants::TICKS_PER_SECOND * 4)) == 0)
|
||||
{
|
||||
updateShape();
|
||||
applyEffects();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BeaconTileEntity::applyEffects()
|
||||
{
|
||||
if (isActive && levels > 0 && !level->isClientSide && primaryPower > 0)
|
||||
{
|
||||
|
||||
double range = (levels * 10) + 10;
|
||||
int baseAmp = 0;
|
||||
if (levels >= 4 && primaryPower == secondaryPower)
|
||||
{
|
||||
baseAmp = 1;
|
||||
}
|
||||
|
||||
AABB *bb = AABB::newTemp(x, y, z, x + 1, y + 1, z + 1)->grow(range, range, range);
|
||||
bb->y1 = level->getMaxBuildHeight();
|
||||
vector<shared_ptr<Entity> > *players = level->getEntitiesOfClass(typeid(Player), bb);
|
||||
for (AUTO_VAR(it,players->begin()); it != players->end(); ++it)
|
||||
{
|
||||
shared_ptr<Player> player = dynamic_pointer_cast<Player>(*it);
|
||||
player->addEffect(new MobEffectInstance(primaryPower, SharedConstants::TICKS_PER_SECOND * 9, baseAmp, true));
|
||||
}
|
||||
|
||||
if (levels >= 4 && primaryPower != secondaryPower && secondaryPower > 0)
|
||||
{
|
||||
for (AUTO_VAR(it,players->begin()); it != players->end(); ++it)
|
||||
{
|
||||
shared_ptr<Player> player = dynamic_pointer_cast<Player>(*it);
|
||||
player->addEffect(new MobEffectInstance(secondaryPower, SharedConstants::TICKS_PER_SECOND * 9, 0, true));
|
||||
}
|
||||
}
|
||||
delete players;
|
||||
}
|
||||
}
|
||||
|
||||
void BeaconTileEntity::updateShape()
|
||||
{
|
||||
|
||||
if (!level->canSeeSky(x, y + 1, z))
|
||||
{
|
||||
isActive = false;
|
||||
levels = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
isActive = true;
|
||||
|
||||
levels = 0;
|
||||
for (int step = 1; step <= 4; step++)
|
||||
{
|
||||
|
||||
int ly = y - step;
|
||||
if (ly < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
bool isOk = true;
|
||||
for (int lx = x - step; lx <= x + step && isOk; lx++)
|
||||
{
|
||||
for (int lz = z - step; lz <= z + step; lz++)
|
||||
{
|
||||
int tile = level->getTile(lx, ly, lz);
|
||||
if (tile != Tile::emeraldBlock_Id && tile != Tile::goldBlock_Id && tile != Tile::diamondBlock_Id && tile != Tile::ironBlock_Id)
|
||||
{
|
||||
isOk = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isOk)
|
||||
{
|
||||
levels = step;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (levels == 0)
|
||||
{
|
||||
isActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
float BeaconTileEntity::getAndUpdateClientSideScale()
|
||||
{
|
||||
|
||||
if (!isActive)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int renderDelta = (int) (level->getGameTime() - clientSideRenderTick);
|
||||
clientSideRenderTick = level->getGameTime();
|
||||
if (renderDelta > 1)
|
||||
{
|
||||
clientSideRenderScale -= ((float) renderDelta / (float) SCALE_TIME);
|
||||
|
||||
if (clientSideRenderScale < 0)
|
||||
{
|
||||
clientSideRenderScale = 0;
|
||||
}
|
||||
}
|
||||
clientSideRenderScale += (1.0f / (float) SCALE_TIME);
|
||||
if (clientSideRenderScale > 1)
|
||||
{
|
||||
clientSideRenderScale = 1;
|
||||
}
|
||||
return clientSideRenderScale;
|
||||
}
|
||||
|
||||
int BeaconTileEntity::getPrimaryPower()
|
||||
{
|
||||
return primaryPower;
|
||||
}
|
||||
|
||||
int BeaconTileEntity::getSecondaryPower()
|
||||
{
|
||||
return secondaryPower;
|
||||
}
|
||||
|
||||
int BeaconTileEntity::getLevels()
|
||||
{
|
||||
return levels;
|
||||
}
|
||||
|
||||
// client-side method used by GUI
|
||||
void BeaconTileEntity::setLevels(int levels)
|
||||
{
|
||||
this->levels = levels;
|
||||
}
|
||||
|
||||
void BeaconTileEntity::setPrimaryPower(int primaryPower)
|
||||
{
|
||||
this->primaryPower = 0;
|
||||
|
||||
// verify power
|
||||
for (int tier = 0; tier < levels && tier < 3; tier++)
|
||||
{
|
||||
for(unsigned int e = 0; e < BEACON_EFFECTS_EFFECTS; ++e)
|
||||
{
|
||||
MobEffect *effect = BEACON_EFFECTS[tier][e];
|
||||
if(effect == NULL) break;
|
||||
|
||||
if (effect->id == primaryPower)
|
||||
{
|
||||
this->primaryPower = primaryPower;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BeaconTileEntity::setSecondaryPower(int secondaryPower)
|
||||
{
|
||||
this->secondaryPower = 0;
|
||||
|
||||
// verify power
|
||||
if (levels >= 4)
|
||||
{
|
||||
for (int tier = 0; tier < 4; tier++)
|
||||
{
|
||||
for(unsigned int e = 0; e < BEACON_EFFECTS_EFFECTS; ++e)
|
||||
{
|
||||
MobEffect *effect = BEACON_EFFECTS[tier][e];
|
||||
if(effect == NULL) break;
|
||||
|
||||
if (effect->id == secondaryPower)
|
||||
{
|
||||
this->secondaryPower = secondaryPower;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<Packet> BeaconTileEntity::getUpdatePacket()
|
||||
{
|
||||
CompoundTag *tag = new CompoundTag();
|
||||
save(tag);
|
||||
return shared_ptr<TileEntityDataPacket>( new TileEntityDataPacket(x, y, z, TileEntityDataPacket::TYPE_BEACON, tag) );
|
||||
}
|
||||
|
||||
double BeaconTileEntity::getViewDistance()
|
||||
{
|
||||
return 256 * 256;
|
||||
}
|
||||
|
||||
void BeaconTileEntity::load(CompoundTag *tag)
|
||||
{
|
||||
TileEntity::load(tag);
|
||||
|
||||
primaryPower = tag->getInt(L"Primary");
|
||||
secondaryPower = tag->getInt(L"Secondary");
|
||||
levels = tag->getInt(L"Levels");
|
||||
}
|
||||
|
||||
void BeaconTileEntity::save(CompoundTag *tag)
|
||||
{
|
||||
TileEntity::save(tag);
|
||||
|
||||
tag->putInt(L"Primary", primaryPower);
|
||||
tag->putInt(L"Secondary", secondaryPower);
|
||||
// this value is re-calculated, but save it anyway to avoid update lag
|
||||
tag->putInt(L"Levels", levels);
|
||||
}
|
||||
|
||||
unsigned int BeaconTileEntity::getContainerSize()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
shared_ptr<ItemInstance> BeaconTileEntity::getItem(unsigned int slot)
|
||||
{
|
||||
if (slot == 0)
|
||||
{
|
||||
return paymentItem;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<ItemInstance> BeaconTileEntity::removeItem(unsigned int slot, int count)
|
||||
{
|
||||
if (slot == 0 && paymentItem != NULL)
|
||||
{
|
||||
if (count >= paymentItem->count)
|
||||
{
|
||||
shared_ptr<ItemInstance> returnItem = paymentItem;
|
||||
paymentItem = nullptr;
|
||||
return returnItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
paymentItem->count -= count;
|
||||
return shared_ptr<ItemInstance>( new ItemInstance(paymentItem->id, count, paymentItem->getAuxValue()) );
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<ItemInstance> BeaconTileEntity::removeItemNoUpdate(int slot)
|
||||
{
|
||||
if (slot == 0 && paymentItem != NULL)
|
||||
{
|
||||
shared_ptr<ItemInstance> returnItem = paymentItem;
|
||||
paymentItem = nullptr;
|
||||
return returnItem;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void BeaconTileEntity::setItem(unsigned int slot, shared_ptr<ItemInstance> item)
|
||||
{
|
||||
if (slot == 0)
|
||||
{
|
||||
paymentItem = item;
|
||||
}
|
||||
}
|
||||
|
||||
wstring BeaconTileEntity::getName()
|
||||
{
|
||||
return hasCustomName() ? name : app.GetString(IDS_CONTAINER_BEACON);
|
||||
}
|
||||
|
||||
wstring BeaconTileEntity::getCustomName()
|
||||
{
|
||||
return hasCustomName() ? name : L"";
|
||||
}
|
||||
|
||||
bool BeaconTileEntity::hasCustomName()
|
||||
{
|
||||
return !name.empty();
|
||||
}
|
||||
|
||||
void BeaconTileEntity::setCustomName(const wstring &name)
|
||||
{
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
int BeaconTileEntity::getMaxStackSize() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool BeaconTileEntity::stillValid(shared_ptr<Player> player)
|
||||
{
|
||||
if (level->getTileEntity(x, y, z) != shared_from_this()) return false;
|
||||
if (player->distanceToSqr(x + 0.5, y + 0.5, z + 0.5) > 8 * 8) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void BeaconTileEntity::startOpen()
|
||||
{
|
||||
}
|
||||
|
||||
void BeaconTileEntity::stopOpen()
|
||||
{
|
||||
}
|
||||
|
||||
bool BeaconTileEntity::canPlaceItem(int slot, shared_ptr<ItemInstance> item)
|
||||
{
|
||||
return (item->id == Item::emerald_Id || item->id == Item::diamond_Id || item->id == Item::goldIngot_Id || item->id == Item::ironIngot_Id);
|
||||
}
|
||||
75
Minecraft.World/BeaconTileEntity.h
Normal file
75
Minecraft.World/BeaconTileEntity.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
#include "TileEntity.h"
|
||||
#include "Container.h"
|
||||
|
||||
class BeaconTileEntity : public TileEntity, public Container
|
||||
{
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_BEACONTILEENTITY; }
|
||||
static TileEntity *create() { return new BeaconTileEntity(); }
|
||||
// 4J Added
|
||||
virtual shared_ptr<TileEntity> clone();
|
||||
|
||||
private:
|
||||
static const int SCALE_TIME = SharedConstants::TICKS_PER_SECOND * 2;
|
||||
|
||||
public:
|
||||
static const int BEACON_EFFECTS_TIERS = 4;
|
||||
static const int BEACON_EFFECTS_EFFECTS = 3;
|
||||
static MobEffect *BEACON_EFFECTS[BEACON_EFFECTS_TIERS][BEACON_EFFECTS_EFFECTS];
|
||||
|
||||
static void staticCtor();
|
||||
|
||||
private:
|
||||
__int64 clientSideRenderTick;
|
||||
float clientSideRenderScale;
|
||||
|
||||
bool isActive;
|
||||
int levels;
|
||||
|
||||
int primaryPower;
|
||||
int secondaryPower;
|
||||
|
||||
shared_ptr<ItemInstance> paymentItem;
|
||||
wstring name;
|
||||
|
||||
public:
|
||||
BeaconTileEntity();
|
||||
|
||||
void tick();
|
||||
|
||||
private:
|
||||
void applyEffects();
|
||||
void updateShape();
|
||||
|
||||
public:
|
||||
float getAndUpdateClientSideScale();
|
||||
int getPrimaryPower();
|
||||
int getSecondaryPower();
|
||||
int getLevels();
|
||||
// client-side method used by GUI
|
||||
void setLevels(int levels);
|
||||
void setPrimaryPower(int primaryPower);
|
||||
void setSecondaryPower(int secondaryPower);
|
||||
shared_ptr<Packet> getUpdatePacket();
|
||||
double getViewDistance();
|
||||
void load(CompoundTag *tag);
|
||||
void save(CompoundTag *tag);
|
||||
unsigned int getContainerSize();
|
||||
shared_ptr<ItemInstance> getItem(unsigned int slot);
|
||||
shared_ptr<ItemInstance> removeItem(unsigned int slot, int count);
|
||||
shared_ptr<ItemInstance> removeItemNoUpdate(int slot);
|
||||
void setItem(unsigned int slot, shared_ptr<ItemInstance> item);
|
||||
wstring getName();
|
||||
wstring getCustomName();
|
||||
bool hasCustomName();
|
||||
void setCustomName(const wstring &name);
|
||||
int getMaxStackSize() const;
|
||||
bool stillValid(shared_ptr<Player> player);
|
||||
void startOpen();
|
||||
void stopOpen();
|
||||
bool canPlaceItem(int slot, shared_ptr<ItemInstance> item);
|
||||
|
||||
// 4J Stu - For container
|
||||
virtual void setChanged() { TileEntity::setChanged(); }
|
||||
};
|
||||
@@ -14,6 +14,8 @@ BedItem::BedItem(int id) : Item( id )
|
||||
|
||||
bool BedItem::useOn(shared_ptr<ItemInstance> itemInstance, shared_ptr<Player> player, Level *level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, bool bTestUseOnOnly)
|
||||
{
|
||||
if (level->isClientSide) return true;
|
||||
|
||||
if (face != Facing::UP)
|
||||
{
|
||||
return false;
|
||||
@@ -33,21 +35,21 @@ bool BedItem::useOn(shared_ptr<ItemInstance> itemInstance, shared_ptr<Player> pl
|
||||
if (dir == Direction::NORTH) zra = -1;
|
||||
if (dir == Direction::EAST) xra = 1;
|
||||
|
||||
if (!player->mayBuild(x, y, z) || !player->mayBuild(x + xra, y, z + zra)) return false;
|
||||
if (!player->mayUseItemAt(x, y, z, face, itemInstance) || !player->mayUseItemAt(x + xra, y, z + zra, face, itemInstance)) return false;
|
||||
|
||||
if (level->isEmptyTile(x, y, z) && level->isEmptyTile(x + xra, y, z + zra) && level->isTopSolidBlocking(x, y - 1, z) && level->isTopSolidBlocking(x + xra, y - 1, z + zra))
|
||||
{
|
||||
// 4J-PB - Adding a test only version to allow tooltips to be displayed
|
||||
if(!bTestUseOnOnly)
|
||||
{
|
||||
level->setTileAndData(x, y, z, tile->id, dir);
|
||||
level->setTileAndData(x, y, z, tile->id, dir, Tile::UPDATE_ALL);
|
||||
// double-check that the bed was successfully placed
|
||||
if (level->getTile(x, y, z) == tile->id)
|
||||
{
|
||||
// 4J-JEV: Hook for durango 'BlockPlaced' event.
|
||||
player->awardStat(GenericStats::blocksPlaced(tile->id), GenericStats::param_blocksPlaced(tile->id,itemInstance->getAuxValue(),1));
|
||||
|
||||
level->setTileAndData(x + xra, y, z + zra, tile->id, dir + BedTile::HEAD_PIECE_DATA);
|
||||
level->setTileAndData(x + xra, y, z + zra, tile->id, dir + BedTile::HEAD_PIECE_DATA, Tile::UPDATE_ALL);
|
||||
}
|
||||
|
||||
itemInstance->count--;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
int BedTile::HEAD_DIRECTION_OFFSETS[4][2] =
|
||||
{
|
||||
{ 0, 1 }, { -1, 0 }, { 0, -1 }, { 1, 0 }
|
||||
{ 0, 1 }, { -1, 0 }, { 0, -1 }, { 1, 0 }
|
||||
};
|
||||
|
||||
BedTile::BedTile(int id) : DirectionalTile(id, Material::cloth, isSolidRender())
|
||||
@@ -24,7 +24,7 @@ BedTile::BedTile(int id) : DirectionalTile(id, Material::cloth, isSolidRender())
|
||||
// 4J Added override
|
||||
void BedTile::updateDefaultShape()
|
||||
{
|
||||
setShape();
|
||||
setShape();
|
||||
}
|
||||
|
||||
// 4J-PB - Adding a TestUse for tooltip display
|
||||
@@ -68,75 +68,76 @@ bool BedTile::TestUse(Level *level, int x, int y, int z, shared_ptr<Player> play
|
||||
bool BedTile::use(Level *level, int x, int y, int z, shared_ptr<Player> player, int clickedFace, float clickX, float clickY, float clickZ, bool soundOnly/*=false*/) // 4J added soundOnly param
|
||||
{
|
||||
if( soundOnly) return false;
|
||||
if (level->isClientSide) return true;
|
||||
if (level->isClientSide) return true;
|
||||
|
||||
int data = level->getData(x, y, z);
|
||||
int data = level->getData(x, y, z);
|
||||
|
||||
if (!BedTile::isHeadPiece(data))
|
||||
if (!isHeadPiece(data))
|
||||
{
|
||||
// fetch head piece instead
|
||||
int direction = getDirection(data);
|
||||
x += HEAD_DIRECTION_OFFSETS[direction][0];
|
||||
z += HEAD_DIRECTION_OFFSETS[direction][1];
|
||||
if (level->getTile(x, y, z) != id)
|
||||
// fetch head piece instead
|
||||
int direction = getDirection(data);
|
||||
x += HEAD_DIRECTION_OFFSETS[direction][0];
|
||||
z += HEAD_DIRECTION_OFFSETS[direction][1];
|
||||
if (level->getTile(x, y, z) != id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
data = level->getData(x, y, z);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
data = level->getData(x, y, z);
|
||||
}
|
||||
|
||||
if (!level->dimension->mayRespawn())
|
||||
if (!level->dimension->mayRespawn() || level->getBiome(x, z) == Biome::hell)
|
||||
{
|
||||
double xc = x + 0.5;
|
||||
double yc = y + 0.5;
|
||||
double zc = z + 0.5;
|
||||
level->setTile(x, y, z, 0);
|
||||
int direction = getDirection(data);
|
||||
x += HEAD_DIRECTION_OFFSETS[direction][0];
|
||||
z += HEAD_DIRECTION_OFFSETS[direction][1];
|
||||
if (level->getTile(x, y, z) == id) {
|
||||
level->setTile(x, y, z, 0);
|
||||
xc = (xc + x + 0.5) / 2;
|
||||
yc = (yc + y + 0.5) / 2;
|
||||
zc = (zc + z + 0.5) / 2;
|
||||
}
|
||||
level->explode(nullptr, x + 0.5f, y + 0.5f, z + 0.5f, 5, true, true);
|
||||
return true;
|
||||
}
|
||||
double xc = x + 0.5;
|
||||
double yc = y + 0.5;
|
||||
double zc = z + 0.5;
|
||||
level->removeTile(x, y, z);
|
||||
int direction = getDirection(data);
|
||||
x += HEAD_DIRECTION_OFFSETS[direction][0];
|
||||
z += HEAD_DIRECTION_OFFSETS[direction][1];
|
||||
if (level->getTile(x, y, z) == id)
|
||||
{
|
||||
level->removeTile(x, y, z);
|
||||
xc = (xc + x + 0.5) / 2;
|
||||
yc = (yc + y + 0.5) / 2;
|
||||
zc = (zc + z + 0.5) / 2;
|
||||
}
|
||||
level->explode(nullptr, x + 0.5f, y + 0.5f, z + 0.5f, 5, true, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (BedTile::isOccupied(data))
|
||||
if (isOccupied(data))
|
||||
{
|
||||
shared_ptr<Player> sleepingPlayer = nullptr;
|
||||
shared_ptr<Player> sleepingPlayer = nullptr;
|
||||
AUTO_VAR(itEnd, level->players.end());
|
||||
for (AUTO_VAR(it, level->players.begin()); it != itEnd; it++ )
|
||||
for (AUTO_VAR(it, level->players.begin()); it != itEnd; it++ )
|
||||
{
|
||||
shared_ptr<Player> p = *it;
|
||||
if (p->isSleeping())
|
||||
if (p->isSleeping())
|
||||
{
|
||||
Pos pos = p->bedPosition;
|
||||
if (pos.x == x && pos.y == y && pos.z == z)
|
||||
Pos pos = p->bedPosition;
|
||||
if (pos.x == x && pos.y == y && pos.z == z)
|
||||
{
|
||||
sleepingPlayer = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
sleepingPlayer = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sleepingPlayer == NULL)
|
||||
if (sleepingPlayer == NULL)
|
||||
{
|
||||
BedTile::setOccupied(level, x, y, z, false);
|
||||
}
|
||||
setOccupied(level, x, y, z, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
player->displayClientMessage(IDS_TILE_BED_OCCUPIED );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Player::BedSleepingResult result = player->startSleepInBed(x, y, z);
|
||||
if (result == Player::OK)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Player::BedSleepingResult result = player->startSleepInBed(x, y, z);
|
||||
if (result == Player::OK)
|
||||
{
|
||||
BedTile::setOccupied(level, x, y, z, true);
|
||||
setOccupied(level, x, y, z, true);
|
||||
// 4J-PB added
|
||||
// are there multiple players in the same world as us?
|
||||
if(level->AllPlayersAreSleeping()==false)
|
||||
@@ -144,18 +145,18 @@ bool BedTile::use(Level *level, int x, int y, int z, shared_ptr<Player> player,
|
||||
player->displayClientMessage(IDS_TILE_BED_PLAYERSLEEP);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == Player::NOT_POSSIBLE_NOW)
|
||||
if (result == Player::NOT_POSSIBLE_NOW)
|
||||
{
|
||||
player->displayClientMessage(IDS_TILE_BED_NO_SLEEP);
|
||||
}
|
||||
}
|
||||
else if (result == Player::NOT_SAFE)
|
||||
{
|
||||
player->displayClientMessage(IDS_TILE_BED_NOTSAFE);
|
||||
}
|
||||
player->displayClientMessage(IDS_TILE_BED_NOTSAFE);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
Icon *BedTile::getTexture(int face, int data)
|
||||
@@ -218,35 +219,35 @@ void BedTile::updateShape(LevelSource *level, int x, int y, int z, int forceData
|
||||
|
||||
void BedTile::neighborChanged(Level *level, int x, int y, int z, int type)
|
||||
{
|
||||
int data = level->getData(x, y, z);
|
||||
int direction = getDirection(data);
|
||||
int data = level->getData(x, y, z);
|
||||
int direction = getDirection(data);
|
||||
|
||||
if (isHeadPiece(data))
|
||||
if (isHeadPiece(data))
|
||||
{
|
||||
if (level->getTile(x - HEAD_DIRECTION_OFFSETS[direction][0], y, z - HEAD_DIRECTION_OFFSETS[direction][1]) != id)
|
||||
if (level->getTile(x - HEAD_DIRECTION_OFFSETS[direction][0], y, z - HEAD_DIRECTION_OFFSETS[direction][1]) != id)
|
||||
{
|
||||
level->setTile(x, y, z, 0);
|
||||
}
|
||||
} else
|
||||
level->removeTile(x, y, z);
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (level->getTile(x + HEAD_DIRECTION_OFFSETS[direction][0], y, z + HEAD_DIRECTION_OFFSETS[direction][1]) != id)
|
||||
if (level->getTile(x + HEAD_DIRECTION_OFFSETS[direction][0], y, z + HEAD_DIRECTION_OFFSETS[direction][1]) != id)
|
||||
{
|
||||
level->setTile(x, y, z, 0);
|
||||
if (!level->isClientSide)
|
||||
level->removeTile(x, y, z);
|
||||
if (!level->isClientSide)
|
||||
{
|
||||
Tile::spawnResources(level, x, y, z, data, 0); // 4J - had to add Tile:: here for C++ since this class doesn't have this overloaded method itself
|
||||
}
|
||||
}
|
||||
}
|
||||
Tile::spawnResources(level, x, y, z, data, 0); // 4J - had to add Tile:: here for C++ since this class doesn't have this overloaded method itself
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int BedTile::getResource(int data, Random *random, int playerBonusLevel)
|
||||
{
|
||||
if (isHeadPiece(data))
|
||||
if (isHeadPiece(data))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return Item::bed->id;
|
||||
return 0;
|
||||
}
|
||||
return Item::bed->id;
|
||||
}
|
||||
|
||||
void BedTile::setShape()
|
||||
@@ -266,59 +267,59 @@ bool BedTile::isOccupied(int data)
|
||||
|
||||
void BedTile::setOccupied(Level *level, int x, int y, int z, bool occupied)
|
||||
{
|
||||
int data = level->getData(x, y, z);
|
||||
if (occupied)
|
||||
int data = level->getData(x, y, z);
|
||||
if (occupied)
|
||||
{
|
||||
data = data | OCCUPIED_DATA;
|
||||
} else
|
||||
data = data | OCCUPIED_DATA;
|
||||
} else
|
||||
{
|
||||
data = data & ~OCCUPIED_DATA;
|
||||
}
|
||||
level->setData(x, y, z, data);
|
||||
data = data & ~OCCUPIED_DATA;
|
||||
}
|
||||
level->setData(x, y, z, data, Tile::UPDATE_NONE);
|
||||
}
|
||||
|
||||
Pos *BedTile::findStandUpPosition(Level *level, int x, int y, int z, int skipCount)
|
||||
{
|
||||
int data = level->getData(x, y, z);
|
||||
int direction = DirectionalTile::getDirection(data);
|
||||
int data = level->getData(x, y, z);
|
||||
int direction = DirectionalTile::getDirection(data);
|
||||
|
||||
// try to find a clear location near the bed
|
||||
for (int step = 0; step <= 1; step++)
|
||||
// try to find a clear location near the bed
|
||||
for (int step = 0; step <= 1; step++)
|
||||
{
|
||||
int startX = x - BedTile::HEAD_DIRECTION_OFFSETS[direction][0] * step - 1;
|
||||
int startZ = z - BedTile::HEAD_DIRECTION_OFFSETS[direction][1] * step - 1;
|
||||
int endX = startX + 2;
|
||||
int endZ = startZ + 2;
|
||||
int startX = x - HEAD_DIRECTION_OFFSETS[direction][0] * step - 1;
|
||||
int startZ = z - HEAD_DIRECTION_OFFSETS[direction][1] * step - 1;
|
||||
int endX = startX + 2;
|
||||
int endZ = startZ + 2;
|
||||
|
||||
for (int standX = startX; standX <= endX; standX++)
|
||||
for (int standX = startX; standX <= endX; standX++)
|
||||
{
|
||||
for (int standZ = startZ; standZ <= endZ; standZ++)
|
||||
for (int standZ = startZ; standZ <= endZ; standZ++)
|
||||
{
|
||||
// 4J Stu - Changed to check isSolidBlockingTile rather than isEmpty for the blocks that we wish to place the player
|
||||
// This allows the player to spawn in blocks with snow, grass etc
|
||||
if (level->isTopSolidBlocking(standX, y - 1, standZ) &&
|
||||
!level->isSolidBlockingTile(standX, y, standZ) &&
|
||||
!level->isSolidBlockingTile(standX, y + 1, standZ))
|
||||
if (level->isTopSolidBlocking(standX, y - 1, standZ) &&
|
||||
!level->getMaterial(standX, y, standZ)->isSolidBlocking() &&
|
||||
!level->getMaterial(standX, y + 1, standZ)->isSolidBlocking() )
|
||||
{
|
||||
if (skipCount > 0) {
|
||||
skipCount--;
|
||||
continue;
|
||||
}
|
||||
return new Pos(standX, y, standZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (skipCount > 0) {
|
||||
skipCount--;
|
||||
continue;
|
||||
}
|
||||
return new Pos(standX, y, standZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void BedTile::spawnResources(Level *level, int x, int y, int z, int data, float odds, int playerBonus)
|
||||
{
|
||||
if (!isHeadPiece(data))
|
||||
if (!isHeadPiece(data))
|
||||
{
|
||||
Tile::spawnResources(level, x, y, z, data, odds, 0);
|
||||
}
|
||||
Tile::spawnResources(level, x, y, z, data, odds, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int BedTile::getPistonPushReaction()
|
||||
@@ -329,4 +330,21 @@ int BedTile::getPistonPushReaction()
|
||||
int BedTile::cloneTileId(Level *level, int x, int y, int z)
|
||||
{
|
||||
return Item::bed_Id;
|
||||
}
|
||||
|
||||
void BedTile::playerWillDestroy(Level *level, int x, int y, int z, int data, shared_ptr<Player> player)
|
||||
{
|
||||
if (player->abilities.instabuild)
|
||||
{
|
||||
if (isHeadPiece(data))
|
||||
{
|
||||
int direction = getDirection(data);
|
||||
x -= HEAD_DIRECTION_OFFSETS[direction][0];
|
||||
z -= HEAD_DIRECTION_OFFSETS[direction][1];
|
||||
if (level->getTile(x, y, z) == id)
|
||||
{
|
||||
level->removeTile(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,37 +17,38 @@ private:
|
||||
Icon **iconTop;
|
||||
|
||||
public:
|
||||
static const int HEAD_PIECE_DATA = 0x8;
|
||||
static const int OCCUPIED_DATA = 0x4;
|
||||
static const int HEAD_PIECE_DATA = 0x8;
|
||||
static const int OCCUPIED_DATA = 0x4;
|
||||
|
||||
static int HEAD_DIRECTION_OFFSETS[4][2];
|
||||
static int HEAD_DIRECTION_OFFSETS[4][2];
|
||||
|
||||
BedTile(int id);
|
||||
|
||||
BedTile(int id);
|
||||
|
||||
virtual void updateDefaultShape();
|
||||
virtual bool TestUse(Level *level, int x, int y, int z, shared_ptr<Player> player);
|
||||
virtual bool use(Level *level, int x, int y, int z, shared_ptr<Player> player, int clickedFace, float clickX, float clickY, float clickZ, bool soundOnly = false); // 4J added soundOnly param
|
||||
virtual Icon *getTexture(int face, int data);
|
||||
virtual bool use(Level *level, int x, int y, int z, shared_ptr<Player> player, int clickedFace, float clickX, float clickY, float clickZ, bool soundOnly = false); // 4J added soundOnly param
|
||||
virtual Icon *getTexture(int face, int data);
|
||||
//@Override
|
||||
void registerIcons(IconRegister *iconRegister);
|
||||
virtual int getRenderShape();
|
||||
virtual int getRenderShape();
|
||||
virtual bool isCubeShaped();
|
||||
virtual bool isSolidRender(bool isServerLevel = false);
|
||||
virtual void updateShape(LevelSource *level, int x, int y, int z, int forceData = -1, shared_ptr<TileEntity> forceEntity = shared_ptr<TileEntity>()); // 4J added forceData, forceEntity param
|
||||
virtual void updateShape(LevelSource *level, int x, int y, int z, int forceData = -1, shared_ptr<TileEntity> forceEntity = shared_ptr<TileEntity>()); // 4J added forceData, forceEntity param
|
||||
virtual void neighborChanged(Level *level, int x, int y, int z, int type);
|
||||
virtual int getResource(int data, Random *random,int playerBonusLevel);
|
||||
virtual int getResource(int data, Random *random,int playerBonusLevel);
|
||||
|
||||
private:
|
||||
using Tile::setShape;
|
||||
void setShape();
|
||||
void setShape();
|
||||
|
||||
public:
|
||||
static bool isHeadPiece(int data);
|
||||
static bool isOccupied(int data);
|
||||
static bool isHeadPiece(int data);
|
||||
static bool isOccupied(int data);
|
||||
static void setOccupied(Level *level, int x, int y, int z, bool occupied);
|
||||
static Pos *findStandUpPosition(Level *level, int x, int y, int z, int skipCount);
|
||||
static Pos *findStandUpPosition(Level *level, int x, int y, int z, int skipCount);
|
||||
|
||||
virtual void spawnResources(Level *level, int x, int y, int z, int data, float odds, int playerBonus);
|
||||
virtual int getPistonPushReaction();
|
||||
virtual void spawnResources(Level *level, int x, int y, int z, int data, float odds, int playerBonus);
|
||||
virtual int getPistonPushReaction();
|
||||
virtual int cloneTileId(Level *level, int x, int y, int z);
|
||||
virtual void playerWillDestroy(Level *level, int x, int y, int z, int data, shared_ptr<Player> player);
|
||||
};
|
||||
|
||||
5
Minecraft.World/Behavior.h
Normal file
5
Minecraft.World/Behavior.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
class Behavior
|
||||
{
|
||||
};
|
||||
30
Minecraft.World/BehaviorRegistry.cpp
Normal file
30
Minecraft.World/BehaviorRegistry.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "BehaviorRegistry.h"
|
||||
|
||||
BehaviorRegistry::BehaviorRegistry(DispenseItemBehavior *defaultValue)
|
||||
{
|
||||
defaultBehavior = defaultValue;
|
||||
}
|
||||
|
||||
BehaviorRegistry::~BehaviorRegistry()
|
||||
{
|
||||
for(AUTO_VAR(it, storage.begin()); it != storage.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
delete defaultBehavior;
|
||||
}
|
||||
|
||||
DispenseItemBehavior *BehaviorRegistry::get(Item *key)
|
||||
{
|
||||
AUTO_VAR(it, storage.find(key));
|
||||
|
||||
return (it == storage.end()) ? defaultBehavior : it->second;
|
||||
}
|
||||
|
||||
void BehaviorRegistry::add(Item *key, DispenseItemBehavior *value)
|
||||
{
|
||||
storage.insert(make_pair(key, value));
|
||||
}
|
||||
17
Minecraft.World/BehaviorRegistry.h
Normal file
17
Minecraft.World/BehaviorRegistry.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
class DispenseItemBehavior;
|
||||
|
||||
class BehaviorRegistry
|
||||
{
|
||||
private:
|
||||
unordered_map<Item*, DispenseItemBehavior*> storage;
|
||||
DispenseItemBehavior *defaultBehavior;
|
||||
|
||||
public:
|
||||
BehaviorRegistry(DispenseItemBehavior *defaultValue);
|
||||
~BehaviorRegistry();
|
||||
|
||||
DispenseItemBehavior *get(Item *key);
|
||||
void add(Item *key, DispenseItemBehavior *value);
|
||||
};
|
||||
@@ -61,30 +61,30 @@ void Biome::staticCtor()
|
||||
|
||||
Biome::hell = (new HellBiome(8))->setColor(0xff0000)->setName(L"Hell")->setNoRain()->setTemperatureAndDownfall(2, 0)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Hell, eMinecraftColour_Foliage_Hell, eMinecraftColour_Water_Hell,eMinecraftColour_Sky_Hell);
|
||||
Biome::sky = (new TheEndBiome(9))->setColor(0x8080ff)->setName(L"Sky")->setNoRain()->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Sky, eMinecraftColour_Foliage_Sky, eMinecraftColour_Water_Sky,eMinecraftColour_Sky_Sky);
|
||||
|
||||
|
||||
Biome::frozenOcean = (new OceanBiome(10))->setColor(0x9090a0)->setName(L"FrozenOcean")->setSnowCovered()->setDepthAndScale(-1, 0.5f)->setTemperatureAndDownfall(0, 0.5f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_FrozenOcean, eMinecraftColour_Foliage_FrozenOcean, eMinecraftColour_Water_FrozenOcean,eMinecraftColour_Sky_FrozenOcean);
|
||||
Biome::frozenRiver = (new RiverBiome(11))->setColor(0xa0a0ff)->setName(L"FrozenRiver")->setSnowCovered()->setDepthAndScale(-0.5f, 0)->setTemperatureAndDownfall(0, 0.5f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_FrozenRiver, eMinecraftColour_Foliage_FrozenRiver, eMinecraftColour_Water_FrozenRiver,eMinecraftColour_Sky_FrozenRiver);
|
||||
Biome::iceFlats = (new IceBiome(12))->setColor(0xffffff)->setName(L"Ice Plains")->setSnowCovered()->setTemperatureAndDownfall(0, 0.5f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_IcePlains, eMinecraftColour_Foliage_IcePlains, eMinecraftColour_Water_IcePlains,eMinecraftColour_Sky_IcePlains);
|
||||
Biome::iceMountains = (new IceBiome(13))->setColor(0xa0a0a0)->setName(L"Ice Mountains")->setSnowCovered()->setDepthAndScale(0.3f, 1.3f)->setTemperatureAndDownfall(0, 0.5f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_IceMountains, eMinecraftColour_Foliage_IceMountains, eMinecraftColour_Water_IceMountains,eMinecraftColour_Sky_IceMountains);
|
||||
|
||||
|
||||
Biome::mushroomIsland = (new MushroomIslandBiome(14))->setColor(0xff00ff)->setName(L"MushroomIsland")->setTemperatureAndDownfall(0.9f, 1.0f)->setDepthAndScale(0.2f, 1.0f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_MushroomIsland, eMinecraftColour_Foliage_MushroomIsland, eMinecraftColour_Water_MushroomIsland,eMinecraftColour_Sky_MushroomIsland);
|
||||
Biome::mushroomIslandShore = (new MushroomIslandBiome(15))->setColor(0xa000ff)->setName(L"MushroomIslandShore")->setTemperatureAndDownfall(0.9f, 1.0f)->setDepthAndScale(-1, 0.1f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_MushroomIslandShore, eMinecraftColour_Foliage_MushroomIslandShore, eMinecraftColour_Water_MushroomIslandShore,eMinecraftColour_Sky_MushroomIslandShore);
|
||||
|
||||
Biome::beaches = (new BeachBiome(16))->setColor(0xfade55)->setName(L"Beach")->setTemperatureAndDownfall(0.8f, 0.4f)->setDepthAndScale(0.0f, 0.1f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Beach, eMinecraftColour_Foliage_Beach, eMinecraftColour_Water_Beach,eMinecraftColour_Sky_Beach);
|
||||
Biome::desertHills = (new DesertBiome(17))->setColor(0xd25f12)->setName(L"DesertHills")->setNoRain()->setTemperatureAndDownfall(2, 0)->setDepthAndScale(0.3f, 0.8f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_DesertHills, eMinecraftColour_Foliage_DesertHills, eMinecraftColour_Water_DesertHills,eMinecraftColour_Sky_DesertHills);
|
||||
Biome::forestHills = (new ForestBiome(18))->setColor(0x22551c)->setName(L"ForestHills")->setLeafColor(0x4EBA31)->setTemperatureAndDownfall(0.7f, 0.8f)->setDepthAndScale(0.3f, 0.7f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_ForestHills, eMinecraftColour_Foliage_ForestHills, eMinecraftColour_Water_ForestHills,eMinecraftColour_Sky_ForestHills);
|
||||
Biome::taigaHills = (new TaigaBiome(19))->setColor(0x163933)->setName(L"TaigaHills")->setSnowCovered()->setLeafColor(0x4EBA31)->setTemperatureAndDownfall(0.05f, 0.8f)->setDepthAndScale(0.3f, 0.8f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_TaigaHills, eMinecraftColour_Foliage_TaigaHills, eMinecraftColour_Water_TaigaHills,eMinecraftColour_Sky_TaigaHills);
|
||||
Biome::smallerExtremeHills = (new ExtremeHillsBiome(20))->setColor(0x72789a)->setName(L"Extreme Hills Edge")->setDepthAndScale(0.2f, 0.8f)->setTemperatureAndDownfall(0.2f, 0.3f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_ExtremeHillsEdge, eMinecraftColour_Foliage_ExtremeHillsEdge, eMinecraftColour_Water_ExtremeHillsEdge,eMinecraftColour_Sky_ExtremeHillsEdge);
|
||||
Biome::desertHills = (new DesertBiome(17))->setColor(0xd25f12)->setName(L"DesertHills")->setNoRain()->setTemperatureAndDownfall(2, 0)->setDepthAndScale(0.3f, 0.8f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_DesertHills, eMinecraftColour_Foliage_DesertHills, eMinecraftColour_Water_DesertHills,eMinecraftColour_Sky_DesertHills);
|
||||
Biome::forestHills = (new ForestBiome(18))->setColor(0x22551c)->setName(L"ForestHills")->setLeafColor(0x4EBA31)->setTemperatureAndDownfall(0.7f, 0.8f)->setDepthAndScale(0.3f, 0.7f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_ForestHills, eMinecraftColour_Foliage_ForestHills, eMinecraftColour_Water_ForestHills,eMinecraftColour_Sky_ForestHills);
|
||||
Biome::taigaHills = (new TaigaBiome(19))->setColor(0x163933)->setName(L"TaigaHills")->setSnowCovered()->setLeafColor(0x4EBA31)->setTemperatureAndDownfall(0.05f, 0.8f)->setDepthAndScale(0.3f, 0.8f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_TaigaHills, eMinecraftColour_Foliage_TaigaHills, eMinecraftColour_Water_TaigaHills,eMinecraftColour_Sky_TaigaHills);
|
||||
Biome::smallerExtremeHills = (new ExtremeHillsBiome(20))->setColor(0x72789a)->setName(L"Extreme Hills Edge")->setDepthAndScale(0.2f, 0.8f)->setTemperatureAndDownfall(0.2f, 0.3f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_ExtremeHillsEdge, eMinecraftColour_Foliage_ExtremeHillsEdge, eMinecraftColour_Water_ExtremeHillsEdge,eMinecraftColour_Sky_ExtremeHillsEdge);
|
||||
|
||||
Biome::jungle = (new JungleBiome(21))->setColor(0x537b09)->setName(L"Jungle")->setLeafColor(0x537b09)->setTemperatureAndDownfall(1.2f, 0.9f)->setDepthAndScale(0.2f, 0.4f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Jungle, eMinecraftColour_Foliage_Jungle, eMinecraftColour_Water_Jungle,eMinecraftColour_Sky_Jungle);
|
||||
Biome::jungleHills = (new JungleBiome(22))->setColor(0x2c4205)->setName(L"JungleHills")->setLeafColor(0x537b09)->setTemperatureAndDownfall(1.2f, 0.9f)->setDepthAndScale(1.8f, 0.5f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_JungleHills, eMinecraftColour_Foliage_JungleHills, eMinecraftColour_Water_JungleHills,eMinecraftColour_Sky_JungleHills);
|
||||
}
|
||||
|
||||
|
||||
Biome::Biome(int id) : id(id)
|
||||
{
|
||||
// 4J Stu Default inits
|
||||
color = 0;
|
||||
// snowCovered = false; // 4J - this isn't set by the java game any more so removing to save confusion
|
||||
// snowCovered = false; // 4J - this isn't set by the java game any more so removing to save confusion
|
||||
|
||||
topMaterial = (byte) Tile::grass_Id;
|
||||
material = (byte) Tile::dirt_Id;
|
||||
@@ -103,9 +103,9 @@ Biome::Biome(int id) : id(id)
|
||||
|
||||
/* 4J - removing these so that we can consistently return newly created trees via getTreeFeature, and let the calling function be resposible for deleting the returned tree
|
||||
normalTree = new TreeFeature();
|
||||
fancyTree = new BasicTree();
|
||||
birchTree = new BirchFeature();
|
||||
swampTree = new SwampTreeFeature();
|
||||
fancyTree = new BasicTree();
|
||||
birchTree = new BirchFeature();
|
||||
swampTree = new SwampTreeFeature();
|
||||
*/
|
||||
|
||||
biomes[id] = this;
|
||||
@@ -126,6 +126,8 @@ Biome::Biome(int id) : id(id)
|
||||
// wolves are added to forests and taigas
|
||||
|
||||
waterFriendlies.push_back(new MobSpawnerData(eTYPE_SQUID, 10, 4, 4));
|
||||
|
||||
ambientFriendlies.push_back(new MobSpawnerData(eTYPE_BAT, 10, 8, 8));
|
||||
}
|
||||
|
||||
Biome::~Biome()
|
||||
@@ -150,7 +152,7 @@ Biome *Biome::setLeafFoliageWaterSkyColor(eMinecraftColour grassColor, eMinecraf
|
||||
|
||||
Biome *Biome::setTemperatureAndDownfall(float temp, float downfall)
|
||||
{
|
||||
this->temperature = temp;
|
||||
temperature = temp;
|
||||
this->downfall = downfall;
|
||||
return this;
|
||||
}
|
||||
@@ -164,17 +166,17 @@ Biome *Biome::setDepthAndScale(float depth, float scale)
|
||||
|
||||
Biome *Biome::setNoRain()
|
||||
{
|
||||
_hasRain = false;
|
||||
return this;
|
||||
_hasRain = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
Feature *Biome::getTreeFeature(Random *random)
|
||||
{
|
||||
if (random->nextInt(10) == 0)
|
||||
if (random->nextInt(10) == 0)
|
||||
{
|
||||
return new BasicTree(false); // 4J used to return member fancyTree, now returning newly created object so that caller can be consistently resposible for cleanup
|
||||
}
|
||||
return new TreeFeature(false); // 4J used to return member normalTree, now returning newly created object so that caller can be consistently resposible for cleanup
|
||||
return new BasicTree(false); // 4J used to return member fancyTree, now returning newly created object so that caller can be consistently resposible for cleanup
|
||||
}
|
||||
return new TreeFeature(false); // 4J used to return member normalTree, now returning newly created object so that caller can be consistently resposible for cleanup
|
||||
}
|
||||
|
||||
Feature *Biome::getGrassFeature(Random *random)
|
||||
@@ -184,48 +186,49 @@ Feature *Biome::getGrassFeature(Random *random)
|
||||
|
||||
Biome *Biome::setSnowCovered()
|
||||
{
|
||||
this->snowCovered = true;
|
||||
return this;
|
||||
snowCovered = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
Biome *Biome::setName(const wstring &name)
|
||||
{
|
||||
this->m_name = name;
|
||||
return this;
|
||||
this->m_name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
Biome *Biome::setLeafColor(int leafColor)
|
||||
{
|
||||
this->leafColor = leafColor;
|
||||
return this;
|
||||
this->leafColor = leafColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
Biome *Biome::setColor(int color)
|
||||
{
|
||||
this->color = color;
|
||||
return this;
|
||||
this->color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
int Biome::getSkyColor(float temp)
|
||||
{
|
||||
//temp /= 3.0f;
|
||||
//if (temp < -1) temp = -1;
|
||||
//if (temp > 1) temp = 1;
|
||||
//return Color::getHSBColor(224 / 360.0f - temp * 0.05f, 0.50f + temp * 0.1f, 1.0f).getRGB();
|
||||
|
||||
//temp /= 3.0f;
|
||||
//if (temp < -1) temp = -1;
|
||||
//if (temp > 1) temp = 1;
|
||||
//return Color::getHSBColor(224 / 360.0f - temp * 0.05f, 0.50f + temp * 0.1f, 1.0f).getRGB();
|
||||
|
||||
// 4J Stu - Load colour from texture pack
|
||||
return Minecraft::GetInstance()->getColourTable()->getColor( m_skyColor );
|
||||
}
|
||||
|
||||
vector<Biome::MobSpawnerData *> *Biome::getMobs(MobCategory *category)
|
||||
{
|
||||
if (category == MobCategory::monster) return &enemies;
|
||||
if (category == MobCategory::creature) return &friendlies;
|
||||
if (category == MobCategory::waterCreature) return &waterFriendlies;
|
||||
if (category == MobCategory::monster) return &enemies;
|
||||
if (category == MobCategory::creature) return &friendlies;
|
||||
if (category == MobCategory::waterCreature) return &waterFriendlies;
|
||||
if (category == MobCategory::creature_chicken) return &friendlies_chicken;
|
||||
if (category == MobCategory::creature_wolf) return &friendlies_wolf;
|
||||
if (category == MobCategory::creature_mushroomcow) return &friendlies_mushroomcow;
|
||||
return NULL;
|
||||
if (category == MobCategory::ambient) return &ambientFriendlies;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Biome::hasSnow()
|
||||
@@ -235,15 +238,15 @@ bool Biome::hasSnow()
|
||||
|
||||
if( getTemperature() >= 0.15f ) return false;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Biome::hasRain()
|
||||
{
|
||||
// 4J - snowCovered flag removed as it wasn't being set by the game anymore, replaced by call to hasSnow()
|
||||
if( hasSnow() ) return false;
|
||||
// if (snowCovered) return false;
|
||||
return _hasRain;
|
||||
// if (snowCovered) return false;
|
||||
return _hasRain;
|
||||
}
|
||||
|
||||
bool Biome::isHumid()
|
||||
@@ -256,8 +259,8 @@ float Biome::getCreatureProbability()
|
||||
return 0.1f;
|
||||
}
|
||||
|
||||
int Biome::getDownfallInt()
|
||||
{
|
||||
int Biome::getDownfallInt()
|
||||
{
|
||||
return (int) (downfall * 65536);
|
||||
}
|
||||
|
||||
@@ -285,19 +288,19 @@ void Biome::decorate(Level *level, Random *random, int xo, int zo)
|
||||
|
||||
int Biome::getGrassColor()
|
||||
{
|
||||
//double temp = Mth::clamp(getTemperature(), 0.0f, 1.0f);
|
||||
//double rain = Mth::clamp(getDownfall(), 0.0f, 1.0f);
|
||||
//double temp = Mth::clamp(getTemperature(), 0.0f, 1.0f);
|
||||
//double rain = Mth::clamp(getDownfall(), 0.0f, 1.0f);
|
||||
|
||||
//return GrassColor::get(temp, rain);
|
||||
//return GrassColor::get(temp, rain);
|
||||
return Minecraft::GetInstance()->getColourTable()->getColor( m_grassColor );
|
||||
}
|
||||
|
||||
int Biome::getFolageColor()
|
||||
{
|
||||
//double temp = Mth::clamp(getTemperature(), 0.0f, 1.0f);
|
||||
//double rain = Mth::clamp(getDownfall(), 0.0f, 1.0f);
|
||||
//double temp = Mth::clamp(getTemperature(), 0.0f, 1.0f);
|
||||
//double rain = Mth::clamp(getDownfall(), 0.0f, 1.0f);
|
||||
|
||||
//return FoliageColor::get(temp, rain);
|
||||
//return FoliageColor::get(temp, rain);
|
||||
return Minecraft::GetInstance()->getColourTable()->getColor( m_foliageColor );
|
||||
}
|
||||
|
||||
|
||||
@@ -51,54 +51,55 @@ public:
|
||||
|
||||
public:
|
||||
wstring m_name;
|
||||
int color;
|
||||
byte topMaterial;
|
||||
byte material;
|
||||
int leafColor;
|
||||
float depth;
|
||||
float scale;
|
||||
float temperature;
|
||||
float downfall;
|
||||
int color;
|
||||
byte topMaterial;
|
||||
byte material;
|
||||
int leafColor;
|
||||
float depth;
|
||||
float scale;
|
||||
float temperature;
|
||||
float downfall;
|
||||
//int waterColor; // 4J Stu removed
|
||||
|
||||
BiomeDecorator *decorator;
|
||||
BiomeDecorator *decorator;
|
||||
|
||||
const int id;
|
||||
|
||||
class MobSpawnerData : public WeighedRandomItem
|
||||
class MobSpawnerData : public WeighedRandomItem
|
||||
{
|
||||
public:
|
||||
eINSTANCEOF mobClass;
|
||||
int minCount;
|
||||
int maxCount;
|
||||
|
||||
MobSpawnerData(eINSTANCEOF mobClass, int probabilityWeight, int minCount, int maxCount) : WeighedRandomItem(probabilityWeight)
|
||||
MobSpawnerData(eINSTANCEOF mobClass, int probabilityWeight, int minCount, int maxCount) : WeighedRandomItem(probabilityWeight)
|
||||
{
|
||||
this->mobClass = mobClass;
|
||||
this->minCount = minCount;
|
||||
this->maxCount = maxCount;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
vector<MobSpawnerData *> enemies;
|
||||
vector<MobSpawnerData *> friendlies;
|
||||
vector<MobSpawnerData *> waterFriendlies;
|
||||
vector<MobSpawnerData *> enemies;
|
||||
vector<MobSpawnerData *> friendlies;
|
||||
vector<MobSpawnerData *> waterFriendlies;
|
||||
vector<MobSpawnerData *> friendlies_chicken;
|
||||
vector<MobSpawnerData *> friendlies_wolf;
|
||||
vector<MobSpawnerData *> friendlies_mushroomcow;
|
||||
|
||||
vector<MobSpawnerData *> ambientFriendlies;
|
||||
|
||||
Biome(int id);
|
||||
~Biome();
|
||||
|
||||
|
||||
BiomeDecorator *createDecorator();
|
||||
|
||||
private:
|
||||
Biome *setTemperatureAndDownfall(float temp, float downfall);
|
||||
Biome *setDepthAndScale(float depth, float scale);
|
||||
Biome *setDepthAndScale(float depth, float scale);
|
||||
|
||||
bool snowCovered;
|
||||
bool _hasRain;
|
||||
bool _hasRain;
|
||||
|
||||
// 4J Added
|
||||
eMinecraftColour m_grassColor;
|
||||
@@ -106,47 +107,47 @@ private:
|
||||
eMinecraftColour m_waterColor;
|
||||
eMinecraftColour m_skyColor;
|
||||
|
||||
Biome *setNoRain();
|
||||
Biome *setNoRain();
|
||||
|
||||
protected:
|
||||
/* removing these so that we can consistently return newly created trees via getTreeFeature, and let the calling function be resposible for deleting the returned tree
|
||||
TreeFeature *normalTree;
|
||||
BasicTree *fancyTree;
|
||||
BirchFeature *birchTree;
|
||||
SwampTreeFeature *swampTree;
|
||||
BasicTree *fancyTree;
|
||||
BirchFeature *birchTree;
|
||||
SwampTreeFeature *swampTree;
|
||||
*/
|
||||
|
||||
public:
|
||||
virtual Feature *getTreeFeature(Random *random);
|
||||
virtual Feature *getTreeFeature(Random *random);
|
||||
virtual Feature *getGrassFeature(Random *random);
|
||||
|
||||
protected:
|
||||
Biome *setSnowCovered();
|
||||
Biome *setName(const wstring &name);
|
||||
Biome *setLeafColor(int leafColor);
|
||||
Biome *setColor(int color);
|
||||
Biome *setName(const wstring &name);
|
||||
Biome *setLeafColor(int leafColor);
|
||||
Biome *setColor(int color);
|
||||
|
||||
// 4J Added
|
||||
Biome *setLeafFoliageWaterSkyColor(eMinecraftColour grassColor, eMinecraftColour foliageColor, eMinecraftColour waterColour, eMinecraftColour skyColour);
|
||||
|
||||
public:
|
||||
virtual int getSkyColor(float temp);
|
||||
virtual int getSkyColor(float temp);
|
||||
|
||||
vector<MobSpawnerData *> *getMobs(MobCategory *category);
|
||||
vector<MobSpawnerData *> *getMobs(MobCategory *category);
|
||||
|
||||
virtual bool hasSnow();
|
||||
virtual bool hasRain();
|
||||
virtual bool hasSnow();
|
||||
virtual bool hasRain();
|
||||
virtual bool isHumid();
|
||||
|
||||
virtual float getCreatureProbability();
|
||||
virtual int getDownfallInt();
|
||||
virtual int getTemperatureInt();
|
||||
virtual float getCreatureProbability();
|
||||
virtual int getDownfallInt();
|
||||
virtual int getTemperatureInt();
|
||||
virtual float getDownfall(); // 4J - brought forward from 1.2.3
|
||||
virtual float getTemperature(); // 4J - brought forward from 1.2.3
|
||||
|
||||
virtual void decorate(Level *level, Random *random, int xo, int zo);
|
||||
virtual void decorate(Level *level, Random *random, int xo, int zo);
|
||||
|
||||
virtual int getGrassColor();
|
||||
virtual int getFolageColor();
|
||||
virtual int getGrassColor();
|
||||
virtual int getFolageColor();
|
||||
virtual int getWaterColor(); // 4J Added
|
||||
};
|
||||
@@ -55,8 +55,8 @@ void BiomeDecorator::_init()
|
||||
lapisOreFeature = new OreFeature(Tile::lapisOre_Id, 6);
|
||||
yellowFlowerFeature = new FlowerFeature(Tile::flower_Id);
|
||||
roseFlowerFeature = new FlowerFeature(Tile::rose_Id);
|
||||
brownMushroomFeature = new FlowerFeature(Tile::mushroom1_Id);
|
||||
redMushroomFeature = new FlowerFeature(Tile::mushroom2_Id);
|
||||
brownMushroomFeature = new FlowerFeature(Tile::mushroom_brown_Id);
|
||||
redMushroomFeature = new FlowerFeature(Tile::mushroom_red_Id);
|
||||
hugeMushroomFeature = new HugeMushroomFeature();
|
||||
reedsFeature = new ReedsFeature();
|
||||
cactusFeature = new CactusFeature();
|
||||
@@ -123,12 +123,12 @@ void BiomeDecorator::decorate()
|
||||
PIXEndNamedEvent();
|
||||
|
||||
PIXBeginNamedEvent(0,"Decorate mushrooms/flowers/grass");
|
||||
for (int i = 0; i < hugeMushrooms; i++)
|
||||
for (int i = 0; i < hugeMushrooms; i++)
|
||||
{
|
||||
int x = xo + random->nextInt(16) + 8;
|
||||
int z = zo + random->nextInt(16) + 8;
|
||||
hugeMushroomFeature->place(level, random, x, level->getHeightmap(x, z), z);
|
||||
}
|
||||
int x = xo + random->nextInt(16) + 8;
|
||||
int z = zo + random->nextInt(16) + 8;
|
||||
hugeMushroomFeature->place(level, random, x, level->getHeightmap(x, z), z);
|
||||
}
|
||||
|
||||
for (int i = 0; i < flowerCount; i++)
|
||||
{
|
||||
@@ -176,15 +176,15 @@ void BiomeDecorator::decorate()
|
||||
}
|
||||
if(deadBushFeature != NULL)delete deadBushFeature;
|
||||
|
||||
for (int i = 0; i < waterlilyCount; i++)
|
||||
for (int i = 0; i < waterlilyCount; i++)
|
||||
{
|
||||
int x = xo + random->nextInt(16) + 8;
|
||||
int z = zo + random->nextInt(16) + 8;
|
||||
int y = random->nextInt(Level::genDepth);
|
||||
while (y > 0 && level->getTile(x, y - 1, z) == 0)
|
||||
y--;
|
||||
waterlilyFeature->place(level, random, x, y, z);
|
||||
}
|
||||
int x = xo + random->nextInt(16) + 8;
|
||||
int z = zo + random->nextInt(16) + 8;
|
||||
int y = random->nextInt(Level::genDepth);
|
||||
while (y > 0 && level->getTile(x, y - 1, z) == 0)
|
||||
y--;
|
||||
waterlilyFeature->place(level, random, x, y, z);
|
||||
}
|
||||
|
||||
for (int i = 0; i < mushroomCount; i++)
|
||||
{
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
// 4J - removal of separate temperature & downfall layers brought forward from 1.2.3
|
||||
void BiomeSource::_init()
|
||||
{
|
||||
layer = nullptr;
|
||||
layer = nullptr;
|
||||
zoomedLayer = nullptr;
|
||||
|
||||
|
||||
cache = new BiomeCache(this);
|
||||
|
||||
playerSpawnBiomes.push_back(Biome::forest);
|
||||
@@ -39,7 +39,7 @@ void BiomeSource::_init(__int64 seed, LevelType *generator)
|
||||
|
||||
BiomeSource::BiomeSource()
|
||||
{
|
||||
_init();
|
||||
_init();
|
||||
}
|
||||
|
||||
// 4J added
|
||||
@@ -105,7 +105,7 @@ void BiomeSource::getDownfallBlock(floatArray &downfalls, int x, int z, int w, i
|
||||
|
||||
BiomeCache::Block *BiomeSource::getBlockAt(int x, int y)
|
||||
{
|
||||
return cache->getBlockAt(x, y);
|
||||
return cache->getBlockAt(x, y);
|
||||
}
|
||||
|
||||
float BiomeSource::getTemperature(int x, int y, int z) const
|
||||
@@ -277,6 +277,7 @@ void BiomeSource::getBiomeIndexBlock(byteArray& biomeIndices, int x, int z, int
|
||||
*/
|
||||
bool BiomeSource::containsOnly(int x, int z, int r, vector<Biome *> allowed)
|
||||
{
|
||||
IntCache::releaseAll();
|
||||
int x0 = ((x - r) >> 2);
|
||||
int z0 = ((z - r) >> 2);
|
||||
int x1 = ((x + r) >> 2);
|
||||
@@ -304,11 +305,12 @@ bool BiomeSource::containsOnly(int x, int z, int r, vector<Biome *> allowed)
|
||||
*/
|
||||
bool BiomeSource::containsOnly(int x, int z, int r, Biome *allowed)
|
||||
{
|
||||
IntCache::releaseAll();
|
||||
int x0 = ((x - r) >> 2);
|
||||
int z0 = ((z - r) >> 2);
|
||||
int x1 = ((x + r) >> 2);
|
||||
int z1 = ((z + r) >> 2);
|
||||
|
||||
|
||||
int w = x1 - x0;
|
||||
int h = z1 - z0;
|
||||
int biomesCount = w*h;
|
||||
@@ -330,6 +332,7 @@ bool BiomeSource::containsOnly(int x, int z, int r, Biome *allowed)
|
||||
*/
|
||||
TilePos *BiomeSource::findBiome(int x, int z, int r, Biome *toFind, Random *random)
|
||||
{
|
||||
IntCache::releaseAll();
|
||||
int x0 = ((x - r) >> 2);
|
||||
int z0 = ((z - r) >> 2);
|
||||
int x1 = ((x + r) >> 2);
|
||||
@@ -367,6 +370,7 @@ TilePos *BiomeSource::findBiome(int x, int z, int r, Biome *toFind, Random *rand
|
||||
*/
|
||||
TilePos *BiomeSource::findBiome(int x, int z, int r, vector<Biome *> allowed, Random *random)
|
||||
{
|
||||
IntCache::releaseAll();
|
||||
int x0 = ((x - r) >> 2);
|
||||
int z0 = ((z - r) >> 2);
|
||||
int x1 = ((x + r) >> 2);
|
||||
@@ -378,8 +382,7 @@ TilePos *BiomeSource::findBiome(int x, int z, int r, vector<Biome *> allowed, Ra
|
||||
intArray biomes = layer->getArea(x0, z0, w, h);
|
||||
TilePos *res = NULL;
|
||||
int found = 0;
|
||||
int biomesCount = w*h;
|
||||
for (unsigned int i = 0; i < biomesCount; i++)
|
||||
for (unsigned int i = 0; i < w * h; i++)
|
||||
{
|
||||
int xx = (x0 + i % w) << 2;
|
||||
int zz = (z0 + i / w) << 2;
|
||||
@@ -420,7 +423,7 @@ __int64 BiomeSource::findSeed(LevelType *generator)
|
||||
mcprogress->progressStage(IDS_PROGRESS_NEW_WORLD_SEED);
|
||||
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_EnableHeightWaterBiomeOverride))
|
||||
if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_EnableBiomeOverride))
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
@@ -561,30 +564,30 @@ bool BiomeSource::getIsMatch(float *frac)
|
||||
{
|
||||
// A true for a particular biome type here marks it as one that *has* to be present
|
||||
static const bool critical[Biome::BIOME_COUNT] = {
|
||||
true, // ocean
|
||||
true, // plains
|
||||
true, // desert
|
||||
false, // extreme hills
|
||||
true, // forest
|
||||
true, // taiga
|
||||
true, // swamps
|
||||
false, // river
|
||||
false, // hell
|
||||
false, // end biome
|
||||
false, // frozen ocean
|
||||
false, // frozen river
|
||||
false, // ice flats
|
||||
false, // ice mountains
|
||||
true, // mushroom island / shore
|
||||
false, // mushroom shore (combined with above)
|
||||
false, // beach
|
||||
false, // desert hills (combined with desert)
|
||||
false, // forest hills (combined with forest)
|
||||
false, // taiga hills (combined with taga)
|
||||
false, // small extreme hills
|
||||
true, // jungle
|
||||
false, // jungle hills (combined with jungle)
|
||||
};
|
||||
true, // ocean
|
||||
true, // plains
|
||||
true, // desert
|
||||
false, // extreme hills
|
||||
true, // forest
|
||||
true, // taiga
|
||||
true, // swamps
|
||||
false, // river
|
||||
false, // hell
|
||||
false, // end biome
|
||||
false, // frozen ocean
|
||||
false, // frozen river
|
||||
false, // ice flats
|
||||
false, // ice mountains
|
||||
true, // mushroom island / shore
|
||||
false, // mushroom shore (combined with above)
|
||||
false, // beach
|
||||
false, // desert hills (combined with desert)
|
||||
false, // forest hills (combined with forest)
|
||||
false, // taiga hills (combined with taga)
|
||||
false, // small extreme hills
|
||||
true, // jungle
|
||||
false, // jungle hills (combined with jungle)
|
||||
};
|
||||
|
||||
|
||||
// Don't want more than 15% ocean
|
||||
|
||||
@@ -9,37 +9,37 @@ BirchFeature::BirchFeature(bool doUpdate) : Feature(doUpdate)
|
||||
|
||||
bool BirchFeature::place(Level *level, Random *random, int x, int y, int z)
|
||||
{
|
||||
int treeHeight = random->nextInt(3) + 5;
|
||||
int treeHeight = random->nextInt(3) + 5;
|
||||
|
||||
bool free = true;
|
||||
if (y < 1 || y + treeHeight + 1 > Level::maxBuildHeight) return false;
|
||||
bool free = true;
|
||||
if (y < 1 || y + treeHeight + 1 > Level::maxBuildHeight) return false;
|
||||
|
||||
for (int yy = y; yy <= y + 1 + treeHeight; yy++)
|
||||
for (int yy = y; yy <= y + 1 + treeHeight; yy++)
|
||||
{
|
||||
int r = 1;
|
||||
if (yy == y) r = 0;
|
||||
if (yy >= y + 1 + treeHeight - 2) r = 2;
|
||||
for (int xx = x - r; xx <= x + r && free; xx++)
|
||||
int r = 1;
|
||||
if (yy == y) r = 0;
|
||||
if (yy >= y + 1 + treeHeight - 2) r = 2;
|
||||
for (int xx = x - r; xx <= x + r && free; xx++)
|
||||
{
|
||||
for (int zz = z - r; zz <= z + r && free; zz++)
|
||||
for (int zz = z - r; zz <= z + r && free; zz++)
|
||||
{
|
||||
if (yy >= 0 && yy < Level::maxBuildHeight)
|
||||
if (yy >= 0 && yy < Level::maxBuildHeight)
|
||||
{
|
||||
int tt = level->getTile(xx, yy, zz);
|
||||
if (tt != 0 && tt != Tile::leaves_Id) free = false;
|
||||
}
|
||||
int tt = level->getTile(xx, yy, zz);
|
||||
if (tt != 0 && tt != Tile::leaves_Id) free = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
free = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!free) return false;
|
||||
if (!free) return false;
|
||||
|
||||
int belowTile = level->getTile(x, y - 1, z);
|
||||
if ((belowTile != Tile::grass_Id && belowTile != Tile::dirt_Id) || y >= Level::maxBuildHeight - treeHeight - 1) return false;
|
||||
int belowTile = level->getTile(x, y - 1, z);
|
||||
if ((belowTile != Tile::grass_Id && belowTile != Tile::dirt_Id) || y >= Level::maxBuildHeight - treeHeight - 1) return false;
|
||||
|
||||
// 4J Stu Added to stop tree features generating areas previously place by game rule generation
|
||||
if(app.getLevelGenerationOptions() != NULL)
|
||||
@@ -54,28 +54,29 @@ bool BirchFeature::place(Level *level, Random *random, int x, int y, int z)
|
||||
}
|
||||
}
|
||||
|
||||
level->setTileNoUpdate(x, y - 1, z, Tile::dirt_Id);
|
||||
placeBlock(level, x, y - 1, z, Tile::dirt_Id);
|
||||
|
||||
for (int yy = y - 3 + treeHeight; yy <= y + treeHeight; yy++)
|
||||
for (int yy = y - 3 + treeHeight; yy <= y + treeHeight; yy++)
|
||||
{
|
||||
int yo = yy - (y + treeHeight);
|
||||
int offs = 1 - yo / 2;
|
||||
for (int xx = x - offs; xx <= x + offs; xx++)
|
||||
int yo = yy - (y + treeHeight);
|
||||
int offs = 1 - yo / 2;
|
||||
for (int xx = x - offs; xx <= x + offs; xx++)
|
||||
{
|
||||
int xo = xx - (x);
|
||||
for (int zz = z - offs; zz <= z + offs; zz++)
|
||||
int xo = xx - (x);
|
||||
for (int zz = z - offs; zz <= z + offs; zz++)
|
||||
{
|
||||
int zo = zz - (z);
|
||||
if (abs(xo) == offs && abs(zo) == offs && (random->nextInt(2) == 0 || yo == 0)) continue;
|
||||
if (!Tile::solid[level->getTile(xx, yy, zz)]) placeBlock(level, xx, yy, zz, Tile::leaves_Id, LeafTile::BIRCH_LEAF);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int hh = 0; hh < treeHeight; hh++)
|
||||
int zo = zz - (z);
|
||||
if (abs(xo) == offs && abs(zo) == offs && (random->nextInt(2) == 0 || yo == 0)) continue;
|
||||
int t = level->getTile(xx, yy, zz);
|
||||
if (t == 0 || t == Tile::leaves_Id) placeBlock(level, xx, yy, zz, Tile::leaves_Id, LeafTile::BIRCH_LEAF);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int hh = 0; hh < treeHeight; hh++)
|
||||
{
|
||||
int t = level->getTile(x, y + hh, z);
|
||||
if (t == 0 || t == Tile::leaves_Id) placeBlock(level, x, y + hh, z, Tile::treeTrunk_Id, TreeTile::BIRCH_TRUNK);
|
||||
}
|
||||
return true;
|
||||
int t = level->getTile(x, y + hh, z);
|
||||
if (t == 0 || t == Tile::leaves_Id) placeBlock(level, x, y + hh, z, Tile::treeTrunk_Id, TreeTile::BIRCH_TRUNK);
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "net.minecraft.world.phys.h"
|
||||
#include "net.minecraft.world.item.h"
|
||||
#include "net.minecraft.world.entity.h"
|
||||
#include "net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "net.minecraft.world.entity.monster.h"
|
||||
#include "net.minecraft.world.entity.projectile.h"
|
||||
#include "SharedConstants.h"
|
||||
#include "..\Minecraft.Client\Textures.h"
|
||||
@@ -18,16 +20,11 @@ Blaze::Blaze(Level *level) : Monster(level)
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to ensure that
|
||||
// the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to ensure that the derived version of the function is called
|
||||
health = getMaxHealth();
|
||||
|
||||
this->textureIdx = TN_MOB_BLAZE; // 4J Was "/mob/fire.png";
|
||||
registerAttributes();
|
||||
setHealth(getMaxHealth());
|
||||
|
||||
fireImmune = true;
|
||||
attackDamage = 6;
|
||||
xpReward = XP_REWARD_LARGE;
|
||||
// this.setSize(1.2f, 1.8f);
|
||||
|
||||
// 4J Default inits
|
||||
allowedHeightOffset = 0.5f;
|
||||
@@ -35,9 +32,10 @@ Blaze::Blaze(Level *level) : Monster(level)
|
||||
attackCounter = 0;
|
||||
}
|
||||
|
||||
int Blaze::getMaxHealth()
|
||||
void Blaze::registerAttributes()
|
||||
{
|
||||
return 20;
|
||||
Monster::registerAttributes();
|
||||
getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->setBaseValue(6);
|
||||
}
|
||||
|
||||
void Blaze::defineSynchedData()
|
||||
@@ -89,7 +87,7 @@ void Blaze::aiStep()
|
||||
allowedHeightOffset = .5f + (float) random->nextGaussian() * 3;
|
||||
}
|
||||
|
||||
if (getAttackTarget() != NULL && (getAttackTarget()->y + getAttackTarget()->getHeadHeight()) > (this->y + getHeadHeight() + allowedHeightOffset))
|
||||
if (getAttackTarget() != NULL && (getAttackTarget()->y + getAttackTarget()->getHeadHeight()) > (y + getHeadHeight() + allowedHeightOffset))
|
||||
{
|
||||
yd = yd + (.3f - yd) * .3f;
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ private:
|
||||
|
||||
public:
|
||||
Blaze(Level *level);
|
||||
virtual int getMaxHealth();
|
||||
|
||||
protected:
|
||||
virtual void registerAttributes();
|
||||
virtual void defineSynchedData();
|
||||
virtual int getAmbientSound();
|
||||
virtual int getHurtSound();
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "Dimension.h"
|
||||
|
||||
|
||||
#define BLOCK_REGION_UPDATE_FULLCHUNK 0x01
|
||||
#define BLOCK_REGION_UPDATE_ZEROHEIGHT 0x02 // added so we can still send a byte for ys, which really needs the range 0-256
|
||||
|
||||
BlockRegionUpdatePacket::~BlockRegionUpdatePacket()
|
||||
{
|
||||
@@ -82,10 +84,10 @@ BlockRegionUpdatePacket::BlockRegionUpdatePacket(int x, int y, int z, int xs, in
|
||||
size = inputSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BlockRegionUpdatePacket::read(DataInputStream *dis) //throws IOException
|
||||
{
|
||||
bIsFullChunk = dis->readBoolean();
|
||||
byte chunkFlags = dis->readByte();
|
||||
x = dis->readInt();
|
||||
y = dis->readShort();
|
||||
z = dis->readInt();
|
||||
@@ -93,6 +95,10 @@ void BlockRegionUpdatePacket::read(DataInputStream *dis) //throws IOException
|
||||
ys = dis->read() + 1;
|
||||
zs = dis->read() + 1;
|
||||
|
||||
bIsFullChunk = (chunkFlags & BLOCK_REGION_UPDATE_FULLCHUNK) ? true : false;
|
||||
if(chunkFlags & BLOCK_REGION_UPDATE_ZEROHEIGHT)
|
||||
ys = 0;
|
||||
|
||||
size = dis->readInt();
|
||||
levelIdx = ( size >> 30 ) & 3;
|
||||
size &= 0x3fffffff;
|
||||
@@ -131,7 +137,11 @@ void BlockRegionUpdatePacket::read(DataInputStream *dis) //throws IOException
|
||||
|
||||
void BlockRegionUpdatePacket::write(DataOutputStream *dos) // throws IOException
|
||||
{
|
||||
dos->writeBoolean(bIsFullChunk);
|
||||
byte chunkFlags = 0;
|
||||
if(bIsFullChunk) chunkFlags |= BLOCK_REGION_UPDATE_FULLCHUNK;
|
||||
if(ys == 0) chunkFlags |= BLOCK_REGION_UPDATE_ZEROHEIGHT;
|
||||
|
||||
dos->writeByte(chunkFlags);
|
||||
dos->writeInt(x);
|
||||
dos->writeShort(y);
|
||||
dos->writeInt(z);
|
||||
|
||||
36
Minecraft.World/BlockSource.h
Normal file
36
Minecraft.World/BlockSource.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "LocatableSource.h"
|
||||
|
||||
class Tile;
|
||||
class Material;
|
||||
class TileEntity;
|
||||
|
||||
class BlockSource : public LocatableSource
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @return The X coordinate for the middle of the block
|
||||
*/
|
||||
virtual double getX() = 0;
|
||||
|
||||
/**
|
||||
* @return The Y coordinate for the middle of the block
|
||||
*/
|
||||
virtual double getY() = 0;
|
||||
|
||||
/**
|
||||
* @return The Z coordinate for the middle of the block
|
||||
*/
|
||||
virtual double getZ() = 0;
|
||||
|
||||
virtual int getBlockX() = 0;
|
||||
virtual int getBlockY() = 0;
|
||||
virtual int getBlockZ() = 0;
|
||||
|
||||
virtual Tile *getType() = 0;
|
||||
virtual int getData() = 0;
|
||||
virtual Material *getMaterial() = 0;
|
||||
|
||||
virtual shared_ptr<TileEntity> getEntity() = 0;
|
||||
};
|
||||
68
Minecraft.World/BlockSourceImpl.cpp
Normal file
68
Minecraft.World/BlockSourceImpl.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "stdafx.h"
|
||||
#include "BlockSourceImpl.h"
|
||||
#include "net.minecraft.world.level.h"
|
||||
#include "net.minecraft.world.level.tile.h"
|
||||
#include "net.minecraft.world.level.tile.entity.h"
|
||||
|
||||
BlockSourceImpl::BlockSourceImpl(Level *world, int x, int y, int z)
|
||||
{
|
||||
this->world = world;
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
Level *BlockSourceImpl::getWorld()
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
||||
double BlockSourceImpl::getX()
|
||||
{
|
||||
return x + 0.5;
|
||||
}
|
||||
|
||||
double BlockSourceImpl::getY()
|
||||
{
|
||||
return y + 0.5;
|
||||
}
|
||||
|
||||
double BlockSourceImpl::getZ()
|
||||
{
|
||||
return z + 0.5;
|
||||
}
|
||||
|
||||
int BlockSourceImpl::getBlockX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
int BlockSourceImpl::getBlockY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
int BlockSourceImpl::getBlockZ()
|
||||
{
|
||||
return z;
|
||||
}
|
||||
|
||||
Tile *BlockSourceImpl::getType()
|
||||
{
|
||||
return Tile::tiles[world->getTile(x, y, z)];
|
||||
}
|
||||
|
||||
int BlockSourceImpl::getData()
|
||||
{
|
||||
return world->getData(x, y, z);
|
||||
}
|
||||
|
||||
Material *BlockSourceImpl::getMaterial()
|
||||
{
|
||||
return world->getMaterial(x, y, z);
|
||||
}
|
||||
|
||||
shared_ptr<TileEntity> BlockSourceImpl::getEntity()
|
||||
{
|
||||
return world->getTileEntity(x, y, z);
|
||||
}
|
||||
29
Minecraft.World/BlockSourceImpl.h
Normal file
29
Minecraft.World/BlockSourceImpl.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockSource.h"
|
||||
|
||||
class Level;
|
||||
|
||||
class BlockSourceImpl : public BlockSource
|
||||
{
|
||||
private:
|
||||
Level *world;
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
|
||||
public:
|
||||
BlockSourceImpl(Level *world, int x, int y, int z);
|
||||
|
||||
Level *getWorld();
|
||||
double getX();
|
||||
double getY();
|
||||
double getZ();
|
||||
int getBlockX();
|
||||
int getBlockY();
|
||||
int getBlockZ();
|
||||
Tile *getType();
|
||||
int getData();
|
||||
Material *getMaterial();
|
||||
shared_ptr<TileEntity> getEntity();
|
||||
};
|
||||
@@ -52,7 +52,7 @@ void Boat::defineSynchedData()
|
||||
{
|
||||
entityData->define(DATA_ID_HURT, 0);
|
||||
entityData->define(DATA_ID_HURTDIR, 1);
|
||||
entityData->define(DATA_ID_DAMAGE, 0);
|
||||
entityData->define(DATA_ID_DAMAGE, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
@@ -90,8 +90,9 @@ double Boat::getRideHeight()
|
||||
return bbHeight * 0.0f - 0.3f;
|
||||
}
|
||||
|
||||
bool Boat::hurt(DamageSource *source, int hurtDamage)
|
||||
bool Boat::hurt(DamageSource *source, float hurtDamage)
|
||||
{
|
||||
if (isInvulnerable()) return false;
|
||||
if (level->isClientSide || removed) return true;
|
||||
|
||||
// 4J-JEV: Fix for #88212,
|
||||
@@ -100,9 +101,10 @@ bool Boat::hurt(DamageSource *source, int hurtDamage)
|
||||
{
|
||||
shared_ptr<Entity> attacker = source->getDirectEntity();
|
||||
|
||||
if (dynamic_pointer_cast<Player>(attacker) != NULL &&
|
||||
!dynamic_pointer_cast<Player>(attacker)->isAllowedToHurtEntity( shared_from_this() ))
|
||||
if ( attacker->instanceof(eTYPE_PLAYER) && !dynamic_pointer_cast<Player>(attacker)->isAllowedToHurtEntity( shared_from_this() ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
setHurtDir(-getHurtDir());
|
||||
@@ -117,13 +119,13 @@ bool Boat::hurt(DamageSource *source, int hurtDamage)
|
||||
markHurt();
|
||||
|
||||
// 4J Stu - Brought froward from 12w36 to fix #46611 - TU5: Gameplay: Minecarts and boat requires more hits than one to be destroyed in creative mode
|
||||
shared_ptr<Player> player = dynamic_pointer_cast<Player>(source->getEntity());
|
||||
if (player != NULL && player->abilities.instabuild) setDamage(100);
|
||||
// 4J-PB - Fix for XB1 #175735 - [CRASH] [Multi-Plat]: Code: Gameplay: Placing a boat on harmful surfaces causes the game to crash
|
||||
bool creativePlayer = (source->getEntity() != NULL) && source->getEntity()->instanceof(eTYPE_PLAYER) && dynamic_pointer_cast<Player>(source->getEntity())->abilities.instabuild;
|
||||
|
||||
if (getDamage() > 20 * 2)
|
||||
if (creativePlayer || getDamage() > 20 * 2)
|
||||
{
|
||||
if (rider.lock() != NULL) rider.lock()->ride( shared_from_this() );
|
||||
spawnAtLocation(Item::boat_Id, 1, 0);
|
||||
if (!creativePlayer) spawnAtLocation(Item::boat_Id, 1, 0);
|
||||
remove();
|
||||
}
|
||||
return true;
|
||||
@@ -171,9 +173,9 @@ void Boat::lerpTo(double x, double y, double z, float yRot, float xRot, int step
|
||||
lyr = yRot;
|
||||
lxr = xRot;
|
||||
|
||||
this->xd = lxd;
|
||||
this->yd = lyd;
|
||||
this->zd = lzd;
|
||||
xd = lxd;
|
||||
yd = lyd;
|
||||
zd = lzd;
|
||||
}
|
||||
|
||||
void Boat::lerpMotion(double xd, double yd, double zd)
|
||||
@@ -247,8 +249,8 @@ void Boat::tick()
|
||||
xRot += (float) ( (lxr - xRot) / lSteps );
|
||||
|
||||
lSteps--;
|
||||
this->setPos(xt, yt, zt);
|
||||
this->setRot(yRot, xRot);
|
||||
setPos(xt, yt, zt);
|
||||
setRot(yRot, xRot);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -260,7 +262,7 @@ void Boat::tick()
|
||||
//this->setPos(xt, yt, zt);
|
||||
|
||||
// 4J Stu - Fix for various boat bugs, ensure that we check collision on client-side movement
|
||||
this->move(xd,yd,zd);
|
||||
move(xd,yd,zd);
|
||||
|
||||
if (onGround)
|
||||
{
|
||||
@@ -317,10 +319,18 @@ void Boat::tick()
|
||||
}
|
||||
|
||||
|
||||
if (rider.lock() != NULL)
|
||||
if ( rider.lock() != NULL && rider.lock()->instanceof(eTYPE_LIVINGENTITY) )
|
||||
{
|
||||
xd += rider.lock()->xd * acceleration;
|
||||
zd += rider.lock()->zd * acceleration;
|
||||
shared_ptr<LivingEntity> livingRider = dynamic_pointer_cast<LivingEntity>(rider.lock());
|
||||
double forward = livingRider->yya;
|
||||
|
||||
if (forward > 0)
|
||||
{
|
||||
double riderXd = -sin(livingRider->yRot * PI / 180);
|
||||
double riderZd = cos(livingRider->yRot * PI / 180);
|
||||
xd += riderXd * acceleration * 0.05f;
|
||||
zd += riderZd * acceleration * 0.05f;
|
||||
}
|
||||
}
|
||||
|
||||
double curSpeed = sqrt(xd * xd + zd * zd);
|
||||
@@ -355,7 +365,7 @@ void Boat::tick()
|
||||
|
||||
if ((horizontalCollision && lastSpeed > 0.20))
|
||||
{
|
||||
if (!level->isClientSide)
|
||||
if (!level->isClientSide && !removed)
|
||||
{
|
||||
remove();
|
||||
for (int i = 0; i < 3; i++)
|
||||
@@ -394,7 +404,7 @@ void Boat::tick()
|
||||
|
||||
if(level->isClientSide) return;
|
||||
|
||||
vector<shared_ptr<Entity> > *entities = level->getEntities(shared_from_this(), this->bb->grow(0.2f, 0, 0.2f));
|
||||
vector<shared_ptr<Entity> > *entities = level->getEntities(shared_from_this(), bb->grow(0.2f, 0, 0.2f));
|
||||
if (entities != NULL && !entities->empty())
|
||||
{
|
||||
AUTO_VAR(itEnd, entities->end());
|
||||
@@ -417,16 +427,14 @@ void Boat::tick()
|
||||
{
|
||||
int yy = Mth::floor(y) + j;
|
||||
int tile = level->getTile(xx, yy, zz);
|
||||
int data = level->getData(xx, yy, zz);
|
||||
|
||||
if (tile == Tile::topSnow_Id)
|
||||
{
|
||||
level->setTile(xx, yy, zz, 0);
|
||||
level->removeTile(xx, yy, zz);
|
||||
}
|
||||
else if (tile == Tile::waterLily_Id)
|
||||
{
|
||||
Tile::waterLily->spawnResources(level, xx, yy, zz, data, 0.3f, 0);
|
||||
level->setTile(xx, yy, zz, 0);
|
||||
level->destroyTile(xx, yy, zz, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +477,7 @@ wstring Boat::getName()
|
||||
|
||||
bool Boat::interact(shared_ptr<Player> player)
|
||||
{
|
||||
if (rider.lock() != NULL && dynamic_pointer_cast<Player>(rider.lock())!=NULL && rider.lock() != player) return true;
|
||||
if ( (rider.lock() != NULL) && rider.lock()->instanceof(eTYPE_PLAYER) && (rider.lock() != player) ) return true;
|
||||
if (!level->isClientSide)
|
||||
{
|
||||
// 4J HEG - Fixed issue with player not being able to dismount boat (issue #4446)
|
||||
@@ -478,14 +486,14 @@ bool Boat::interact(shared_ptr<Player> player)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Boat::setDamage(int damage)
|
||||
void Boat::setDamage(float damage)
|
||||
{
|
||||
entityData->set(DATA_ID_DAMAGE, damage);
|
||||
}
|
||||
|
||||
int Boat::getDamage()
|
||||
float Boat::getDamage()
|
||||
{
|
||||
return entityData->getInteger(DATA_ID_DAMAGE);
|
||||
return entityData->getFloat(DATA_ID_DAMAGE);
|
||||
}
|
||||
|
||||
void Boat::setHurtTime(int hurtTime)
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
Boat(Level *level, double x, double y, double z);
|
||||
|
||||
virtual double getRideHeight();
|
||||
virtual bool hurt(DamageSource *source, int damage);
|
||||
virtual bool hurt(DamageSource *source, float damage);
|
||||
virtual void animateHurt();
|
||||
virtual bool isPickable();
|
||||
|
||||
@@ -71,8 +71,8 @@ public:
|
||||
wstring getName();
|
||||
virtual bool interact(shared_ptr<Player> player);
|
||||
|
||||
virtual void setDamage(int damage);
|
||||
virtual int getDamage();
|
||||
virtual void setDamage(float damage);
|
||||
virtual float getDamage();
|
||||
virtual void setHurtTime(int hurtTime);
|
||||
virtual int getHurtTime();
|
||||
virtual void setHurtDir(int hurtDir);
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
|
||||
BoatItem::BoatItem(int id) : Item( id )
|
||||
{
|
||||
this->maxStackSize = 1;
|
||||
maxStackSize = 1;
|
||||
}
|
||||
|
||||
bool BoatItem::TestUse(Level *level, shared_ptr<Player> player)
|
||||
bool BoatItem::TestUse(shared_ptr<ItemInstance> itemInstance, Level *level, shared_ptr<Player> player)
|
||||
{
|
||||
// 4J-PB - added for tooltips to test use
|
||||
// 4J TODO really we should have the crosshair hitresult telling us if it hit water, and at what distance, so we don't need to do this again
|
||||
@@ -105,22 +105,28 @@ shared_ptr<ItemInstance> BoatItem::use(shared_ptr<ItemInstance> itemInstance, Le
|
||||
int yt = hr->y;
|
||||
int zt = hr->z;
|
||||
|
||||
if (!level->isClientSide)
|
||||
if (level->getTile(xt, yt, zt) == Tile::topSnow_Id) yt--;
|
||||
if( level->countInstanceOf(eTYPE_BOAT, true) < Level::MAX_XBOX_BOATS ) // 4J - added limit
|
||||
{
|
||||
if (level->getTile(xt, yt, zt) == Tile::topSnow_Id) yt--;
|
||||
if( level->countInstanceOf(eTYPE_BOAT, true) < Level::MAX_XBOX_BOATS ) // 4J - added limit
|
||||
shared_ptr<Boat> boat = shared_ptr<Boat>( new Boat(level, xt + 0.5f, yt + 1.0f, zt + 0.5f) );
|
||||
boat->yRot = ((Mth::floor(player->yRot * 4.0F / 360.0F + 0.5) & 0x3) - 1) * 90;
|
||||
if (!level->getCubes(boat, boat->bb->grow(-.1, -.1, -.1))->empty())
|
||||
{
|
||||
level->addEntity( shared_ptr<Boat>( new Boat(level, xt + 0.5f, yt + 1.0f, zt + 0.5f) ) );
|
||||
if (!player->abilities.instabuild)
|
||||
{
|
||||
itemInstance->count--;
|
||||
}
|
||||
return itemInstance;
|
||||
}
|
||||
else
|
||||
if (!level->isClientSide)
|
||||
{
|
||||
// display a message to say max boats has been hit
|
||||
player->displayClientMessage(IDS_MAX_BOATS );
|
||||
level->addEntity(boat);
|
||||
}
|
||||
if (!player->abilities.instabuild)
|
||||
{
|
||||
itemInstance->count--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// display a message to say max boats has been hit
|
||||
player->displayClientMessage(IDS_MAX_BOATS );
|
||||
}
|
||||
}
|
||||
delete hr;
|
||||
|
||||
@@ -11,7 +11,7 @@ public:
|
||||
|
||||
BoatItem(int id);
|
||||
|
||||
virtual bool TestUse(Level *level, shared_ptr<Player> player);
|
||||
virtual bool TestUse(shared_ptr<ItemInstance> itemInstance, Level *level, shared_ptr<Player> player);
|
||||
virtual shared_ptr<ItemInstance> use(shared_ptr<ItemInstance> itemInstance, Level *level, shared_ptr<Player> player);
|
||||
|
||||
/*
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
const float BodyControl::maxClampAngle = 75.0f;
|
||||
|
||||
BodyControl::BodyControl(Mob *mob)
|
||||
BodyControl::BodyControl(LivingEntity *mob)
|
||||
{
|
||||
this->mob = mob;
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
class BodyControl : public Control
|
||||
{
|
||||
private:
|
||||
Mob *mob;
|
||||
LivingEntity *mob;
|
||||
static const float maxClampAngle;
|
||||
int timeStill;
|
||||
float lastHeadY;
|
||||
|
||||
public:
|
||||
BodyControl(Mob *mob);
|
||||
BodyControl(LivingEntity *mob);
|
||||
|
||||
void clientTick();
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ bool BonusChestFeature::place(Level *level, Random *random, int x, int y, int z,
|
||||
y++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int x2, y2, z2;
|
||||
|
||||
@@ -45,7 +45,7 @@ bool BonusChestFeature::place(Level *level, Random *random, int x, int y, int z,
|
||||
{
|
||||
x2 = x;
|
||||
y2 = y - 1; // 4J - the position passed in is actually two above the top solid block, as the calling function adds 1 to getTopSolidBlock, and that actually returns the block above anyway.
|
||||
// this would explain why there is a while loop above here (not used in force mode) to move the y back down again, shouldn't really be needed if 1 wasn't added to the getTopSolidBlock return value.
|
||||
// this would explain why there is a while loop above here (not used in force mode) to move the y back down again, shouldn't really be needed if 1 wasn't added to the getTopSolidBlock return value.
|
||||
z2 = z;
|
||||
}
|
||||
else
|
||||
@@ -55,34 +55,34 @@ bool BonusChestFeature::place(Level *level, Random *random, int x, int y, int z,
|
||||
z2 = z + random->nextInt(4) - random->nextInt(4);
|
||||
}
|
||||
|
||||
if (force || ( level->isEmptyTile(x2, y2, z2) && level->isTopSolidBlocking(x2, y2 - 1, z2)))
|
||||
if (force || ( level->isEmptyTile(x2, y2, z2) && level->isTopSolidBlocking(x2, y2 - 1, z2)))
|
||||
{
|
||||
level->setTile(x2, y2, z2, Tile::chest_Id);
|
||||
shared_ptr<ChestTileEntity> chest = dynamic_pointer_cast<ChestTileEntity>(level->getTileEntity(x2, y2, z2));
|
||||
if (chest != NULL)
|
||||
level->setTileAndData(x2, y2, z2, Tile::chest_Id, 0, Tile::UPDATE_CLIENTS);
|
||||
shared_ptr<ChestTileEntity> chest = dynamic_pointer_cast<ChestTileEntity>(level->getTileEntity(x2, y2, z2));
|
||||
if (chest != NULL)
|
||||
{
|
||||
WeighedTreasure::addChestItems(random, treasureList, chest, numRolls);
|
||||
WeighedTreasure::addChestItems(random, treasureList, chest, numRolls);
|
||||
chest->isBonusChest = true; // 4J added
|
||||
}
|
||||
if (level->isEmptyTile(x2 - 1, y2, z2) && level->isTopSolidBlocking(x2 - 1, y2 - 1, z2))
|
||||
}
|
||||
if (level->isEmptyTile(x2 - 1, y2, z2) && level->isTopSolidBlocking(x2 - 1, y2 - 1, z2))
|
||||
{
|
||||
level->setTile(x2 - 1, y2, z2, Tile::torch_Id);
|
||||
}
|
||||
if (level->isEmptyTile(x2 + 1, y2, z2) && level->isTopSolidBlocking(x2 - 1, y2 - 1, z2))
|
||||
level->setTileAndData(x2 - 1, y2, z2, Tile::torch_Id, 0, Tile::UPDATE_CLIENTS);
|
||||
}
|
||||
if (level->isEmptyTile(x2 + 1, y2, z2) && level->isTopSolidBlocking(x2 - 1, y2 - 1, z2))
|
||||
{
|
||||
level->setTile(x2 + 1, y2, z2, Tile::torch_Id);
|
||||
}
|
||||
if (level->isEmptyTile(x2, y2, z2 - 1) && level->isTopSolidBlocking(x2 - 1, y2 - 1, z2))
|
||||
level->setTileAndData(x2 + 1, y2, z2, Tile::torch_Id, 0, Tile::UPDATE_CLIENTS);
|
||||
}
|
||||
if (level->isEmptyTile(x2, y2, z2 - 1) && level->isTopSolidBlocking(x2 - 1, y2 - 1, z2))
|
||||
{
|
||||
level->setTile(x2, y2, z2 - 1, Tile::torch_Id);
|
||||
}
|
||||
if (level->isEmptyTile(x2, y2, z2 + 1) && level->isTopSolidBlocking(x2 - 1, y2 - 1, z2))
|
||||
level->setTileAndData(x2, y2, z2 - 1, Tile::torch_Id, 0, Tile::UPDATE_CLIENTS);
|
||||
}
|
||||
if (level->isEmptyTile(x2, y2, z2 + 1) && level->isTopSolidBlocking(x2 - 1, y2 - 1, z2))
|
||||
{
|
||||
level->setTile(x2, y2, z2 + 1, Tile::torch_Id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
level->setTileAndData(x2, y2, z2 + 1, Tile::torch_Id, 0, Tile::UPDATE_CLIENTS);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "Mob.h"
|
||||
|
||||
class Level;
|
||||
class BossMobPart;
|
||||
|
||||
class BossMob : public Mob
|
||||
class BossMob
|
||||
{
|
||||
protected:
|
||||
int maxHealth;
|
||||
|
||||
public:
|
||||
BossMob(Level *level);
|
||||
|
||||
virtual int getMaxHealth();
|
||||
virtual bool hurt(shared_ptr<BossMobPart> bossMobPart, DamageSource *source, int damage);
|
||||
virtual bool hurt(DamageSource *source, int damage);
|
||||
|
||||
protected:
|
||||
virtual bool reallyHurt(DamageSource *source, int damage);
|
||||
virtual float getMaxHealth() = 0;
|
||||
virtual float getHealth() = 0;
|
||||
virtual wstring getAName() = 0;
|
||||
};
|
||||
@@ -31,7 +31,7 @@ shared_ptr<ItemInstance> BottleItem::use(shared_ptr<ItemInstance> itemInstance,
|
||||
{
|
||||
return itemInstance;
|
||||
}
|
||||
if (!player->mayBuild(xt, yt, zt))
|
||||
if (!player->mayUseItemAt(xt, yt, zt, hr->f, itemInstance))
|
||||
{
|
||||
return itemInstance;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ shared_ptr<ItemInstance> BottleItem::use(shared_ptr<ItemInstance> itemInstance,
|
||||
}
|
||||
|
||||
// 4J-PB - added to allow tooltips
|
||||
bool BottleItem::TestUse(Level *level, shared_ptr<Player> player)
|
||||
bool BottleItem::TestUse(shared_ptr<ItemInstance> itemInstance, Level *level, shared_ptr<Player> player)
|
||||
{
|
||||
HitResult *hr = getPlayerPOVHitResult(level, player, true);
|
||||
if (hr == NULL) return false;
|
||||
@@ -76,7 +76,7 @@ bool BottleItem::TestUse(Level *level, shared_ptr<Player> player)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!player->mayBuild(xt, yt, zt))
|
||||
if (!player->mayUseItemAt(xt, yt, zt, hr->f, itemInstance))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public:
|
||||
Icon *getIcon(int auxValue);
|
||||
|
||||
virtual shared_ptr<ItemInstance> use(shared_ptr<ItemInstance> itemInstance, Level *level, shared_ptr<Player> player);
|
||||
virtual bool TestUse(Level *level, shared_ptr<Player> player);
|
||||
virtual bool TestUse(shared_ptr<ItemInstance> itemInstance, Level *level, shared_ptr<Player> player);
|
||||
|
||||
//@Override
|
||||
void registerIcons(IconRegister *iconRegister);
|
||||
|
||||
@@ -14,6 +14,19 @@ BoundingBox::BoundingBox()
|
||||
z1 = 0;
|
||||
}
|
||||
|
||||
BoundingBox::BoundingBox(intArray sourceData)
|
||||
{
|
||||
if (sourceData.length == 6)
|
||||
{
|
||||
x0 = sourceData[0];
|
||||
y0 = sourceData[1];
|
||||
z0 = sourceData[2];
|
||||
x1 = sourceData[3];
|
||||
y1 = sourceData[4];
|
||||
z1 = sourceData[5];
|
||||
}
|
||||
}
|
||||
|
||||
BoundingBox *BoundingBox::getUnknownBox()
|
||||
{
|
||||
return new BoundingBox(INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MIN, INT_MIN );
|
||||
@@ -21,56 +34,56 @@ BoundingBox *BoundingBox::getUnknownBox()
|
||||
|
||||
BoundingBox *BoundingBox::orientBox(int footX, int footY, int footZ, int offX, int offY, int offZ, int width, int height, int depth, int orientation)
|
||||
{
|
||||
switch (orientation)
|
||||
switch (orientation)
|
||||
{
|
||||
default:
|
||||
return new BoundingBox(footX + offX, footY + offY, footZ + offZ, footX + width - 1 + offX, footY + height - 1 + offY, footZ + depth - 1 + offZ);
|
||||
default:
|
||||
return new BoundingBox(footX + offX, footY + offY, footZ + offZ, footX + width - 1 + offX, footY + height - 1 + offY, footZ + depth - 1 + offZ);
|
||||
case Direction::NORTH:
|
||||
// foot is at x0, y0, z1
|
||||
return new BoundingBox(footX + offX, footY + offY, footZ - depth + 1 + offZ, footX + width - 1 + offX, footY + height - 1 + offY, footZ + offZ);
|
||||
// foot is at x0, y0, z1
|
||||
return new BoundingBox(footX + offX, footY + offY, footZ - depth + 1 + offZ, footX + width - 1 + offX, footY + height - 1 + offY, footZ + offZ);
|
||||
case Direction::SOUTH:
|
||||
// foot is at x0, y0, z0
|
||||
return new BoundingBox(footX + offX, footY + offY, footZ + offZ, footX + width - 1 + offX, footY + height - 1 + offY, footZ + depth - 1 + offZ);
|
||||
// foot is at x0, y0, z0
|
||||
return new BoundingBox(footX + offX, footY + offY, footZ + offZ, footX + width - 1 + offX, footY + height - 1 + offY, footZ + depth - 1 + offZ);
|
||||
case Direction::WEST:
|
||||
// foot is at x1, y0, z0, but width and depth are flipped
|
||||
return new BoundingBox(footX - depth + 1 + offZ, footY + offY, footZ + offX, footX + offZ, footY + height - 1 + offY, footZ + width - 1 + offX);
|
||||
// foot is at x1, y0, z0, but width and depth are flipped
|
||||
return new BoundingBox(footX - depth + 1 + offZ, footY + offY, footZ + offX, footX + offZ, footY + height - 1 + offY, footZ + width - 1 + offX);
|
||||
case Direction::EAST:
|
||||
// foot is at x0, y0, z0, but width and depth are flipped
|
||||
return new BoundingBox(footX + offZ, footY + offY, footZ + offX, footX + depth - 1 + offZ, footY + height - 1 + offY, footZ + width - 1 + offX);
|
||||
}
|
||||
// foot is at x0, y0, z0, but width and depth are flipped
|
||||
return new BoundingBox(footX + offZ, footY + offY, footZ + offX, footX + depth - 1 + offZ, footY + height - 1 + offY, footZ + width - 1 + offX);
|
||||
}
|
||||
}
|
||||
|
||||
BoundingBox::BoundingBox(BoundingBox *other)
|
||||
{
|
||||
this->x0 = other->x0;
|
||||
this->y0 = other->y0;
|
||||
this->z0 = other->z0;
|
||||
this->x1 = other->x1;
|
||||
this->y1 = other->y1;
|
||||
this->z1 = other->z1;
|
||||
x0 = other->x0;
|
||||
y0 = other->y0;
|
||||
z0 = other->z0;
|
||||
x1 = other->x1;
|
||||
y1 = other->y1;
|
||||
z1 = other->z1;
|
||||
}
|
||||
|
||||
BoundingBox::BoundingBox(int x0, int y0, int z0, int x1, int y1, int z1)
|
||||
{
|
||||
this->x0 = x0;
|
||||
this->y0 = y0;
|
||||
this->z0 = z0;
|
||||
this->x1 = x1;
|
||||
this->y1 = y1;
|
||||
this->z1 = z1;
|
||||
this->x0 = x0;
|
||||
this->y0 = y0;
|
||||
this->z0 = z0;
|
||||
this->x1 = x1;
|
||||
this->y1 = y1;
|
||||
this->z1 = z1;
|
||||
}
|
||||
|
||||
BoundingBox::BoundingBox(int x0, int z0, int x1, int z1)
|
||||
{
|
||||
this->x0 = x0;
|
||||
this->z0 = z0;
|
||||
this->x1 = x1;
|
||||
this->z1 = z1;
|
||||
this->x0 = x0;
|
||||
this->z0 = z0;
|
||||
this->x1 = x1;
|
||||
this->z1 = z1;
|
||||
|
||||
// the bounding box for this constructor is limited to world size,
|
||||
// excluding bedrock level
|
||||
this->y0 = 1;
|
||||
this->y1 = 512;
|
||||
y0 = 1;
|
||||
y1 = 512;
|
||||
}
|
||||
|
||||
bool BoundingBox::intersects(BoundingBox *other)
|
||||
@@ -90,39 +103,39 @@ bool BoundingBox::intersects(int x0, int z0, int x1, int z1)
|
||||
|
||||
void BoundingBox::expand(BoundingBox *other)
|
||||
{
|
||||
this->x0 = Math::_min(this->x0, other->x0);
|
||||
this->y0 = Math::_min(this->y0, other->y0);
|
||||
this->z0 = Math::_min(this->z0, other->z0);
|
||||
this->x1 = Math::_max(this->x1, other->x1);
|
||||
this->y1 = Math::_max(this->y1, other->y1);
|
||||
this->z1 = Math::_max(this->z1, other->z1);
|
||||
x0 = Math::_min(x0, other->x0);
|
||||
y0 = Math::_min(y0, other->y0);
|
||||
z0 = Math::_min(z0, other->z0);
|
||||
x1 = Math::_max(x1, other->x1);
|
||||
y1 = Math::_max(y1, other->y1);
|
||||
z1 = Math::_max(z1, other->z1);
|
||||
}
|
||||
|
||||
BoundingBox *BoundingBox::getIntersection(BoundingBox *other)
|
||||
{
|
||||
if (!intersects(other))
|
||||
if (!intersects(other))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
BoundingBox *result = new BoundingBox();
|
||||
result->x0 = Math::_max(this->x0, other->x0);
|
||||
result->y0 = Math::_max(this->y0, other->y0);
|
||||
result->z0 = Math::_max(this->z0, other->z0);
|
||||
result->x1 = Math::_min(this->x1, other->x1);
|
||||
result->y1 = Math::_min(this->y1, other->y1);
|
||||
result->z1 = Math::_min(this->z1, other->z1);
|
||||
return NULL;
|
||||
}
|
||||
BoundingBox *result = new BoundingBox();
|
||||
result->x0 = Math::_max(x0, other->x0);
|
||||
result->y0 = Math::_max(y0, other->y0);
|
||||
result->z0 = Math::_max(z0, other->z0);
|
||||
result->x1 = Math::_min(x1, other->x1);
|
||||
result->y1 = Math::_min(y1, other->y1);
|
||||
result->z1 = Math::_min(z1, other->z1);
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
void BoundingBox::move(int dx, int dy, int dz)
|
||||
{
|
||||
x0 += dx;
|
||||
y0 += dy;
|
||||
z0 += dz;
|
||||
x1 += dx;
|
||||
y1 += dy;
|
||||
z1 += dz;
|
||||
x0 += dx;
|
||||
y0 += dy;
|
||||
z0 += dz;
|
||||
x1 += dx;
|
||||
y1 += dy;
|
||||
z1 += dz;
|
||||
}
|
||||
|
||||
bool BoundingBox::isInside(int x, int y, int z)
|
||||
@@ -163,4 +176,14 @@ int BoundingBox::getZCenter()
|
||||
wstring BoundingBox::toString()
|
||||
{
|
||||
return L"(" + _toString<int>(x0) + L", " + _toString<int>(y0) + L", " + _toString<int>(z0) + L"; " + _toString<int>(x1) + L", " + _toString<int>(y1) + L", " + _toString<int>(z1) + L")";
|
||||
}
|
||||
|
||||
IntArrayTag *BoundingBox::createTag(const wstring &name)
|
||||
{
|
||||
// 4J-JEV: If somebody knows a better way to do this, please tell me.
|
||||
int *data = new int[6]();
|
||||
data[0] = x0; data[1] = y0; data[2] = z0;
|
||||
data[3] = x1; data[4] = y1; data[5] = z1;
|
||||
|
||||
return new IntArrayTag( name, intArray(data,6) );
|
||||
}
|
||||
@@ -1,11 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "ArrayWithLength.h"
|
||||
|
||||
class BoundingBox
|
||||
{
|
||||
public:
|
||||
int x0, y0, z0, x1, y1, z1;
|
||||
|
||||
BoundingBox();
|
||||
BoundingBox(intArray sourceData);
|
||||
static BoundingBox *getUnknownBox();
|
||||
static BoundingBox *orientBox(int footX, int footY, int footZ, int offX, int offY, int offZ, int width, int height, int depth, int orientation);
|
||||
BoundingBox(BoundingBox *other);
|
||||
@@ -28,4 +31,5 @@ public:
|
||||
int getZCenter();
|
||||
|
||||
wstring toString();
|
||||
IntArrayTag *createTag(const wstring &name);
|
||||
};
|
||||
@@ -46,9 +46,9 @@ void BowItem::releaseUsing(shared_ptr<ItemInstance> itemInstance, Level *level,
|
||||
{
|
||||
arrow->setOnFire(100);
|
||||
}
|
||||
itemInstance->hurt(1, player);
|
||||
itemInstance->hurtAndBreak(1, player);
|
||||
|
||||
level->playSound(player, eSoundType_RANDOM_BOW, 1.0f, 1 / (random->nextFloat() * 0.4f + 1.2f) + pow * 0.5f);
|
||||
level->playEntitySound(player, eSoundType_RANDOM_BOW, 1.0f, 1 / (random->nextFloat() * 0.4f + 1.2f) + pow * 0.5f);
|
||||
|
||||
if (infiniteArrows)
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ BreakDoorGoal::BreakDoorGoal(Mob *mob) : DoorInteractGoal(mob)
|
||||
bool BreakDoorGoal::canUse()
|
||||
{
|
||||
if (!DoorInteractGoal::canUse()) return false;
|
||||
if (!mob->level->getGameRules()->getBoolean(GameRules::RULE_MOBGRIEFING)) return false;
|
||||
return !doorTile->isOpen(mob->level, doorX, doorY, doorZ);
|
||||
}
|
||||
|
||||
@@ -57,7 +58,7 @@ void BreakDoorGoal::tick()
|
||||
{
|
||||
if (mob->level->difficulty == Difficulty::HARD)
|
||||
{
|
||||
mob->level->setTile(doorX, doorY, doorZ, 0);
|
||||
mob->level->removeTile(doorX, doorY, doorZ);
|
||||
mob->level->levelEvent(LevelEvent::SOUND_ZOMBIE_DOOR_CRASH, doorX, doorY, doorZ, 0);
|
||||
mob->level->levelEvent(LevelEvent::PARTICLES_DESTROY_BLOCK, doorX, doorY, doorZ, doorTile->id);
|
||||
}
|
||||
|
||||
@@ -4,19 +4,20 @@
|
||||
#include "net.minecraft.world.entity.animal.h"
|
||||
#include "net.minecraft.world.level.h"
|
||||
#include "net.minecraft.world.phys.h"
|
||||
#include "BasicTypeContainers.h"
|
||||
#include "BreedGoal.h"
|
||||
#include "ExperienceOrb.h"
|
||||
|
||||
#include "GenericStats.h"
|
||||
|
||||
BreedGoal::BreedGoal(Animal *animal, float speed)
|
||||
BreedGoal::BreedGoal(Animal *animal, double speedModifier)
|
||||
{
|
||||
partner = weak_ptr<Animal>();
|
||||
loveTime = 0;
|
||||
|
||||
this->animal = animal;
|
||||
this->level = animal->level;
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
setRequiredControlFlags(Control::MoveControlFlag | Control::LookControlFlag);
|
||||
}
|
||||
|
||||
@@ -41,26 +42,28 @@ void BreedGoal::stop()
|
||||
void BreedGoal::tick()
|
||||
{
|
||||
animal->getLookControl()->setLookAt(partner.lock(), 10, animal->getMaxHeadXRot());
|
||||
animal->getNavigation()->moveTo(partner.lock(), speed);
|
||||
animal->getNavigation()->moveTo(partner.lock(), speedModifier);
|
||||
++loveTime;
|
||||
if (loveTime == 20 * 3) breed();
|
||||
if (loveTime >= 20 * 3 && animal->distanceToSqr(partner.lock()) < 3*3) breed();
|
||||
}
|
||||
|
||||
shared_ptr<Animal> BreedGoal::getFreePartner()
|
||||
{
|
||||
float r = 8;
|
||||
vector<shared_ptr<Entity> > *others = level->getEntitiesOfClass(typeid(*animal), animal->bb->grow(r, r, r));
|
||||
double dist = Double::MAX_VALUE;
|
||||
shared_ptr<Animal> partner = nullptr;
|
||||
for(AUTO_VAR(it, others->begin()); it != others->end(); ++it)
|
||||
{
|
||||
shared_ptr<Animal> p = dynamic_pointer_cast<Animal>(*it);
|
||||
if (animal->canMate(p))
|
||||
if (animal->canMate(p) && animal->distanceToSqr(p) < dist)
|
||||
{
|
||||
delete others;
|
||||
return p;
|
||||
partner = p;
|
||||
dist = animal->distanceToSqr(p);
|
||||
}
|
||||
}
|
||||
delete others;
|
||||
return nullptr;
|
||||
return partner;
|
||||
}
|
||||
|
||||
void BreedGoal::breed()
|
||||
@@ -97,7 +100,7 @@ void BreedGoal::breed()
|
||||
partner.lock()->setAge(5 * 60 * 20);
|
||||
animal->resetLove();
|
||||
partner.lock()->resetLove();
|
||||
offspring->setAge(-20 * 60 * 20);
|
||||
offspring->setAge(AgableMob::BABY_START_AGE);
|
||||
offspring->moveTo(animal->x, animal->y, animal->z, 0, 0);
|
||||
offspring->setDespawnProtected();
|
||||
level->addEntity(offspring);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user