the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 527 lines 11 kB view raw
1#include "stdafx.h" 2#include "com.mojang.nbt.h" 3#include "net.minecraft.world.entity.h" 4#include "net.minecraft.world.entity.player.h" 5#include "net.minecraft.world.item.h" 6#include "net.minecraft.world.level.h" 7#include "net.minecraft.world.level.material.h" 8#include "net.minecraft.world.level.tile.h" 9#include "net.minecraft.world.phys.h" 10#include "net.minecraft.world.damagesource.h" 11#include "Boat.h" 12 13const double Boat::MAX_SPEED = 0.35; 14const double Boat::MAX_COLLISION_SPEED = MAX_SPEED * 0.75; 15const double Boat::MIN_ACCELERATION = 0.07; 16const double Boat::MAX_ACCELERATION = 0.35; 17 18// 4J - added for common ctor code 19void Boat::_init() 20{ 21 doLerp = true; 22 acceleration = MIN_ACCELERATION; 23 24 lSteps = 0; 25 lx = ly = lz = lyr = lxr = 0.0; 26 lxd = lyd = lzd = 0.0; 27 28 blocksBuilding = true; 29 setSize(1.5f, 0.6f); 30 heightOffset = bbHeight / 2.0f; 31 32 // 4J Stu - This function call had to be moved here from the Entity ctor to ensure that 33 // the derived version of the function is called 34 this->defineSynchedData(); 35} 36 37 38 39Boat::Boat(Level *level) : Entity( level ) 40{ 41 42 _init(); 43} 44 45 46bool Boat::makeStepSound() 47{ 48 return false; 49} 50 51void Boat::defineSynchedData() 52{ 53 entityData->define(DATA_ID_HURT, 0); 54 entityData->define(DATA_ID_HURTDIR, 1); 55 entityData->define(DATA_ID_DAMAGE, 0.0f); 56} 57 58 59AABB *Boat::getCollideAgainstBox(shared_ptr<Entity> entity) 60{ 61 return entity->bb; 62} 63 64AABB *Boat::getCollideBox() 65{ 66 return bb; 67} 68 69bool Boat::isPushable() 70{ 71 return true; 72} 73 74Boat::Boat(Level *level, double x, double y, double z) : Entity( level ) 75{ 76 _init(); 77 setPos(x, y + heightOffset, z); 78 79 xd = 0; 80 yd = 0; 81 zd = 0; 82 83 xo = x; 84 yo = y; 85 zo = z; 86} 87 88double Boat::getRideHeight() 89{ 90 return bbHeight * 0.0f - 0.3f; 91} 92 93bool Boat::hurt(DamageSource *source, float hurtDamage) 94{ 95 if (isInvulnerable()) return false; 96 if (level->isClientSide || removed) return true; 97 98 // 4J-JEV: Fix for #88212, 99 // Untrusted players shouldn't be able to damage minecarts or boats. 100 if (dynamic_cast<EntityDamageSource *>(source) != NULL) 101 { 102 shared_ptr<Entity> attacker = source->getDirectEntity(); 103 104 if ( attacker->instanceof(eTYPE_PLAYER) && !dynamic_pointer_cast<Player>(attacker)->isAllowedToHurtEntity( shared_from_this() )) 105 { 106 return false; 107 } 108 } 109 110 setHurtDir(-getHurtDir()); 111 setHurtTime(10); 112 113 // 4J Stu - If someone is riding in this, then it can tick multiple times which causes the damage to 114 // decrease too quickly. So just make the damage a bit higher to start with for similar behaviour 115 // to an unridden one. Only do this change if the riding player is attacking it. 116 if( rider.lock() != NULL && rider.lock() == source->getEntity() ) hurtDamage += 1; 117 118 setDamage(getDamage() + hurtDamage * 10); 119 markHurt(); 120 121 // 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 122 // 4J-PB - Fix for XB1 #175735 - [CRASH] [Multi-Plat]: Code: Gameplay: Placing a boat on harmful surfaces causes the game to crash 123 bool creativePlayer = (source->getEntity() != NULL) && source->getEntity()->instanceof(eTYPE_PLAYER) && dynamic_pointer_cast<Player>(source->getEntity())->abilities.instabuild; 124 125 if (creativePlayer || getDamage() > 20 * 2) 126 { 127 if (rider.lock() != NULL) rider.lock()->ride( shared_from_this() ); 128 if (!creativePlayer) spawnAtLocation(Item::boat_Id, 1, 0); 129 remove(); 130 } 131 return true; 132} 133 134void Boat::animateHurt() 135{ 136 setHurtDir(-getHurtDir()); 137 setHurtTime(10); 138 setDamage(getDamage() * 11); 139} 140 141bool Boat::isPickable() 142{ 143 return !removed; 144} 145 146 147void Boat::lerpTo(double x, double y, double z, float yRot, float xRot, int steps) 148{ 149 if (doLerp) 150 { 151 lSteps = steps + 5; 152 } 153 else 154 { 155 double xdiff = x - this->x; 156 double ydiff = y - this->y; 157 double zdiff = z - this->z; 158 double diff = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; 159 160 if (diff > 1) 161 { 162 lSteps = 3; 163 } 164 else 165 { 166 return; 167 } 168 } 169 170 lx = x; 171 ly = y; 172 lz = z; 173 lyr = yRot; 174 lxr = xRot; 175 176 xd = lxd; 177 yd = lyd; 178 zd = lzd; 179} 180 181void Boat::lerpMotion(double xd, double yd, double zd) 182{ 183 lxd = this->xd = xd; 184 lyd = this->yd = yd; 185 lzd = this->zd = zd; 186} 187 188void Boat::tick() 189{ 190 Entity::tick(); 191 if (getHurtTime() > 0) setHurtTime(getHurtTime() - 1); 192 if (getDamage() > 0) setDamage(getDamage() - 1); 193 xo = x; 194 yo = y; 195 zo = z; 196 197 198 int steps = 5; 199 double waterPercentage = 0; 200 for (int i = 0; i < steps; i++) 201 { 202 double y0 = bb->y0 + (bb->y1 - bb->y0) * (i + 0) / steps - 2 / 16.0f; 203 double y1 = bb->y0 + (bb->y1 - bb->y0) * (i + 1) / steps - 2 / 16.0f; 204 AABB *bb2 = AABB::newTemp(bb->x0, y0, bb->z0, bb->x1, y1, bb->z1); 205 if (level->containsLiquid(bb2, Material::water)) 206 { 207 waterPercentage += 1.0 / steps; 208 } 209 } 210 211 double lastSpeed = sqrt(xd * xd + zd * zd); 212 if (lastSpeed > MAX_COLLISION_SPEED) 213 { 214 double xa = cos(yRot * PI / 180); 215 double za = sin(yRot * PI / 180); 216 217 for (int i = 0; i < 1 + lastSpeed * 60; i++) 218 { 219 220 double side = (random->nextFloat() * 2 - 1); 221 222 double side2 = (random->nextInt(2) * 2 - 1) * 0.7; 223 if (random->nextBoolean()) 224 { 225 double xx = x - xa * side * 0.8 + za * side2; 226 double zz = z - za * side * 0.8 - xa * side2; 227 level->addParticle(eParticleType_splash, xx, y - 2 / 16.0f, zz, +xd, yd, +zd); 228 } 229 else 230 { 231 double xx = x + xa + za * side * 0.7; 232 double zz = z + za - xa * side * 0.7; 233 level->addParticle(eParticleType_splash, xx, y - 2 / 16.0f, zz, +xd, yd, +zd); 234 } 235 } 236 } 237 238 if (level->isClientSide && doLerp) 239 { 240 if (lSteps > 0) 241 { 242 double xt = x + (lx - x) / lSteps; 243 double yt = y + (ly - y) / lSteps; 244 double zt = z + (lz - z) / lSteps; 245 246 double yrd = Mth::wrapDegrees(lyr - yRot); 247 248 yRot += (float) ( (yrd) / lSteps ); 249 xRot += (float) ( (lxr - xRot) / lSteps ); 250 251 lSteps--; 252 setPos(xt, yt, zt); 253 setRot(yRot, xRot); 254 } 255 else 256 { 257#if 1 258 // Original 259 //double xt = x + xd; 260 //double yt = y + yd; 261 //double zt = z + zd; 262 //this->setPos(xt, yt, zt); 263 264 // 4J Stu - Fix for various boat bugs, ensure that we check collision on client-side movement 265 move(xd,yd,zd); 266 267 if (onGround) 268 { 269 xd *= 0.5f; 270 yd *= 0.5f; 271 zd *= 0.5f; 272 } 273 xd *= 0.99f; 274 yd *= 0.95f; 275 zd *= 0.99f; 276#else 277 // 4J Stu - Fix for #8280 - Gameplay : Boats behave erratically when exited next to land. 278 // The client shouldn't change the position of the boat 279 double xt = x;// + xd; 280 double yt = y + yd; 281 double zt = z;// + zd; 282 this->setPos(xt, yt, zt); 283 284 // 4J Stu - Fix for #9579 - GAMEPLAY: Boats with a player in them slowly sink under the water over time, and with no player in them they float into the sky. 285 // Just make the boats bob up and down rather than any other client-side movement when not receiving packets from server 286 if (waterPercentage < 1) 287 { 288 double bob = waterPercentage * 2 - 1; 289 yd += 0.04f * bob; 290 } 291 else 292 { 293 if (yd < 0) yd /= 2; 294 yd += 0.007f; 295 } 296 //if (onGround) 297 //{ 298 xd *= 0.5f; 299 yd *= 0.5f; 300 zd *= 0.5f; 301 //} 302 //xd *= 0.99f; 303 //yd *= 0.95f; 304 //zd *= 0.99f; 305#endif 306 } 307 return; 308 } 309 310 if (waterPercentage < 1) 311 { 312 double bob = waterPercentage * 2 - 1; 313 yd += 0.04f * bob; 314 } 315 else 316 { 317 if (yd < 0) yd /= 2; 318 yd += 0.007f; 319 } 320 321 322 if ( rider.lock() != NULL && rider.lock()->instanceof(eTYPE_LIVINGENTITY) ) 323 { 324 shared_ptr<LivingEntity> livingRider = dynamic_pointer_cast<LivingEntity>(rider.lock()); 325 double forward = livingRider->yya; 326 327 if (forward > 0) 328 { 329 double riderXd = -sin(livingRider->yRot * PI / 180); 330 double riderZd = cos(livingRider->yRot * PI / 180); 331 xd += riderXd * acceleration * 0.05f; 332 zd += riderZd * acceleration * 0.05f; 333 } 334 } 335 336 double curSpeed = sqrt(xd * xd + zd * zd); 337 338 if (curSpeed > MAX_SPEED) 339 { 340 double ratio = MAX_SPEED / curSpeed; 341 342 xd *= ratio; 343 zd *= ratio; 344 curSpeed = MAX_SPEED; 345 } 346 347 if (curSpeed > lastSpeed && acceleration < MAX_ACCELERATION) 348 { 349 acceleration += (MAX_ACCELERATION - acceleration) / 35; 350 if (acceleration > MAX_ACCELERATION) acceleration = MAX_ACCELERATION; 351 } 352 else 353 { 354 acceleration -= (acceleration - MIN_ACCELERATION) / 35; 355 if (acceleration < MIN_ACCELERATION) acceleration = MIN_ACCELERATION; 356 } 357 358 if (onGround) 359 { 360 xd *= 0.5f; 361 yd *= 0.5f; 362 zd *= 0.5f; 363 } 364 move(xd, yd, zd); 365 366 if ((horizontalCollision && lastSpeed > 0.20)) 367 { 368 if (!level->isClientSide && !removed) 369 { 370 remove(); 371 for (int i = 0; i < 3; i++) 372 { 373 spawnAtLocation(Tile::wood_Id, 1, 0); 374 } 375 for (int i = 0; i < 2; i++) 376 { 377 spawnAtLocation(Item::stick->id, 1, 0); 378 } 379 } 380 } 381 else 382 { 383 xd *= 0.99f; 384 yd *= 0.95f; 385 zd *= 0.99f; 386 } 387 388 xRot = 0; 389 double yRotT = yRot; 390 double xDiff = xo - x; 391 double zDiff = zo - z; 392 if (xDiff * xDiff + zDiff * zDiff > 0.001) 393 { 394 yRotT = (float) (atan2(zDiff, xDiff) * 180 / PI); 395 } 396 397 double rotDiff = Mth::wrapDegrees(yRotT - yRot); 398 399 if (rotDiff > 20) rotDiff = 20; 400 if (rotDiff < -20) rotDiff = -20; 401 402 yRot += (float) rotDiff; 403 setRot(yRot, xRot); 404 405 if(level->isClientSide) return; 406 407 vector<shared_ptr<Entity> > *entities = level->getEntities(shared_from_this(), bb->grow(0.2f, 0, 0.2f)); 408 if (entities != NULL && !entities->empty()) 409 { 410 AUTO_VAR(itEnd, entities->end()); 411 for (AUTO_VAR(it, entities->begin()); it != itEnd; it++) 412 { 413 shared_ptr<Entity> e = (*it); // entities->at(i); 414 if (e != rider.lock() && e->isPushable() && e->GetType() == eTYPE_BOAT) 415 { 416 e->push(shared_from_this()); 417 } 418 } 419 } 420 421 for (int i = 0; i < 4; i++) 422 { 423 int xx = Mth::floor(x + ((i % 2) - 0.5) * 0.8); 424 int zz = Mth::floor(z + ((i / 2) - 0.5) * 0.8); 425 426 for (int j = 0; j < 2; j++) 427 { 428 int yy = Mth::floor(y) + j; 429 int tile = level->getTile(xx, yy, zz); 430 431 if (tile == Tile::topSnow_Id) 432 { 433 level->removeTile(xx, yy, zz); 434 } 435 else if (tile == Tile::waterLily_Id) 436 { 437 level->destroyTile(xx, yy, zz, true); 438 } 439 } 440 441 } 442 443 if (rider.lock() != NULL) 444 { 445 if (rider.lock()->removed) rider = weak_ptr<Entity>(); 446 } 447} 448 449void Boat::positionRider() 450{ 451 if (rider.lock() == NULL) return; 452 453 double xa = cos(yRot * PI / 180) * 0.4; 454 double za = sin(yRot * PI / 180) * 0.4; 455 rider.lock()->setPos(x + xa, y + getRideHeight() + rider.lock()->getRidingHeight(), z + za); 456} 457 458 459void Boat::addAdditonalSaveData(CompoundTag *base) 460{ 461} 462 463void Boat::readAdditionalSaveData(CompoundTag *base) 464{ 465} 466 467 468float Boat::getShadowHeightOffs() 469{ 470 return 0; 471} 472 473wstring Boat::getName() 474{ 475 return L"Boat"; 476} 477 478bool Boat::interact(shared_ptr<Player> player) 479{ 480 if ( (rider.lock() != NULL) && rider.lock()->instanceof(eTYPE_PLAYER) && (rider.lock() != player) ) return true; 481 if (!level->isClientSide) 482 { 483 // 4J HEG - Fixed issue with player not being able to dismount boat (issue #4446) 484 player->ride( rider.lock() == player ? nullptr : shared_from_this() ); 485 } 486 return true; 487} 488 489void Boat::setDamage(float damage) 490{ 491 entityData->set(DATA_ID_DAMAGE, damage); 492} 493 494float Boat::getDamage() 495{ 496 return entityData->getFloat(DATA_ID_DAMAGE); 497} 498 499void Boat::setHurtTime(int hurtTime) 500{ 501 entityData->set(DATA_ID_HURT, hurtTime); 502} 503 504int Boat::getHurtTime() 505{ 506 return entityData->getInteger(DATA_ID_HURT); 507} 508 509void Boat::setHurtDir(int hurtDir) 510{ 511 entityData->set(DATA_ID_HURTDIR, hurtDir); 512} 513 514int Boat::getHurtDir() 515{ 516 return entityData->getInteger(DATA_ID_HURTDIR); 517} 518 519bool Boat::getDoLerp() 520{ 521 return doLerp; 522} 523 524void Boat::setDoLerp(bool doLerp) 525{ 526 this->doLerp = doLerp; 527}