the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 528 lines 12 kB view raw
1#include "stdafx.h" 2#include "net.minecraft.world.entity.h" 3#include "net.minecraft.world.level.h" 4#include "net.minecraft.world.level.tile.h" 5#include "net.minecraft.world.level.dimension.h" 6#include "..\Minecraft.Client\ServerLevel.h" 7#include "PortalForcer.h" 8 9PortalForcer::PortalPosition::PortalPosition(int x, int y, int z, __int64 time) : Pos(x, y, z) 10{ 11 lastUsed = time; 12} 13 14PortalForcer::PortalForcer(ServerLevel *level) 15{ 16 this->level = level; 17 random = new Random(level->getSeed()); 18} 19 20PortalForcer::~PortalForcer() 21{ 22 for(AUTO_VAR(it,cachedPortals.begin()); it != cachedPortals.end(); ++it) 23 { 24 delete it->second; 25 } 26} 27 28void PortalForcer::force(shared_ptr<Entity> e, double xOriginal, double yOriginal, double zOriginal, float yRotOriginal) 29{ 30 if (level->dimension->id == 1) 31 { 32 int x = Mth::floor(e->x); 33 int y = Mth::floor(e->y) - 1; 34 int z = Mth::floor(e->z); 35 36 int xa = 1; 37 int za = 0; 38 for (int b = -2; b <= 2; b++) 39 { 40 for (int s = -2; s <= 2; s++) 41 { 42 for (int h = -1; h < 3; h++) 43 { 44 int xt = x + s * xa + b * za; 45 int yt = y + h; 46 int zt = z + s * za - b * xa; 47 48 bool border = h < 0; 49 50 level->setTileAndUpdate(xt, yt, zt, border ? Tile::obsidian_Id : 0); 51 } 52 } 53 } 54 55 e->moveTo(x, y, z, e->yRot, 0); 56 e->xd = e->yd = e->zd = 0; 57 58 return; 59 } 60 61 if (findPortal(e, xOriginal, yOriginal, zOriginal, yRotOriginal)) 62 { 63 return; 64 } 65 66 createPortal(e); 67 findPortal(e, xOriginal, yOriginal, zOriginal, yRotOriginal); 68} 69 70 71bool PortalForcer::findPortal(shared_ptr<Entity> e, double xOriginal, double yOriginal, double zOriginal, float yRotOriginal) 72{ 73 // 4J Stu - Decrease the range at which we search for a portal in the nether given our smaller nether 74 int r = 16;//* 8; 75 if(level->dimension->id == -1) 76 { 77 r *= 3; 78 } 79 else 80 { 81#ifdef __PSVITA__ 82 // AP poor little Vita takes 30 seconds to leave the Nether. This should help 83 r *= 5; 84#else 85 r *= 8; 86#endif 87 } 88 double closest = -1; 89 int xTarget = 0; 90 int yTarget = 0; 91 int zTarget = 0; 92 93 int xc = Mth::floor(e->x); 94 int zc = Mth::floor(e->z); 95 96 long hash = ChunkPos::hashCode(xc, zc); 97 bool updateCache = true; 98 99 AUTO_VAR(it, cachedPortals.find(hash)); 100 if (it != cachedPortals.end()) 101 { 102 PortalPosition *pos = it->second; 103 104 closest = 0; 105 xTarget = pos->x; 106 yTarget = pos->y; 107 zTarget = pos->z; 108 pos->lastUsed = level->getGameTime(); 109 updateCache = false; 110 } 111 else 112 { 113 for (int x = xc - r; x <= xc + r; x++) 114 { 115 double xd = (x + 0.5) - e->x; 116 for (int z = zc - r; z <= zc + r; z++) 117 { 118 double zd = (z + 0.5) - e->z; 119 for (int y = level->getHeight() - 1; y >= 0; y--) 120 { 121 if (level->getTile(x, y, z) == Tile::portalTile_Id) 122 { 123 while (level->getTile(x, y - 1, z) == Tile::portalTile_Id) 124 { 125 y--; 126 } 127 128 double yd = (y + 0.5) - e->y; 129 double dist = xd * xd + yd * yd + zd * zd; 130 if (closest < 0 || dist < closest) 131 { 132 closest = dist; 133 xTarget = x; 134 yTarget = y; 135 zTarget = z; 136 } 137 } 138 } 139 } 140 } 141 } 142 143 if (closest >= 0) 144 { 145 int x = xTarget; 146 int y = yTarget; 147 int z = zTarget; 148 149 if (updateCache) 150 { 151 cachedPortals[hash] = new PortalPosition(x, y, z, level->getGameTime()); 152 cachedPortalKeys.push_back(hash); 153 } 154 155 double xt = x + 0.5; 156 double yt = y + 0.5; 157 double zt = z + 0.5; 158 int dir = Direction::UNDEFINED; 159 160 if (level->getTile(x - 1, y, z) == Tile::portalTile_Id) dir = Direction::NORTH; 161 if (level->getTile(x + 1, y, z) == Tile::portalTile_Id) dir = Direction::SOUTH; 162 if (level->getTile(x, y, z - 1) == Tile::portalTile_Id) dir = Direction::EAST; 163 if (level->getTile(x, y, z + 1) == Tile::portalTile_Id) dir = Direction::WEST; 164 165 int originalDir = e->getPortalEntranceDir(); 166 167 if (dir > Direction::UNDEFINED) 168 { 169 int leftDir = Direction::DIRECTION_COUNTER_CLOCKWISE[dir]; 170 int forwardsx = Direction::STEP_X[dir]; 171 int forwardsz = Direction::STEP_Z[dir]; 172 int leftx = Direction::STEP_X[leftDir]; 173 int leftz = Direction::STEP_Z[leftDir]; 174 175 bool leftBlocked = !level->isEmptyTile(x + forwardsx + leftx, y, z + forwardsz + leftz) || !level->isEmptyTile(x + forwardsx + leftx, y + 1, z + forwardsz + leftz); 176 bool rightBlocked = !level->isEmptyTile(x + forwardsx, y, z + forwardsz) || !level->isEmptyTile(x + forwardsx, y + 1, z + forwardsz); 177 178 if (leftBlocked && rightBlocked) 179 { 180 dir = Direction::DIRECTION_OPPOSITE[dir]; 181 leftDir = Direction::DIRECTION_OPPOSITE[leftDir]; 182 forwardsx = Direction::STEP_X[dir]; 183 forwardsz = Direction::STEP_Z[dir]; 184 leftx = Direction::STEP_X[leftDir]; 185 leftz = Direction::STEP_Z[leftDir]; 186 187 x -= leftx; 188 xt -= leftx; 189 z -= leftz; 190 zt -= leftz; 191 leftBlocked = !level->isEmptyTile(x + forwardsx + leftx, y, z + forwardsz + leftz) || !level->isEmptyTile(x + forwardsx + leftx, y + 1, z + forwardsz + leftz); 192 rightBlocked = !level->isEmptyTile(x + forwardsx, y, z + forwardsz) || !level->isEmptyTile(x + forwardsx, y + 1, z + forwardsz); 193 } 194 195 float offsetLeft = 0.5f; 196 float offsetForwards = 0.5f; 197 198 if (!leftBlocked && rightBlocked) 199 { 200 offsetLeft = 1; 201 } 202 else if (leftBlocked && !rightBlocked) 203 { 204 offsetLeft = 0; 205 } 206 else if (leftBlocked && rightBlocked) 207 { 208 offsetForwards = 0; 209 } 210 211 // Center them in the frame and push them out forwards 212 xt += (leftx * offsetLeft) + (offsetForwards * forwardsx); 213 zt += (leftz * offsetLeft) + (offsetForwards * forwardsz); 214 215 float xx = 0; 216 float zz = 0; 217 float xz = 0; 218 float zx = 0; 219 220 if (dir == originalDir) 221 { 222 xx = 1; 223 zz = 1; 224 } 225 else if (dir == Direction::DIRECTION_OPPOSITE[originalDir]) 226 { 227 xx = -1; 228 zz = -1; 229 } 230 else if (dir == Direction::DIRECTION_CLOCKWISE[originalDir]) 231 { 232 xz = 1; 233 zx = -1; 234 } 235 else 236 { 237 xz = -1; 238 zx = 1; 239 } 240 241 double xd = e->xd; 242 double zd = e->zd; 243 e->xd = xd * xx + zd * zx; 244 e->zd = xd * xz + zd * zz; 245 e->yRot = (yRotOriginal - originalDir * 90) + (dir * 90); 246 } 247 else 248 { 249 e->xd = e->yd = e->zd = 0; 250 } 251 252 e->moveTo(xt, yt, zt, e->yRot, e->xRot); 253 return true; 254 } 255 256 return false; 257} 258 259 260bool PortalForcer::createPortal(shared_ptr<Entity> e) 261{ 262 // 4J Stu - Increase the range at which we try and create a portal to stop creating them floating in mid air over lava 263 int r = 16 * 3; 264 double closest = -1; 265 266 int xc = Mth::floor(e->x); 267 int yc = Mth::floor(e->y); 268 int zc = Mth::floor(e->z); 269 270 // 4J Stu - Changes to stop Portals being created at the border of the nether inside the bedrock 271 int XZSIZE = level->dimension->getXZSize() * 16; // XZSize is chunks, convert to blocks 272 int XZOFFSET = (XZSIZE / 2) - 4; // Subtract 4 to stay away from the edges // TODO Make the 4 a constant in HellRandomLevelSource 273 274 // Move the positions that we want to check away from the edge of the world 275 if( (xc - r) < -XZOFFSET ) 276 { 277 app.DebugPrintf("Adjusting portal creation x due to being too close to the edge\n"); 278 xc -= ( (xc - r) + XZOFFSET); 279 } 280 else if ( (xc + r) >= XZOFFSET ) 281 { 282 app.DebugPrintf("Adjusting portal creation x due to being too close to the edge\n"); 283 xc -= ( (xc + r) - XZOFFSET); 284 } 285 if( (zc - r) < -XZOFFSET ) 286 { 287 app.DebugPrintf("Adjusting portal creation z due to being too close to the edge\n"); 288 zc -= ( (zc - r) + XZOFFSET); 289 } 290 else if ( (zc + r) >= XZOFFSET ) 291 { 292 app.DebugPrintf("Adjusting portal creation z due to being too close to the edge\n"); 293 zc -= ( (zc + r) - XZOFFSET); 294 } 295 296 int xTarget = xc; 297 int yTarget = yc; 298 int zTarget = zc; 299 int dirTarget = 0; 300 301 int dirOffs = random->nextInt(4); 302 303 { 304 for (int x = xc - r; x <= xc + r; x++) 305 { 306 double xd = (x + 0.5) - e->x; 307 for (int z = zc - r; z <= zc + r; z++) 308 { 309 double zd = (z + 0.5) - e->z; 310 311 for (int y = level->getHeight() - 1; y >= 0; y--) 312 { 313 if (level->isEmptyTile(x, y, z)) 314 { 315 while (y>0 && level->isEmptyTile(x, y - 1, z)) 316 { 317 y--; 318 } 319 320 for (int dir = dirOffs; dir < dirOffs + 4; dir++) 321 { 322 int xa = dir % 2; 323 int za = 1 - xa; 324 325 if (dir % 4 >= 2) 326 { 327 xa = -xa; 328 za = -za; 329 } 330 331 332 for (int b = 0; b < 3; b++) 333 { 334 for (int s = 0; s < 4; s++) 335 { 336 for (int h = -1; h < 4; h++) 337 { 338 int xt = x + (s - 1) * xa + b * za; 339 int yt = y + h; 340 int zt = z + (s - 1) * za - b * xa; 341 342 // 4J Stu - Changes to stop Portals being created at the border of the nether inside the bedrock 343 if( ( xt < -XZOFFSET ) || ( xt >= XZOFFSET ) || ( zt < -XZOFFSET ) || ( zt >= XZOFFSET ) ) 344 { 345 app.DebugPrintf("Skipping possible portal location as at least one block is too close to the edge\n"); 346 goto next_first; 347 } 348 349 if (h < 0 && !level->getMaterial(xt, yt, zt)->isSolid()) goto next_first; 350 if (h >= 0 && !level->isEmptyTile(xt, yt, zt)) goto next_first; 351 } 352 } 353 } 354 355 double yd = (y + 0.5) - e->y; 356 double dist = xd * xd + yd * yd + zd * zd; 357 if (closest < 0 || dist < closest) 358 { 359 closest = dist; 360 xTarget = x; 361 yTarget = y; 362 zTarget = z; 363 dirTarget = dir % 4; 364 } 365 } 366 } 367next_first: continue; 368 } 369 } 370 } 371 } 372 if (closest < 0) 373 { 374 for (int x = xc - r; x <= xc + r; x++) 375 { 376 double xd = (x + 0.5) - e->x; 377 for (int z = zc - r; z <= zc + r; z++) 378 { 379 double zd = (z + 0.5) - e->z; 380 381 for (int y = level->getHeight() - 1; y >= 0; y--) 382 { 383 if (level->isEmptyTile(x, y, z)) 384 { 385 while (y > 0 && level->isEmptyTile(x, y - 1, z)) 386 { 387 y--; 388 } 389 390 for (int dir = dirOffs; dir < dirOffs + 2; dir++) 391 { 392 int xa = dir % 2; 393 int za = 1 - xa; 394 for (int s = 0; s < 4; s++) 395 { 396 for (int h = -1; h < 4; h++) 397 { 398 int xt = x + (s - 1) * xa; 399 int yt = y + h; 400 int zt = z + (s - 1) * za; 401 402 // 4J Stu - Changes to stop Portals being created at the border of the nether inside the bedrock 403 if( ( xt < -XZOFFSET ) || ( xt >= XZOFFSET ) || ( zt < -XZOFFSET ) || ( zt >= XZOFFSET ) ) 404 { 405 app.DebugPrintf("Skipping possible portal location as at least one block is too close to the edge\n"); 406 goto next_second; 407 } 408 409 if (h < 0 && !level->getMaterial(xt, yt, zt)->isSolid()) goto next_second; 410 if (h >= 0 && !level->isEmptyTile(xt, yt, zt)) goto next_second; 411 } 412 } 413 414 double yd = (y + 0.5) - e->y; 415 double dist = xd * xd + yd * yd + zd * zd; 416 if (closest < 0 || dist < closest) 417 { 418 closest = dist; 419 xTarget = x; 420 yTarget = y; 421 zTarget = z; 422 dirTarget = dir % 2; 423 } 424 } 425 } 426next_second: continue; 427 } 428 } 429 } 430 } 431 432 433 434 int dir = dirTarget; 435 436 int x = xTarget; 437 int y = yTarget; 438 int z = zTarget; 439 440 int xa = dir % 2; 441 int za = 1 - xa; 442 443 if (dir % 4 >= 2) 444 { 445 xa = -xa; 446 za = -za; 447 } 448 449 450 if (closest < 0) 451 { 452 if (yTarget < 70) yTarget = 70; 453 if (yTarget > level->getHeight() - 10) yTarget = level->getHeight() - 10; 454 y = yTarget; 455 456 for (int b = -1; b <= 1; b++) 457 { 458 for (int s = 1; s < 3; s++) 459 { 460 for (int h = -1; h < 3; h++) 461 { 462 int xt = x + (s - 1) * xa + b * za; 463 int yt = y + h; 464 int zt = z + (s - 1) * za - b * xa; 465 466 bool border = h < 0; 467 468 level->setTileAndUpdate(xt, yt, zt, border ? Tile::obsidian_Id : 0); 469 } 470 } 471 } 472 } 473 474 for (int pass = 0; pass < 4; pass++) 475 { 476 for (int s = 0; s < 4; s++) 477 { 478 for (int h = -1; h < 4; h++) 479 { 480 int xt = x + (s - 1) * xa; 481 int yt = y + h; 482 int zt = z + (s - 1) * za; 483 484 bool border = s == 0 || s == 3 || h == -1 || h == 3; 485 level->setTileAndData(xt, yt, zt, border ? Tile::obsidian_Id : Tile::portalTile_Id, 0, Tile::UPDATE_CLIENTS); 486 } 487 } 488 489 for (int s = 0; s < 4; s++) 490 { 491 for (int h = -1; h < 4; h++) 492 { 493 int xt = x + (s - 1) * xa; 494 int yt = y + h; 495 int zt = z + (s - 1) * za; 496 497 level->updateNeighborsAt(xt, yt, zt, level->getTile(xt, yt, zt)); 498 } 499 } 500 } 501 502 return true; 503} 504 505void PortalForcer::tick(__int64 time) 506{ 507 if (time % (SharedConstants::TICKS_PER_SECOND * 5) == 0) 508 { 509 __int64 cutoff = time - SharedConstants::TICKS_PER_SECOND * 30; 510 511 for(AUTO_VAR(it,cachedPortalKeys.begin()); it != cachedPortalKeys.end();) 512 { 513 __int64 key = *it; 514 PortalPosition *pos = cachedPortals[key]; 515 516 if (pos == NULL || pos->lastUsed < cutoff) 517 { 518 delete pos; 519 it = cachedPortalKeys.erase(it); 520 cachedPortals.erase(key); 521 } 522 else 523 { 524 ++it; 525 } 526 } 527 } 528}