Make objects fall through the planet and warp around the edges
Make objects visible and active across planet edgesmaster
parent
d20b830575
commit
62465fd158
|
@ -272,12 +272,13 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
|||
|
||||
bool any_position_valid = false;
|
||||
|
||||
int planet_circumference = ceil(g_settings->getU16("planet_radius") * M_PI) * 2 * MAP_BLOCKSIZE;
|
||||
|
||||
v3s16 p;
|
||||
for (p.X = min.X; p.X <= max.X; p.X++)
|
||||
for (p.Y = min.Y; p.Y <= max.Y; p.Y++)
|
||||
for (p.Z = min.Z; p.Z <= max.Z; p.Z++) {
|
||||
if (g_settings->getBool("planet_enable")) {
|
||||
int planet_circumference = ceil(g_settings->getU16("planet_radius") * M_PI) * 2 * MAP_BLOCKSIZE;
|
||||
if (p.X >= planet_circumference / 2) p.X -= planet_circumference;
|
||||
if (p.Z >= planet_circumference / 2) p.Z -= planet_circumference;
|
||||
if (p.X < -planet_circumference / 2) p.X += planet_circumference;
|
||||
|
|
|
@ -738,7 +738,38 @@ void GenericCAO::updateNodePos()
|
|||
|
||||
if (node) {
|
||||
v3s16 camera_offset = m_env->getCameraOffset();
|
||||
node->setPosition(pos_translator.vect_show - intToFloat(camera_offset, BS));
|
||||
/*
|
||||
* Planet: Since the planet is actually just a flat map that wraps around
|
||||
* a seemingly spherical object, there are 9 possible minimal distances to
|
||||
* the same object, because the end of the map on one side is the beginning
|
||||
* of the map on the other side again. Find the minimal distance from the player
|
||||
* to this object.
|
||||
*/
|
||||
if (!g_settings->getBool("planet_enable")) {
|
||||
node->setPosition(pos_translator.vect_show - intToFloat(camera_offset, BS));
|
||||
} else {
|
||||
v3s16 cam_pos_nodes = floatToInt(m_client->getCamera()->getPosition(), BS);
|
||||
|
||||
// Round planet circumference up to even number of mapblocks, in nodes
|
||||
int planet_circumference = ceil(g_settings->getU16("planet_radius") * M_PI) * 2 * MAP_BLOCKSIZE;
|
||||
|
||||
float mindist = (cam_pos_nodes - floatToInt(m_position, BS)).getLength();
|
||||
int offset_minimal_x = 0, offset_minimal_z = 0;
|
||||
for (int wrapx = -1; wrapx <= 1; ++wrapx)
|
||||
for (int wrapz = -1; wrapz <= 1; ++wrapz) {
|
||||
float distx = cam_pos_nodes.X - (m_position.X / BS + wrapx * planet_circumference);
|
||||
float distz = cam_pos_nodes.Z - (m_position.Z / BS + wrapz * planet_circumference);
|
||||
float dist = sqrt(distx * distx + distz * distz);
|
||||
|
||||
if (dist < mindist) {
|
||||
mindist = dist;
|
||||
offset_minimal_x = wrapx * planet_circumference;
|
||||
offset_minimal_z = wrapz * planet_circumference;
|
||||
}
|
||||
}
|
||||
node->setPosition(pos_translator.vect_show - intToFloat(camera_offset, BS) + v3f(offset_minimal_x * BS, 0, offset_minimal_z * BS));
|
||||
}
|
||||
|
||||
if (node != m_spritenode) { // rotate if not a sprite
|
||||
v3f rot = node->getRotation();
|
||||
rot.Y = -m_yaw;
|
||||
|
|
|
@ -373,6 +373,33 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
|||
m_velocity += dtime * m_acceleration;
|
||||
}
|
||||
|
||||
/*
|
||||
Handle Planet
|
||||
*/
|
||||
if (g_settings->getBool("planet_enable")) {
|
||||
int planet_radius = g_settings->getU16("planet_radius") * MAP_BLOCKSIZE * BS;
|
||||
int planet_circumference = ceil(g_settings->getU16("planet_radius") * M_PI) * 2 * MAP_BLOCKSIZE * BS;
|
||||
|
||||
// Teleport items to other side of planet at planet edges
|
||||
if (m_base_position.X > planet_circumference / 2 - 0.5 * BS)
|
||||
m_base_position.X = -(float)planet_circumference / 2 - 0.5 * BS;
|
||||
if (m_base_position.X < -planet_circumference / 2 - 0.5 * BS)
|
||||
m_base_position.X = (float)planet_circumference / 2 - 0.5 * BS;
|
||||
if (m_base_position.Z > planet_circumference / 2 - 0.5 * BS)
|
||||
m_base_position.Z = -(float)planet_circumference / 2 - 0.5 * BS;
|
||||
if (m_base_position.Z < -planet_circumference / 2 - 0.5 * BS)
|
||||
m_base_position.Z = (float)planet_circumference / 2 - 0.5 * BS;
|
||||
|
||||
// Make objects fall through the planet center
|
||||
if (g_settings->getBool("planet_fallthrough_enable")) {
|
||||
if (m_base_position.Y < -planet_radius) {
|
||||
m_base_position.Y = -planet_radius + BS;
|
||||
m_base_position.X += planet_circumference / 2. * (m_base_position.X < 0 ? 1 : -1);
|
||||
m_velocity.Y *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_prop.automatic_face_movement_dir &&
|
||||
(fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001)) {
|
||||
|
||||
|
|
|
@ -279,6 +279,10 @@ void LBMManager::applyLBMs(ServerEnvironment *env, MapBlock *block, u32 stamp)
|
|||
|
||||
void fillRadiusBlock(v3s16 p0, s16 r, std::set<v3s16> &list)
|
||||
{
|
||||
bool planet_enable = g_settings->getBool("planet_enable");
|
||||
int planet_radius = g_settings->getU16("planet_radius");
|
||||
int planet_circumference = ceil(g_settings->getU16("planet_radius") * M_PI) * 2;
|
||||
|
||||
v3s16 p;
|
||||
for(p.X=p0.X-r; p.X<=p0.X+r; p.X++)
|
||||
for(p.Y=p0.Y-r; p.Y<=p0.Y+r; p.Y++)
|
||||
|
@ -287,7 +291,26 @@ void fillRadiusBlock(v3s16 p0, s16 r, std::set<v3s16> &list)
|
|||
// limit to a sphere
|
||||
if (p.getDistanceFrom(p0) <= r) {
|
||||
// Set in list
|
||||
list.insert(p);
|
||||
// Activate blocks across planet edges, insert in list
|
||||
if (planet_enable) {
|
||||
v3s16 ppos = p;
|
||||
if (ppos.X >= planet_circumference / 2)
|
||||
ppos.X -= planet_circumference;
|
||||
if (ppos.X < -planet_circumference / 2)
|
||||
ppos.X += planet_circumference;
|
||||
if (ppos.Z >= planet_circumference / 2)
|
||||
ppos.Z -= planet_circumference;
|
||||
if (ppos.Z < -planet_circumference / 2)
|
||||
ppos.Z += planet_circumference;
|
||||
if (ppos.Y < -planet_radius) {
|
||||
ppos.Y = -planet_radius - ppos.Y;
|
||||
ppos.X += planet_circumference / 2 * (ppos.X < 0 ? 1 : -1);
|
||||
}
|
||||
|
||||
list.insert(ppos);
|
||||
} else {
|
||||
list.insert(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1483,6 +1506,9 @@ void ServerEnvironment::getAddedActiveObjects(PlayerSAO *playersao, s16 radius,
|
|||
|
||||
if (player_radius_f < 0)
|
||||
player_radius_f = 0;
|
||||
|
||||
bool planet_enable = g_settings->getBool("planet_enable");
|
||||
int planet_circumference = ceil(g_settings->getU16("planet_radius") * M_PI) * 2 * MAP_BLOCKSIZE * BS;
|
||||
/*
|
||||
Go through the object list,
|
||||
- discard removed/deactivated objects,
|
||||
|
@ -1503,6 +1529,19 @@ void ServerEnvironment::getAddedActiveObjects(PlayerSAO *playersao, s16 radius,
|
|||
|
||||
f32 distance_f = object->getBasePosition().
|
||||
getDistanceFrom(playersao->getBasePosition());
|
||||
|
||||
// Distances on the planet are different, calculate distance across edges
|
||||
if (planet_enable) {
|
||||
for (int wrapx = -1; wrapx <= 1; ++wrapx)
|
||||
for (int wrapz = -1; wrapz <= 1; ++wrapz) {
|
||||
float dist = object->getBasePosition().getDistanceFrom(
|
||||
v3f(playersao->getBasePosition() - v3f(wrapx, 0, wrapz) * planet_circumference));
|
||||
|
||||
if (dist < distance_f)
|
||||
distance_f = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if (object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
|
||||
// Discard if too far
|
||||
if (distance_f > player_radius_f && player_radius_f != 0)
|
||||
|
@ -1534,6 +1573,9 @@ void ServerEnvironment::getRemovedActiveObjects(PlayerSAO *playersao, s16 radius
|
|||
|
||||
if (player_radius_f < 0)
|
||||
player_radius_f = 0;
|
||||
|
||||
bool planet_enable = g_settings->getBool("planet_enable");
|
||||
int planet_circumference = ceil(g_settings->getU16("planet_radius") * M_PI) * 2 * MAP_BLOCKSIZE * BS;
|
||||
/*
|
||||
Go through current_objects; object is removed if:
|
||||
- object is not found in m_active_objects (this is actually an
|
||||
|
@ -1558,6 +1600,19 @@ void ServerEnvironment::getRemovedActiveObjects(PlayerSAO *playersao, s16 radius
|
|||
}
|
||||
|
||||
f32 distance_f = object->getBasePosition().getDistanceFrom(playersao->getBasePosition());
|
||||
|
||||
// Distances on the planet are different, calculate distance across edges
|
||||
if (planet_enable) {
|
||||
for (int wrapx = -1; wrapx <= 1; ++wrapx)
|
||||
for (int wrapz = -1; wrapz <= 1; ++wrapz) {
|
||||
float dist = object->getBasePosition().getDistanceFrom(
|
||||
v3f(playersao->getBasePosition() - v3f(wrapx, 0, wrapz) * planet_circumference));
|
||||
|
||||
if (dist < distance_f)
|
||||
distance_f = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if (object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
|
||||
if (distance_f <= player_radius_f || player_radius_f == 0)
|
||||
continue;
|
||||
|
|
Loading…
Reference in New Issue