diff --git a/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.cpp index b9664c9d..02e7c0fe 100644 --- a/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.cpp +++ b/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.cpp @@ -916,7 +916,7 @@ void IUIScene_CraftingMenu::UpdateHighlight() // special case for the torch coal/charcoal int id=pTempItemInstAdditional->getDescriptionId(); - LPCWSTR itemstring; + wstring itemstring; switch(id) { @@ -945,11 +945,15 @@ void IUIScene_CraftingMenu::UpdateHighlight() } break; default: - itemstring=app.GetString(id ); + if (pTempItemInstAdditional->hasCustomHoverName()) { + itemstring = pTempItemInstAdditional->getHoverName(); + } else { + itemstring = app.GetString(id); + } break; } - setItemText(itemstring); + setItemText(itemstring.c_str()); } else { diff --git a/Minecraft.Client/ServerPlayer.cpp b/Minecraft.Client/ServerPlayer.cpp index 5f8c5e48..cd321df0 100644 --- a/Minecraft.Client/ServerPlayer.cpp +++ b/Minecraft.Client/ServerPlayer.cpp @@ -850,8 +850,10 @@ void ServerPlayer::die(DamageSource *source) bool ServerPlayer::hurt(DamageSource *dmgSource, float dmg) { - if (isInvulnerable()) return false; - if (gameMode == nullptr||gameMode->isCreative()) return false; + if (isInvulnerable() && dmgSource != DamageSource::outOfWorld) return false; + if (gameMode == nullptr || gameMode->isCreative()) { + if (dmgSource != DamageSource::outOfWorld) return false; + } // 4J: Not relevant to console servers // Allow falldamage on dedicated pvpservers -- so people cannot cheat their way out of 'fall traps' diff --git a/Minecraft.Client/TrackedEntity.cpp b/Minecraft.Client/TrackedEntity.cpp index bd475097..7a12ce9a 100644 --- a/Minecraft.Client/TrackedEntity.cpp +++ b/Minecraft.Client/TrackedEntity.cpp @@ -290,24 +290,53 @@ void TrackedEntity::tick(EntityTracker *tracker, vector > *pl wasRiding = false; } else - { - bool rot = abs(yRotn - yRotp) >= TOLERANCE_LEVEL || abs(xRotn - xRotp) >= TOLERANCE_LEVEL; - if (rot) - { - // 4J: Changed this to use deltas - broadcast(std::make_shared(e->entityId, static_cast(yRota), static_cast(xRota))); - yRotp = yRotn; - xRotp = xRotn; - } +{ + // the entity have a rider, the code didnt send position updates, + // causing desync between client and server when boat was spritning. - xp = Mth::floor(e->x * 32.0); - yp = Mth::floor(e->y * 32.0); - zp = Mth::floor(e->z * 32.0); + bool rot = abs(yRotn - yRotp) >= TOLERANCE_LEVEL || abs(xRotn - xRotp) >= TOLERANCE_LEVEL; + if (rot) + { + + broadcast(std::make_shared(e->entityId, static_cast(yRota), static_cast(xRota))); + yRotp = yRotn; + xRotp = xRotn; + } - sendDirtyEntityData(); + int xn = Mth::floor(e->x * 32.0); + int yn = Mth::floor(e->y * 32.0); + int zn = Mth::floor(e->z * 32.0); + int xa = xn - xp; + int ya = yn - yp; + int za = zn - zp; - wasRiding = true; - } + // send only if the boat moved enough + // or 3 seconds periodically + bool pos = abs(xa) >= TOLERANCE_LEVEL || abs(ya) >= TOLERANCE_LEVEL || abs(za) >= TOLERANCE_LEVEL + || (tickCount % (SharedConstants::TICKS_PER_SECOND * 3) == 0); + + if (pos) + { + // if deltapos is too much big use teleport. + if (xa < -128 || xa >= 128 || ya < -128 || ya >= 128 || za < -128 || za >= 128) + { + broadcast(std::make_shared(e->entityId, xn, yn, zn, + static_cast(yRotn), static_cast(xRotn))); + } + else + { + // small movement, delta + broadcast(std::make_shared(e->entityId, + static_cast(xa), static_cast(ya), static_cast(za))); + } + xp = xn; + yp = yn; + zp = zn; + } + + sendDirtyEntityData(); + wasRiding = true; +} int yHeadRot = Mth::floor(e->getYHeadRot() * 256 / 360); if (abs(yHeadRot - yHeadRotp) >= TOLERANCE_LEVEL) diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index 178bda48..d9415cb2 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -149,47 +149,57 @@ static void CopyWideArgToAnsi(LPCWSTR source, char* dest, size_t destSize) dest[destSize - 1] = 0; } -// ---------- Persistent options (options.txt next to exe) ---------- -static void GetOptionsFilePath(char *out, size_t outSize) +// ---------- Persistent options (options.dat next to exe) ---------- +static void GetOptionsFilePath(char *out, DWORD outSize) { - GetModuleFileNameA(nullptr, out, static_cast(outSize)); - char *p = strrchr(out, '\\'); - if (p) *(p + 1) = '\0'; - strncat_s(out, outSize, "options.txt", _TRUNCATE); + GetModuleFileNameA(nullptr, out, outSize); + char *p = strrchr(out, '\\'); + if (p) *(p + 1) = '\0'; + strncat_s(out, outSize, "settings.dat", _TRUNCATE); } static void SaveFullscreenOption(bool fullscreen) { - char path[MAX_PATH]; - GetOptionsFilePath(path, sizeof(path)); - FILE *f = nullptr; - if (fopen_s(&f, path, "w") == 0 && f) - { - fprintf(f, "fullscreen=%d\n", fullscreen ? 1 : 0); - fclose(f); - } + GAME_SETTINGS settings = {}; + + char path[MAX_PATH] = {}; + GetOptionsFilePath(path, MAX_PATH); + FILE *f = nullptr; + if (fopen_s(&f, path, "rb") == 0 && f) + { + fread(&settings, sizeof(GAME_SETTINGS), 1, f); + fclose(f); + } + + if (fullscreen) + settings.uiBitmaskValues |= (1UL << 25); + else + settings.uiBitmaskValues &= ~(1UL << 25); + + if (fopen_s(&f, path, "wb") == 0 && f) + { + fwrite(&settings, sizeof(GAME_SETTINGS), 1, f); + fclose(f); + } } static bool LoadFullscreenOption() { - char path[MAX_PATH]; + char path[MAX_PATH] = {}; GetOptionsFilePath(path, sizeof(path)); - FILE *f = nullptr; - if (fopen_s(&f, path, "r") == 0 && f) - { - char line[256]; - while (fgets(line, sizeof(line), f)) - { - int val = 0; - if (sscanf_s(line, "fullscreen=%d", &val) == 1) - { - fclose(f); - return val != 0; - } - } - fclose(f); - } - return false; + + FILE *f = nullptr; + if (fopen_s(&f, path, "rb") != 0 || !f) + return false; + + GAME_SETTINGS current = {}; + bool ok = (fread(¤t, sizeof(GAME_SETTINGS), 1, f) == 1); + fclose(f); + + if (!ok) + return false; + + return (current.uiBitmaskValues & (1UL << 25)) != 0; } // ------------------------------------------------------------------ @@ -824,7 +834,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) return FALSE; } - + return TRUE; } @@ -1696,11 +1706,12 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, CleanupDevice(); return 0; } - // Restore fullscreen state from previous session. Route through the // deferred exclusive fullscreen path so the main loop applies it on the // first tick (safer than transitioning during init). - if ((LoadFullscreenOption() && !g_isFullscreen) || launchOptions.fullscreen) + + bool FullScreenEnabled = LoadFullscreenOption(); + if (FullScreenEnabled && !g_isFullscreen) { g_bPendingExclusiveFullscreen = true; g_bPendingExclusiveFullscreenValue = true; @@ -1765,7 +1776,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, return 1; } g_bResizeReady = true; - + //app.TemporaryCreateGameStart(); //Sleep(10000); diff --git a/Minecraft.World/BlockPos.cpp b/Minecraft.World/BlockPos.cpp index 13703c50..c48496cc 100644 --- a/Minecraft.World/BlockPos.cpp +++ b/Minecraft.World/BlockPos.cpp @@ -8,7 +8,7 @@ const BlockPos BlockPos::ZERO = BlockPos(0, 0, 0); -// Costruttori + BlockPos::BlockPos() : Vec3i(0, 0, 0) {} BlockPos::BlockPos(int x, int y, int z) : Vec3i(x, y, z) {} @@ -49,7 +49,7 @@ BlockPos::BlockPos(int compressed) : Vec3i(0, 0, 0) { BlockPos::BlockPos(BlockSource& source) : Vec3i(source.getBlockX(), source.getBlockY(), source.getBlockZ()) {} -// Metodi di confronto + bool BlockPos::equals(const BlockPos& other) const { return x == other.x && y == other.y && z == other.z; } @@ -88,7 +88,7 @@ BlockPos BlockPos::relative(int direction, int distance) const { return BlockPos(x + dx, y, z + dz); } -// Metodi direzionali +// directional methods BlockPos BlockPos::above(int distance) const { return BlockPos(x, y + distance, z); } @@ -119,7 +119,7 @@ BlockPos BlockPos::multiply(int factor) const { return BlockPos(x * factor, y * factor, z * factor); } -// Compressione +// compression int BlockPos::compress() const { static const int MASK_X = (1 << BITS_X) - 1; static const int MASK_Y = (1 << BITS_Y) - 1; diff --git a/Minecraft.World/Boat.cpp b/Minecraft.World/Boat.cpp index 3d5ac6e7..faaca25d 100644 --- a/Minecraft.World/Boat.cpp +++ b/Minecraft.World/Boat.cpp @@ -148,7 +148,7 @@ void Boat::lerpTo(double x, double y, double z, float yRot, float xRot, int step { if (doLerp) { - lSteps = steps + 5; + lSteps = steps +5; } else { @@ -188,6 +188,10 @@ void Boat::lerpMotion(double xd, double yd, double zd) void Boat::tick() { Entity::tick(); + + + + if (getHurtTime() > 0) setHurtTime(getHurtTime() - 1); if (getDamage() > 0) setDamage(getDamage() - 1); xo = x; @@ -199,8 +203,8 @@ void Boat::tick() double waterPercentage = 0; for (int i = 0; i < steps; i++) { - double y0 = bb->y0 + (bb->y1 - bb->y0) * (i + 0) / steps - 2 / 16.0f; - double y1 = bb->y0 + (bb->y1 - bb->y0) * (i + 1) / steps - 2 / 16.0f; + double y0 = bb->y0 + (bb->y1 - bb->y0) * (i + 0) / steps + 1.5f / 16.0f; + double y1 = bb->y0 + (bb->y1 - bb->y0) * (i + 1) / steps + 1.5f / 16.0f; AABB *bb2 = AABB::newTemp(bb->x0, y0, bb->z0, bb->x1, y1, bb->z1); if (level->containsLiquid(bb2, Material::water)) { @@ -257,18 +261,19 @@ void Boat::tick() return; } - // Bob in water - if (waterPercentage > 0) + // Bob in water & gravity + if (waterPercentage < 1.0) { - double bob = waterPercentage * 2 - 1; + double bob = waterPercentage * 2.0 - 1.0; yd += 0.04f * bob; } - - // Reimplement gravity again (??) - int tileUnder = level->getTile(Mth::floor(x), Mth::floor(y-0.15), Mth::floor(z)); - if (tileUnder == 0 && !onGround) + else { - yd -= 0.04f; + if (yd < 0.0) + { + yd /= 2.0; + } + yd += 0.007f; } // Rider controls @@ -281,24 +286,16 @@ void Boat::tick() { double riderXd = -sin(livingRider->yRot * PI / 180); double riderZd = cos(livingRider->yRot * PI / 180); - float mult = livingRider->isSprinting() ? 2.0f : 1.0f; + double currentSpeed = sqrt(xd * xd + zd * zd); float moveFactor = (float)forward; if (forward < 0) moveFactor *= 0.5f; // Move slower backwards - xd += riderXd * acceleration * 0.05f * mult * moveFactor; - zd += riderZd * acceleration * 0.05f * mult * moveFactor; + xd += riderXd * acceleration * 0.05f * moveFactor; + zd += riderZd * acceleration * 0.05f * moveFactor; } } double curSpeed = sqrt(xd * xd + zd * zd); double maxSpeed = MAX_SPEED; - if (rider.lock() != nullptr && rider.lock()->instanceof(eTYPE_LIVINGENTITY)) - { - shared_ptr livingRider = dynamic_pointer_cast(rider.lock()); - if (livingRider->isSprinting()) - { - maxSpeed *= 1.5; - } - } if (curSpeed > maxSpeed) { @@ -330,10 +327,12 @@ void Boat::tick() move(xd, yd, zd); // Break boat on high speed collision + float breakThreshold = (rider.lock() != nullptr) ? 0.35f : 0.20f; if ((horizontalCollision && lastSpeed > 0.20)) { if (!level->isClientSide && !removed) { + remove(); for (int i = 0; i < 3; i++) { @@ -343,6 +342,9 @@ void Boat::tick() { spawnAtLocation(Item::stick->id, 1, 0); } + + + } } else @@ -472,10 +474,19 @@ bool Boat::interact(shared_ptr player) if ( (rider.lock() != nullptr) && rider.lock()->instanceof(eTYPE_PLAYER) && (rider.lock() != player) ) return true; if (!level->isClientSide) { + bool isRiding = (rider.lock() == player); + + if (isRiding) + { + + player->xd = 0; + player->yd = 0; + player->zd = 0; + } // 4J HEG - Fixed issue with player not being able to dismount boat (issue #4446) - player->ride( rider.lock() == player ? nullptr : shared_from_this() ); - } - return true; + player->ride(isRiding ? nullptr : shared_from_this()); + } + return true; } void Boat::setDamage(float damage) diff --git a/Minecraft.World/ClothDyeRecipes.cpp b/Minecraft.World/ClothDyeRecipes.cpp index b12461a7..d934ca43 100644 --- a/Minecraft.World/ClothDyeRecipes.cpp +++ b/Minecraft.World/ClothDyeRecipes.cpp @@ -116,6 +116,9 @@ void ClothDyeRecipes::addRecipes(Recipes *r) new ItemInstance(Item::dye, 1, DyePowderItem::RED), new ItemInstance(Item::dye, 1, DyePowderItem::WHITE),L'D'); + + + for (int i = 0; i < 16; i++) { r->addShapedRecipy(new ItemInstance(Tile::woolCarpet, 3, i), diff --git a/Minecraft.World/Ocelot.cpp b/Minecraft.World/Ocelot.cpp index 926215be..c0255938 100644 --- a/Minecraft.World/Ocelot.cpp +++ b/Minecraft.World/Ocelot.cpp @@ -199,7 +199,7 @@ bool Ocelot::mobInteract(shared_ptr player) } else { - if (temptGoal->isRunning() && item != nullptr && item->id == Item::fish_Id && player->distanceToSqr(shared_from_this()) < 3 * 3) + if (/*temptGoal->isRunning() &&*/ item != nullptr && item->id == Item::fish_Id && player->distanceToSqr(shared_from_this()) < 3 * 3) { // 4J-PB - don't lose the fish in creative mode if (!player->abilities.instabuild) item->count--;